OData API with parameterized get operation - rest

Is it possible to implement the get operation with filter parameters as below:
public IHttpResult Get([FromODataUri] int productId, int accountId)
{
...
}
Note that we are not supposed to use [ODataRoute] attribute to customize it. Any thoughts?

Get operation with multiple parameters works just fine as usual, just need to call the service with named query string parameters. For example for the above Get operation the URL can be: http://localhost/myapp/odata/Products/?productId=1&accountId=2

Related

What is the best solution to pass two different parameters to a REST API?

I have a doubt about what could be the best way to define a REST URI for an API.
I have an API that provide the details of a commodity.
So I know that I can do a GET request like this:
http://XXX.YYY.ZZZ.TTT:8280/commodity_details/1
where commodity_details is what I want to obtain (a commodity details) and 1 is the ID of a specific commodity. This should be a proper REST URI.
Ok, I know that I can also pass the ID parameter into a JSON document doint a POST request like this:
http://XXX.YYY.ZZZ.TTT:8280/commodity_details/
and attacching a JSON payload like this to my POST request:
{
"commodity_id": 1
}
I think that if I have the single commodity_id parameter maybe is better the first version (putting the required ID into the URI), is it?
But what happens if I need a second language_id parameter? (my API should receive also this language_id parameters so it can provide an internazionalized output in the proper language.
So in this case I need to pass 2 parameters (commodity_id and language_id).
In this case is better use a POST request with a JSON payload that contains both the parameters? Something like this:
{
"commodity_id": 1,
"language_id": 2
}
Or what could be a good URI template for this scenario?
For passing just 2 parameters you can go with first approach(query string parameter) which is simpler to use
[HttpGet("{commodity_id}/{language_id}")]
public string GetCommodityDetails(string commodity_id, string language_id)
{
string commodityDetails=string.empty;
//your implementation
return commodityDetails;
}

Fetching the Odata query parameter in code

I have a rest Get method Ex:-
public IQueryable<Test> GetTest() {
return _service.GetAll();
}
I want to fetch the query parameter in code which was the part of the request url, I cant give OdataQueryOption parameter in the method like GetTest(OdataQueryOption
op).
Please suggest a solution
Assuming you're implementing an ODataController you should be able to access this.Request.RequestUri.Query. If you want the name/value pairs you should use System.Web.HttpUtility.ParseQueryString to get a NameValueCollection.

How can I define an Angular resource that doesn't use query parameters for REST GET?

Currently I have a resource defined in Angular like this:
Users: $resource(APIBASEROUTE +'/users/:_id', {_id: '#_id'})
When I call for a user with this code:
$scope.user = ayApi.Users.get({id:$routeParams.userId});
The request is sent as a query parameter like this:
http://localhost:3000/api/v1/users?id=526eff826a6100fb22000000
However it needs to hit the REST server like this:
http://localhost:3000/api/v1/users/526eff826a6100fb22000000
How do I make Angular do it this way?
I guess that the problem is in incosistency of the parameters names.
in definition you have: {_id:'#_id'}), it should be the {id...
Or in your call it should be with underscore
$scope.user = ayApi.Users.get({_id:$routeParams.userId});
Any other parameter (not mapped in the resource definition) is treated as a query string param. That's why angular decided to append your id as a query string part. It is not _id

Sending multiple queries to a webapi controller

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
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.

Why won't my WCF Data Service accept my querystring?

I'm using jqGrid to display some data to the user. One of the features needed is for users to be able to search the grid. I'm using a WCF Data Service to get this data and return it.
When I first started jqGrid development I just needed pagination (no searching required) and was successfully able to use the following method:
[WebGet(ResponseFormat = WebMessageFormat.Json)]
public String GetStuff(int? page, int? rows)
{
// pagination going on in here
}
Then I needed the search so I added a param of type string like so:
[WebGet(ResponseFormat = WebMessageFormat.Json)]
public String GetStuff(int? page, int? rows, string search)
{
// more stuff going on in here
}
and then I get a 400 Bad Request error. I assume its because of the search param, I just don't understand why int works (and even bool worked) but string doesn't. Does it have anything to do with the fact that WCF Data Services are RESTful?
I of course double-checked the query string that jqGrid sends (via ajax) and it matches the param name. There are some extra query string params that jqGrid sends that are not used (ignoring them worked fine with my original pagination code)
String literals in the query URL must be quoted with single quotes. So the above service operation would be called like this:
/GetStuff?page=1&rows=10&search='John'
Does your query string look like that?