2

I've been given the task to implement the following using WCF REST:

Resource       POST                GET           PUT                  DELETE
/device        Create new device   List devices  Bulk update devices  Delete all devices

This isn't a problem per-se, but the problem is that all these functions need different parameters. For example, the POST method takes a WSDevice, while the GET method takes a WSCollectionQuery as parameter (used for querying well .. collections). All 4 methods take different parameters, but have to be accessible through the /device Uri.

This should be possible in REST (according to http://pages.apigee.com/web-api-design-ebook-thank-you-download.html?aliId=1911411 , where I got the table from in the first place. See page 7).

What I currently have:

[OperationContract,
WebInvoke(Method = "POST",
    ResponseFormat = WebMessageFormat.Json,
    BodyStyle = WebMessageBodyStyle.Wrapped,
    UriTemplate = "/v" + REST_API_VERSION + "/device/?device={device}")]
WSResult DevicePost(String sessionKey, WSDevice device);

[OperationContract,
WebInvoke(Method = "GET",
    ResponseFormat = WebMessageFormat.Json,
    BodyStyle = WebMessageBodyStyle.Wrapped,
    UriTemplate = "/v" + REST_API_VERSION + "/device/?collectionQuery={collectionQuery}")]
WSResult DeviceGet(String sessionKey, WSCollectionQuery collectionQuery);

[OperationContract,
WebInvoke(Method = "PUT",
    ResponseFormat = WebMessageFormat.Json,
    BodyStyle = WebMessageBodyStyle.Wrapped,
    UriTemplate = "/v" + REST_API_VERSION + "/device/?devices={devices}")]
WSResult DevicePut(String sessionKey, WSDevice[] devices);

[OperationContract,
WebInvoke(Method = "DELETE",
    ResponseFormat = WebMessageFormat.Json,
    BodyStyle = WebMessageBodyStyle.Wrapped,
    UriTemplate = "/v" + REST_API_VERSION + "/device/")]
WSResult DeviceDelete(String sessionKey);

So essentially I'd like to have the same UriTemplate, but with different outcome depending on the passed parameters in the message body. I know I added the parameters above in the Uri, but that was just to attempt to differentiate between the Uri.

The error I'm getting is the following:

UriTemplateTable does not support multiple templates that have equivalent path as template '/v1/device/?device={device}' but have different query strings, where the query strings cannot all be disambiguated via literal values. See the documentation for UriTemplateTable for more detail.

I know why I'm receiving this error. What I'd like to know is how else to solve this problem? I've looked at having one function taking Method = "*" which works, but I can't access any parameters other than the one passed in the function.

If anyone knows a solution to this or can say it's not possible if it isn't, it'd be much, much appreciated!

Edit: I also know now you can't pass complex types in GET, but that's an issue that can be worked around.

Wotuu
  • 828
  • 1
  • 8
  • 18

1 Answers1

0

Probably the best solution in this case is to use exactly the same UriTemplate for all 4 methods:

UriTemplate = "/v" + REST_API_VERSION + "/device/?device={device}&collectionQuery={collectionQuery}&devices={devices}"

Then you can check for the necessary parameter in each case.

Quite why this doesn't throw the ambiguous exception beats me however.

ianbeks
  • 2,198
  • 1
  • 23
  • 26