The cleanest way to model Accept header bindings in .NET MVC

I am embedding a REST layer in .NET MVC 3. I am looking for a clean way to grab the Accept header to determine if I should return Json or Xml.

I would also like to spoof this header using the GET parameter for debugging (I want this to continue for prod as well).

Here's how I discovered it at the moment:

if (Request.AcceptTypes.Contains("application/json") || Request.Url.Query.Contains("application/json")) 

This is the only place in my controller code that directly relates to the Request object. I would like a cleaner, more verifiable way to read this. My ideal solution would be a parameter on the controller.

I tried a few keywords to see if the default connecting device would overlap it, but I didn’t try anything.

So what is the cleanest way to get this information? Custom binder model? Can you give an example?

+6
source share
2 answers

An action filter attribute would be a good, clean solution.

There is a good tutorial here: http://www.asp.net/mvc/tutorials/older-versions/controllers-and-routing/understanding-action-filters-cs

+2
source

I do not see the best alternatives to custom model binding. I will post my insert here if anyone else sees this. Using model binding allows the Accept header to be directly attached to the direct input of the action, allowing direct testing of return types and without forcing you to artificially have more actions than you need and not lead to dynamic typed data / bag types.

Here's a Model Binder with a supporting enum type:

 public enum RequestAcceptType { NotSpecified, Json, Xml } public class RequestAcceptTypeModelBinder : IModelBinder { public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) { if (bindingContext == null) { throw new ArgumentNullException("bindingContext"); } RequestAcceptType acceptType = RequestAcceptType.NotSpecified; // Try for Json if (controllerContext.HttpContext.Request.AcceptTypes.Contains("application/json") || controllerContext.HttpContext.Request.Url.Query.Contains("application/json")) { acceptType = RequestAcceptType.Json; } // Default to Xml if (acceptType == RequestAcceptType.NotSpecified) { acceptType = RequestAcceptType.Xml; } return acceptType; } } 

Here is the corresponding bit in Global.asax in the Application_Start method:

 ModelBinders.Binders[typeof(RequestAcceptType)] = new RequestAcceptTypeModelBinder(); 

Then, to use it in your actions, simply enter an argument (any name) with an enumeration type:

 public ActionResult Index(RequestAcceptType acceptType) 

If no one answers the best method in a couple of days, I will take this as an answer.

+2
source

Source: https://habr.com/ru/post/921725/


All Articles