1
votes

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

1
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
@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: stackoverflow.com/questions/46585/… - Abhijeet Patel
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: stackoverflow.com/questions/630453/put-vs-post-in-rest - jfrankcarr
@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
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

1 Answers

1
votes

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.