I am developing some REST resources using the ASP.NET MVC 3 platform. So far, its been great, I love the flexibility of MVC 3, and it is a breeze to build REST services with it. One area where I have been having a difficult time are the route constraints in Global.asax. For one, they never seem to work properly (including one ALWAYS returns 404, even if the input most definitely meets the requirements of the constraint...but thats another question).
Second, and more importantly, the result returned when a constraint fails is always an HTML page. Assuming the constraints work, having the result be HTML really throws a wrench in the mix when all of the consumers of these REST services will be accepting data types, such as application/json, text/xml, possibly bson, etc. I really need to be able to address errors in our clients directly, rather than simply blowing up and logging the html for sideband resolution.
Is it possible to change what gets returned in response to a route constraint? Is it possible to make whats returned dynamic, such that if the client issuing the request only accepts application/bson, we can generate an acceptable response, rather than simply generating a canned response of a single mime type?
About returning a code error instead of going to a controller you have to implemet a custom RouteHandler. This link resumes all thing you can put the finger on ...and that you might modify this way. About "adapting" the return type...you can do this in the controller. It is enough to put som if and in some cases you return Json(...) and in other cases you return View or PartialView.
However it is nice to do this in a controller filter...!
I implemented a Control filter that allows the controller to negotiate the return type with the client. I is very simple...the client just declare the type that i would like to receive either in a route parameter (a piece of the url, or of the query string) or by posting a field that contains this info. The use is very simple...you rcontroller can return a View thai the "default" return type if no infos come from the client. Then the filter "change" automatically the result type before the View is invoked transformig it in what the client required. The possibilties handled by the filter are a view whose name is chosen by the client or Json
The code is here(It contains some controls on the "hint" provided by the client to prevent attacks by malicious users):
public class AcceptViewHintAttribute : ActionFilterAttribute
{
private JsonRequestBehavior jsBehavior;
public AcceptViewHintAttribute(JsonRequestBehavior jsBehavior = JsonRequestBehavior.DenyGet)
{
this.jsBehavior = jsBehavior;
}
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
string hint = filterContext.RequestContext.HttpContext.Request.Params["ViewHint"];
if (hint == null) hint = filterContext.RequestContext.RouteData.Values["ViewHint"] as string;
if (!string.IsNullOrWhiteSpace(hint) && hint.Length<=100 && new Regex(@"^\w+$").IsMatch(hint) )
{
ViewResultBase res = filterContext.Result as ViewResultBase;
if (res != null)
{
if (hint == "json")
{
JsonResult jr = new JsonResult();
jr.Data = res.ViewData.Model;
jr.JsonRequestBehavior = jsBehavior;
filterContext.Result = jr;
}
else
{
res.ViewName = hint;
}
}
}
base.OnActionExecuted(filterContext);
}
}
Errlusion might be of some help here.
You may be able to write some custom logic to check the HTTP Accept
header and/or use [SomeContext].Request.IsAjaxRequest()
to see if JSON or BSON would be appropriate to return -- or just return JSON or BSON for all types of requests if you prefer.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With