I feel like I'm trying to do a really simple thing, but I can't figure out how to do it. Basically, I have a Web API controller that I am using to query data using complex and arbitrary data. For example, let's pretend my Controller is called YelpController
and its intent is to allow the consumer to find restaurants. I would want to do something like this:
// here's my search criteria; these are all optional
public class SearchCriteria
{
public int Latitude { get; set; }
public int Longitude { get; set; }
public string Cuisine { get; set; }
public ExpenseCategory { get; set; }
}
public IEnumerable<Restaurant> GetByCriteria(SearchCriteria filters)
{
// do stuff
return matches;
}
I'd like to issue this via an ajax request, like this:
Clearly, this doesn't work since I can't send a "data" payload along with a GET request. I could do this with a POST, but that seems hacky.
Instead of using one wrapper class as a single input parameter, I could split it out and have 4 parameters to the method and pass them in via a query string (eg /api/Yelp/GetByCriteria?latitude=xxx&longitude=yyy), but that is REALLY brittle and would require
my API to change every time I add a new parameter.
Also, I clearly cannot use OData/IQueryable; my datastore is NoSQL and, besides, the parameters I want to pass aren't even supported currently.
So, what's the PROPER solution for this scenario? This seems like a super common use case, but I can't find anyone else with the same problem
public class BindJson : System.Web.Http.Filters.ActionFilterAttribute
{
Type _type;
string _queryStringKey;
public BindJson(Type type, string queryStringKey)
{
_type = type;
_queryStringKey = queryStringKey;
}
public override void OnActionExecuting(System.Web.Http.Controllers.HttpActionContext actionContext)
{
var json = actionContext.Request.RequestUri.ParseQueryString()[_queryStringKey];
var serializer = new JavaScriptSerializer();
actionContext.ActionArguments[_queryStringKey] = serializer.Deserialize(json, _type);
}
}
public class YelpController : ApiController
{
[BindJson(typeof(SearchCriteria), "json")]
public IEnumerable<Restaurant> GetByCriteria(SearchCriteria json)
{
// do stuff
return new List<Restaurant>();
}
}
You can construct this with JSON.stringify method. Here is a possible filter,
public class BindJson : System.Web.Http.Filters.ActionFilterAttribute
{
public override void OnActionExecuting(System.Web.Http.Controllers.HttpActionContext actionContext)
{
var json = actionContext.Request.RequestUri.ParseQueryString()["json"];
var serializer = new JavaScriptSerializer();
actionContext.ActionArguments["filters"] = serializer.Deserialize(json, typeof(SearchCriteria));
}
}
public class YelpController : ApiController
{
[BindJson]
public IEnumerable<Restaurant> GetByCriteria(SearchCriteria filters)
{
// do stuff
return new List<Restaurant>();
}
}
"And whoever is removed away from the Fire and admitted to Paradise, he indeed is successful." (The Holy Quran)
Excellent Windows VPS Hosting Imran Baloch MVP, MVB, MCP, MCTS, MCPD
BurntSky
Participant
785 Points
160 Posts
Passing multiple or complex parameters to a GET handler
May 25, 2012 04:58 AM|LINK
I feel like I'm trying to do a really simple thing, but I can't figure out how to do it. Basically, I have a Web API controller that I am using to query data using complex and arbitrary data. For example, let's pretend my Controller is called YelpController and its intent is to allow the consumer to find restaurants. I would want to do something like this:
// here's my search criteria; these are all optional public class SearchCriteria { public int Latitude { get; set; } public int Longitude { get; set; } public string Cuisine { get; set; } public ExpenseCategory { get; set; } } public IEnumerable<Restaurant> GetByCriteria(SearchCriteria filters) { // do stuff return matches; }I'd like to issue this via an ajax request, like this:
$.ajax( { url: "/api/Yelp/GetByCriteria", type: "GET", contentType: "application/json", data: JSON.stringify({ Latitude: 47.6097, Longitude: -122.3331 }), success: function (result) { alert(result.Result); } });Clearly, this doesn't work since I can't send a "data" payload along with a GET request. I could do this with a POST, but that seems hacky.
Instead of using one wrapper class as a single input parameter, I could split it out and have 4 parameters to the method and pass them in via a query string (eg /api/Yelp/GetByCriteria?latitude=xxx&longitude=yyy), but that is REALLY brittle and would require my API to change every time I add a new parameter.
Also, I clearly cannot use OData/IQueryable; my datastore is NoSQL and, besides, the parameters I want to pass aren't even supported currently.
So, what's the PROPER solution for this scenario? This seems like a super common use case, but I can't find anyone else with the same problem
imran_ku07
All-Star
45815 Points
7698 Posts
MVP
Re: Passing multiple or complex parameters to a GET handler
May 25, 2012 07:37 AM|LINK
A custom filter will be help you here. You need to pass just a single json querystring in url, for example,
?json={"Latitude"%3A+47.6097%2C+"Longitude"%3A+-122.3331}
Edit: you can improve this method by doing,
public class BindJson : System.Web.Http.Filters.ActionFilterAttribute { Type _type; string _queryStringKey; public BindJson(Type type, string queryStringKey) { _type = type; _queryStringKey = queryStringKey; } public override void OnActionExecuting(System.Web.Http.Controllers.HttpActionContext actionContext) { var json = actionContext.Request.RequestUri.ParseQueryString()[_queryStringKey]; var serializer = new JavaScriptSerializer(); actionContext.ActionArguments[_queryStringKey] = serializer.Deserialize(json, _type); } } public class YelpController : ApiController { [BindJson(typeof(SearchCriteria), "json")] public IEnumerable<Restaurant> GetByCriteria(SearchCriteria json) { // do stuff return new List<Restaurant>(); } }You can construct this with JSON.stringify method. Here is a possible filter,
public class BindJson : System.Web.Http.Filters.ActionFilterAttribute { public override void OnActionExecuting(System.Web.Http.Controllers.HttpActionContext actionContext) { var json = actionContext.Request.RequestUri.ParseQueryString()["json"]; var serializer = new JavaScriptSerializer(); actionContext.ActionArguments["filters"] = serializer.Deserialize(json, typeof(SearchCriteria)); } } public class YelpController : ApiController { [BindJson] public IEnumerable<Restaurant> GetByCriteria(SearchCriteria filters) { // do stuff return new List<Restaurant>(); } }Excellent Windows VPS Hosting
Imran Baloch MVP, MVB, MCP, MCTS, MCPD
BurntSky
Participant
785 Points
160 Posts
Re: Passing multiple or complex parameters to a GET handler
May 25, 2012 03:10 PM|LINK
Excellent. Passing URL encoded stringified JSON in a query string is probably not the most elegant solution, but so far it seems to work. Thanks!
arawin1979
Member
2 Points
1 Post
Re: Passing multiple or complex parameters to a GET handler
Feb 21, 2013 02:23 PM|LINK
Hi Thanks for the solution