{"id":70632,"date":"2017-04-25T09:23:17","date_gmt":"2017-04-25T09:23:17","guid":{"rendered":"https:\/\/www.simple-talk.com\/?p=70632"},"modified":"2021-05-17T18:34:38","modified_gmt":"2021-05-17T18:34:38","slug":"improved-model-binding-asp-net-core","status":"publish","type":"post","link":"https:\/\/www.red-gate.com\/simple-talk\/development\/dotnet-development\/improved-model-binding-asp-net-core\/","title":{"rendered":"Improvements to Model Binding in ASP.NET Core"},"content":{"rendered":"<p>Model binding in ASP.NET MVC is an excellent example of how some apparently trivial improvements to a technology can sometimes make life easier for the programmer. To experience the difference, think of how cumbersome it could be to read an integer value passed on the query string of the URL.<\/p>\n<pre class=\"theme:vs2012 lang:js decode:true\">public class DemoController\r\n{\r\n   public ActionResult Read()\r\n   {\r\n       var number = Request[\"Number\"];\r\n       ...\r\n   }\r\n}\r\n<\/pre>\n<p>Unfortunately, the content stored in the variable is a string and some explicit conversion is required to have a usable integer. With model-binding in action, it becomes much smoother:<\/p>\n<pre class=\"theme:vs2012 lang:js decode:true\">public class DemoController\r\n{\r\n   public ActionResult Read(int number)\r\n   {\r\n       ...\r\n   }\r\n}\r\n<\/pre>\n<p>The native model-binding layer kicks in and finds any value available around the HTTP request that can be mapped to the name of the \u201cnumber\u201d parameter. If the type of the declared parameter is compatible with the data in the request, the model binding layer does the conversion and serves the controller method, easily and effectively, an appropriate value. It is a good clean process that reduces the amount of written code that you or other members of the team have to read at some point. Any data you need to process from the incoming request is simply injected into the controller\u2019s space through the signature of the method.<\/p>\n<p>Of course, there is a possible drawback in terms of performance. Internally, model binding uses plenty of reflection to do the job and this reflection comes at a cost in terms of CPU cycles per request. However, a significant share of those CPU cycles is necessary anyway in order to get ready to process the data. In the end, it is a matter of who does what, and model binding can do its job very well. In ASP.NET Core it does it even better than in classic ASP.NET MVC.<\/p>\n<h2>New Features in ASP.NET Core<\/h2>\n<p>The first improvement I wish to mention is one I personally long waited for. It\u2019s another of those small features that together make programming easier. Before ASP.NET Core, any failed attempt to bind to a model resulted in an exception being thrown. Moreover, the exception is thrown outside the control of the controller class so that a global error handler is the only way to catch it. A very common situation is when the controller method needs to receive an integer and either no integer is passed or no value is passed that can be turned into an integer. Let\u2019s consider the following URL:<\/p>\n<pre class=\"theme:vs2012 lang:js decode:true\">http:\/\/server\/demo\/read?number=hello<\/pre>\n<p>Let\u2019s consider now a possible controller method that will handle it.<\/p>\n<pre class=\"theme:vs2012 lang:js decode:true\">public class DemoController\r\n{\r\n   public ActionResult Read(int number)\r\n   {\r\n       ...\r\n   }\r\n}<\/pre>\n<p>The query string of the request contains the value \u201c<strong>hello<\/strong>\u201d associated to the parameter <strong>number<\/strong> and it\u2019s quite impossible to turn it into an integer. In ASP.NET MVC, you will get an exception unless you change the type of the parameter <strong>number<\/strong> to a nullable integer or give it a default value. The improvement to this In ASP.NET Core is that the model binding layer will automatically give the parameter <strong>number<\/strong> the default value of the type (0 for an integer) if the binding can&#8217;t happen for whatever reason.<\/p>\n<p>ASP.NET Core also offers extreme flexibility when choosing the source of values for model binding. In the default configuration of classic ASP.NET MVC, the values to bind might come from routes, posted data, and query strings, in this exact order. In ASP.NET Core, the order is slightly different and posted data is processed before route data and query strings. In classic ASP.NET MVC furthermore you can\u2019t control the choice of the binding source. When a value with the same parameter name is uploaded you can&#8217;t force the process to read the value from a particular source and are, instead, tied to the fixed order of processing. This is entirely different in ASP.NET Core.<\/p>\n<h2>Bind Behavior Attributes<\/h2>\n<p>Two new attributes can be used with model binding in ASP.NET Core. They are <strong>BindNever<\/strong> and <strong>BindRequired<\/strong>. Once applied, the former indicates that binding should never happen on that particular element. The latter, instead, indicates that binding is required. It isn\u2019t entirely clear how these two relate. First of all, <strong>BindRequired<\/strong> has nothing to do with the <strong>Required<\/strong> data annotations attribute that helps in validating a model. The two attributes only determine whether or not binding will happen. Both attributes can only be applied at the class or, better yet, property level. Here\u2019s an example:<\/p>\n<pre class=\"theme:vs2012 lang:js decode:true\">public class Container\r\n{\r\n    [BindNever]\r\n    public int Number { get; set; }\r\n    public int Code { get; set; }\r\n}\r\n<\/pre>\n<p>Imagine now that the class Container is used to capture input data on a controller action method, as below.<\/p>\n<pre class=\"theme:vs2012 lang:js decode:true\">public IActionResult Read(Container container, int number, int code)\r\n{\r\n    ...\r\n}\r\n<\/pre>\n<p>The <strong>code<\/strong> parameter is not decorated in any way and its behavior is exactly the same as in previous versions of ASP.NET MVC. If there\u2019s any request data that can be mapped, it will receive it. Suppose now that there\u2019s some request data that can be mapped to a parameter named <strong>number<\/strong>. The default behavior\u2014the same behavior as in old ASP.NET MVC\u2014would provide for both the <strong>number<\/strong> method parameter and the <strong>Number<\/strong> property to receive the value. In ASP.NET Core, instead, a class property decorated with the <strong>BindNever<\/strong> attribute will not be subject to model binding. If you invoke a URL with a query string of <strong>?number=67&amp;code=90<\/strong> then you would see what\u2019s in the figure below.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-70633\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2017\/04\/word-image-38.png\" width=\"650\" height=\"315\" \/><\/p>\n<p>In fact, the figure shows that the <strong>Number<\/strong> property of the <strong>Container<\/strong> object has not been bound to the incoming data. This is the effect of the <strong>BindNever<\/strong> attribute. At the same time, the plain method parameter named <strong>number<\/strong> has been correctly set via model binding.<\/p>\n<p>The attribute <strong>BindNever<\/strong> may come handy when you are receiving posted data into an input model class and don\u2019t want to have some posted data spoil the state of the object. The user of <strong>BindRequired<\/strong> is a bit trickier. The attribute doesn\u2019t originate errors or exceptions but it simply invalidates the model state if binding failed on the decorated property.<\/p>\n<pre class=\"theme:vs2012 lang:js decode:true\">public class Container\r\n{\r\n    [BindRequired]\r\n    public int Number { get; set; }\r\n    public int Code { get; set; }\r\n}\r\n<\/pre>\n<p>Put another way, if you decorate <strong>Number<\/strong> with the <strong>BindRequired<\/strong> attribute and no value is posted that can be mapped there, then nothing bad happens to your application. However, the moment you check whether the model state is valid you get a negative answer.<\/p>\n<pre class=\"theme:vs2012 lang:js decode:true \">if (ModelState.IsValid)\r\n{\r\n     \/\/ False if binding failed on any property \r\n     \/\/ decorated with the BindRequired attribute\r\n}\r\n<\/pre>\n<p>Note that <strong>BindNever<\/strong> and <strong>BindRequired<\/strong> attributes can&#8217;t be applied to method parameters.<\/p>\n<h2>Forcing Binding to a Given Source<\/h2>\n<p>As mentioned, the model binding layer firstly processes route data, followed by posted data and finally query string data in a fixed order. Consider the following URL:<\/p>\n<pre class=\"theme:vs2012 lang:js decode:true\">\/demo\/123?code=456<\/pre>\n<p>The ambiguity is resolved when assigning the parameter <strong>code<\/strong> the route value of 123 because route data is gets higher priority than query string values.<\/p>\n<pre class=\"theme:vs2012 lang:js decode:true\">[Route(\"demo\/{code}\")]\r\npublic IActionResult Read(Container container, int code)\r\n{\r\n   ...\r\n}\r\n<\/pre>\n<p>In ASP.NET Core, you can alter the fixed order of model binding data sources by forcing the source for a particular parameter. You can do this through any of the following new attributes: <strong>FromQuery<\/strong>, <strong>FromRoute<\/strong>, and <strong>FromForm<\/strong>. As the names indicate, those attributes force the model binding layer to map values from query strings, route data and posted data respectively. For the same URL above, let\u2019s consider the following controller code.<\/p>\n<pre class=\"theme:vs2012 lang:js decode:true\">[Route(\"demo\/{code}\")]\r\npublic IActionResult Read(Container container, [FromQuery] int code)\r\n{\r\n   ...\r\n}\r\n<\/pre>\n<p>The <strong>FromQuery<\/strong> attribute forces the binding of parameter <strong>code<\/strong> to whatever comes from the query string with a matching name. In this case, the parameter code will receive a value of 456 overriding the value being passed with the route data of the URL. The interesting thing is that if the query string doesn\u2019t contain a matching value then the code parameter takes the default value for the declared type rather than any other matching value being posted. In other words, the net effect of any of the <strong>FromQuery<\/strong>, <strong>FromRoute<\/strong> and<strong> FromForm<\/strong> attributes is constraining the model binding to exactly the specified data source.<\/p>\n<h2>Additional Sources for Model binding<\/h2>\n<p>It\u2019s not unusual that some data to be used in the processing of a HTTP request is passed in through a HTTP header. Model binding doesn\u2019t work automatically with the content that comes in through HTTP headers, but in this case, you can retrieve it quite comfortably from within the controller code using the <strong>Request.Headers<\/strong> collection. Interestingly, this has been one of the favorite, and commonly used, extensions to the ASP.NET MVC framework.<\/p>\n<p>To instruct ASP.NET MVC to support additional data sources for model binding, you create custom value providers. Sample additional value providers may read from HTTP headers, cookies, session state and whatever else you can think of that makes sense. A custom value provider is a class that implements the <strong>IValueProvider<\/strong> interface that you register at the application\u2019s startup, as below:<\/p>\n<pre class=\"theme:vs2012 lang:js decode:true\">\/\/ This code works for ASP.NET MVC 5.x (non ASP.NET Core)\r\nValueProviderFactories.Factories.Add(new MyCustomValueProvider());\r\n<\/pre>\n<p>To register a custom value provider in ASP.NET Core you need the following code instead.<\/p>\n<pre class=\"theme:vs2012 lang:js decode:true\">services.AddMvc(options =&gt;\r\n{\r\n    options.ValueProviderFactories.Add(new MyCustomValueProvider());\r\n});\r\n<\/pre>\n<p>In ASP.NET Core, a new attribute makes it easier to map header values more comfortably\u2014the <strong>FromHeader<\/strong> attribute. The main problem I see with automatic binding of HTTP header values to action method parameters is the structure of the names. A header name such as Accept-Language, for example, would require a parameter named accordingly, except that dashes are not acceptable in a C# variable name. The <strong>FromHeader<\/strong> attribute provides an elegant workaround.<\/p>\n<pre class=\"theme:vs2012 lang:js decode:true\">public IActionResult Read([FromHeader(Name =\"Accept-Language\")] string language)\r\n{\r\n   ...\r\n}\r\n<\/pre>\n<p>The attribute gets the header name as an argument and binds the associated value to the method parameter. As a result of the previous code, the language parameter will receive the value of the Accept-Language header. (See Figure.)<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-70634\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2017\/04\/word-image-39.png\" width=\"853\" height=\"142\" \/><\/p>\n<p>In other circumstances, it might worthwhile passing request data not via the URL or headers but as part of the request body. To enable the controller method to receive body content you must explicitly tell the model binding layer to parse the body content to a particular parameter. This is the job that the <strong>FromBody<\/strong> attribute does for you in ASP.NET Core. All that is required on your end is decorating a parameter method with the attribute, as below.<\/p>\n<pre class=\"theme:vs2012 lang:js decode:true\">public IActionResult Read([FromBody] string content)<\/pre>\n<p>The entire content of the request (GET or POST) will be processed as a single unit and mapped wherever possible to the parameter standing possible type constraints.<\/p>\n<p>Note that <strong>FromHeader<\/strong> and <strong>FromBody<\/strong> are new attributes if you see them through the lens of the MVC application model. However, for those accustomed with Web API development both attributes are old acquaintances.<\/p>\n<h2>The FromServices Attribute<\/h2>\n<p>Yet another new model binding tool you find in ASP.NET Core is the <strong>FromServices<\/strong> attribute. It still relates to binding values to controller method parameters but it involves a brand-new subsystem of ASP.NET Core\u2014the Dependency Injection (DI) subsystem.<\/p>\n<p>Speaking in general, DI provides three ways of injecting data into a class\u2014through the constructor, a public property or a method parameter. Injecting through the constructor is enabled by default as long as a type registered with the DI system is discovered in the constructor\u2019s signature.<\/p>\n<pre class=\"theme:vs2012 lang:js decode:true\">public class DemoController : Controller\r\n{\r\n     public DemoController(IOptions options)\r\n     {\r\n         \/\/ DI system resolved IOptions automatically \r\n         \/\/ (provided the type was registered with \r\n         \/\/ the DI system during startup)\r\n     }\r\n}\r\n<\/pre>\n<p>To enable DI in the other two scenarios, you resort to the <strong>FromServices<\/strong> attribute. You can attach the <strong>FromServices<\/strong> attribute to a public property of a controller or a class, and have it automatically bound to an instance of the registered type, if any. Similarly, you can do the same on a method parameter.<\/p>\n<pre class=\"theme:vs2012 lang:js decode:true\">public IActionResult Read([FromServices] ISomeRegisteredType registeredObject)\r\n{\r\n   \/\/ Use the bound instance here\r\n   ...\r\n}\r\n<\/pre>\n<p>The <strong>FromServices<\/strong> attribute relies on the ASP.NET Core embedded DI system and gives you all its benefits but only when you strictly need it. If you inject dependencies in the controller constructor and use them only in a few methods then you would pay the overhead of setting up DI for each and every request. With <strong>FromServices<\/strong>, instead, you would pay the overhead on a per-use basis.<\/p>\n<h2>Summary<\/h2>\n<p>Model binding has been a powerful feature of ASP.NET MVC since its early days; it has worked effectively from the start. The advent of Web API brought some extra features such as <strong>FromHeader<\/strong> and<strong> FromBody<\/strong> that were never brought back to the plain ASP.NET MVC application model. ASP.NET Core unifies the former MVC and Web API application models and provides a larger and more functional framework for model binding.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Model Binding has been a popular feature of ASP.NET MVC, but  has, before now, had some minor restrictions. ASP.NET Core now has enhanced model binding: If a  value passed via routes, posted data, or query strings couldn&#8217;t be bound appropriately, it forced a global exception.  Now, there are a number of ways of providing a more graceful reaction to incorrect data. You can now force the binding to a given source or create new sources for binding to.  Dino Esposito explains.&hellip;<\/p>\n","protected":false},"author":221911,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[143538],"tags":[],"coauthors":[6780],"class_list":["post-70632","post","type-post","status-publish","format-standard","hentry","category-dotnet-development"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/70632","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/users\/221911"}],"replies":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/comments?post=70632"}],"version-history":[{"count":9,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/70632\/revisions"}],"predecessor-version":[{"id":91030,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/70632\/revisions\/91030"}],"wp:attachment":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/media?parent=70632"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/categories?post=70632"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/tags?post=70632"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/coauthors?post=70632"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}