1

Is there a way in webapi(besides odata) to specify multiple queries? Here is the scenario: A custom sproc. that accepts 2 zip codes, performs distance calculation and return the distance The WebAPI endpoint accepts the zips and calls into the sproc. and returns a Distance DTO class ZIPDistance { public string Zip1, public string Zip2, public sttring Distance }

The URL for this: "/api/ZipDistances?$select=Distance&$filter=Zip1 eq 13240 and Zip2 eq 90210 In the ZipDistancesController we extract the parameters from the above query using ODataQueryOptions, call into the sproc. and return the DTO above.

For potential performance reasons it was requested that the above endpoint somehow accept a collection of zip code pairs i.e. a collection of the "ZIPDistance" DTOs representing the "pairs" of zips for which we need to call into the sproc above, loop over the DTOs, invoke the sproc. per DTO and return a collection of DTOs for the result so that a client would make a single HTTP call instead of multiple calls and obtain all results in 1 call.

The only way that I am aware of doing is via a POST and pass in the collection of ZIPDistances representing the zip code pairs in the payload, but this is fundamentally against REST since now we change the semantic meaning of POST to mean data retrieval (i.e. GET)

The question is whether the above scenario supported by WEBAPI and what would be the best way for implementing the above without overloading verb meaning and causing confusion.

UPDATE:

I've prototyped out one possible solution here which involves embedding the pairs in the URL:

http://<host>/api/ZipDistances?$select=Distance&$filter=Pairs eq 'Zip1 eq 13240 and Zip2 eq 90210,Zip1 eq 13241 and Zip2 eq 90211'

and the corresponding DTO:

 public class ZipDistanceDTO
    {
        public string ZipPairs { get; set; }
        public string Distance { get; set; }
    }

This would return the following result:

[{"ZipPairs":"'Zip1 eq 13240 and Zip2 eq 90210","Distance":"558"},
{"ZipPairs":"Zip1 eq 13241 and Zip2 eq 90211'","Distance":"558"}]

Comments/Thoughts on this would be appreciated.

UPDATE (2): I've posted another prototype here that uses a Query resource

Abhijeet Patel
  • 6,562
  • 8
  • 50
  • 93
  • I'm not sure if it's the pure REST way of doing things, but in a BI web app/api that has complex parameters, such as you described, I'm using a PUT of a JSON object to request a drill down query from the API server. The base data is retrieved via a GET but the drill downs are a PUT. The drill down request can have a large number of parameters, including ranges, so building a querystring URL became kind of messy, particularly since I already had the object on hand. – jfrankcarr Sep 29 '13 at 11:25
  • @Jfrankcarr: It's not the REST way of doing things.A POST is intended to be used for any operation which is neither safe or idempotent. Typically a POST would be used to create a new resource and/or alter state. Ref: http://stackoverflow.com/questions/46585/when-do-you-use-post-and-when-do-you-use-get – Abhijeet Patel Sep 29 '13 at 23:00
  • 1
    PUT is idempotent but not safe. Another problem with using GET is that IE, the corporate mandated browser, can only handle 2048 characters in a GET. Of course, when to use GET, PUT or POST is a long running debate: http://stackoverflow.com/questions/630453/put-vs-post-in-rest – jfrankcarr Sep 30 '13 at 00:06
  • @jfrankcarr: Liel's answer below seems to work well and is RESTFUL. POSTing a "ZipDistanceQuery" object against a "xxxQuery" endpoint to obtain a ID and issue a GET against a "xxxQueryResult" endpoint using the ID to get the result. – Abhijeet Patel Oct 01 '13 at 01:42
  • I'm using a query resource style object in my current project except I'm using a PUT rather than POST since data isn't being changed in the request. One of the tricky things I've found about reporting/BI apps is that they don't fit into the usual CRUD patterns that well. – jfrankcarr Oct 01 '13 at 11:20
  • REST and RPC style services are fundamentally different. It's a mind shift to move away from GetXXX style methods in a web service to a resource centric view wherein your "Queries" is just another resource(endpoint) similar to any other data end point(Products,Customers etc.)The resource could be transient unlike the other resources but that's an implementation detail. But fundamentally GET/PUT/POST should work the same way. There is a heavy debate between PUT/POST. My stance has always been to use POST to create, PUT for a full update and PATCH for a partial update – Abhijeet Patel Oct 03 '13 at 03:47

1 Answers1

1

Issuing proper GET request with multiple ZIP codes is just fine to be used.

However,
Another possible RESTfull way is to create a "Query Resource" object using POST, returning "Query Resource ID Number", which will later be used in a separated GET request.

By that you are creating saved queries which can also be efficient for re-querying as well.

Liel
  • 2,407
  • 4
  • 20
  • 39
  • Do you have any suggestions for generating the ResourceID? Adding the resource to the DB is overkill since these queries would be transient. I am using an in-memory cache to store the query for a specified time interval but this approach would not work if in a load balanced scenario wherein the client could hit instance A to POST the "query" objects and hit instance B to GET the results – Abhijeet Patel Oct 08 '13 at 04:02
  • Well, if you can't have A communicate with B, then I see no way other than posting to a DB. By the way, a DB can also be a shared memory space, the file system, or some other kind of communication. Are you sure that the queries will be transient? – Liel Oct 08 '13 at 05:14
  • Yes the queries will be transient since the query resource really represents a collection of ZipDistanceDTOs for which we invoke a sproc. No real need to persist this in a DB. Plus it would also impact perf. since we'd need to take a DB hit every time to store and retrieve a serialized representation of the DTOs just for executing a sproc. Seems a bit overkill to me. Another option would be to maybe use a distributed cache? – Abhijeet Patel Oct 08 '13 at 05:20