ASP. NET MVC Model binding (IV)
Preface
The previous space gives a rough explanation of the model binder Imodelbinder and the implementation type, model binder provider, and can imagine the model binder as a large container, why do you say so? Leave a question here.
First, the controller's method parameters may be many types, may be multiple of the same type, in response to this situation the MVC framework uses the binding implementation is ivalueprovider to do, and for the different types of parameters and so on some cases, There are also significant differences in the implementation types of Ivalueprovider, and these specific implementations will be explained in the following pages.
All say onlooker sees most, we do not go into the MVC framework, stand outside to see. This article will be outside the perspective of the Ivalueprovider to do a description.
Model
binding
Imodelbinder , custom model Simple implementation of the binder
Model Binder in MVC position in the frame
MVC the default model in Binder Generation Process
Imodelbinderprovider the simple application
Ivalueprovider in MVC the positions and procedures generated in the framework
Ivalueprovider the application Scenario
Ivalueprovider the realization of the Namevaluecollectionvalueprovider
Ivalueprovider the location and process generated in the MVC framework
The location of the build
Can you recall the description of where the model binder was generated in the ASP. NET MVC Model binding (ii), here's a description of the generated location,
Figure 1
650) this.width=650; "src=" Http://images.cnitblog.com/i/627988/201407/012231169344465.png "width=" 738 "height=" 335 "border=" 0 "hspace=" 0 "vspace=" 0 "title=" "style=" width:738px;height:335px; "/>
As shown in Figure 1, in the Blue Line execution process, the Ivalueprovider type is generated after the model binder is generated, saying that the build is a bit inappropriate to get it. Why do you say that in the build section below
The resulting process
Let's look at the implementation code for the Blue Line process in 11.
Code 1-1
Protected virtual object getparametervalue (controllercontext controllercontext, Parameterdescriptor parameterdescriptor) { Type parameterType = parameterdescriptor.parametertype; Imodelbinder modelbinder = this. Getmodelbinder (Parameterdescriptor); ivalueprovider valueprovider = controllercontext.controller.valueprovider; string str = parameterdescriptor.bindinginfo.prefix ?? parameterDescriptor.ParameterName; predicate<string> propertyfilter = getpropertyfilter (parameterDeScriptor); modelbindingcontext context2 = new modelbindingcontext { fallbacktoemptyprefix = parameterdescriptor.bindinginfo.prefix == null, ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType (Null, parametertype), ModelName = str, ModelState = controllercontext.controller.viewdata.modelstate, propertyfilter = propertyfilter, ValueProvider = valueProvider }; modelbindingcontext bindingcontext = context2; return (Modelbinder.bindmodel (Controllercontext, bindingcontext) ?? parameterdescriptor.defaultvalue); }
For the method shown in code 1-1, the return type and the function of this method do not need to be taken care of, what we want to know now is how Ivalueprovider is coming!!!
From code 1-1, we can clearly see that after the model binder is generated, the MVC framework obtains a reference to the controller requested by the current request from the ControllerContext controller context parameter object. The Ivalueprovider type is then obtained according to the current controller object reference.
The MVC framework then instantiates the Modelbindingcontext type and assigns the Ivalueprovider type you just acquired to the Valueprovider attribute in it.
For the Modelbindingcontext type, the model binding context object, look at its definition code 1-2.
Code 1-2
public class modelbindingcontext { public modelbindingcontext (); public Modelbindingcontext (Modelbindingcontext bindingcontext); public bool fallbacktoemptyprefix { get; set; } public object Model { get; set; } public ModelMetadata ModelMetadata { get; set; } public string modelname { get; set; } public ModelStateDictionary ModelState { get; set; } public type modeltype { get; set; } public predicate<string> propertyfilter { get; set; } public IDictionary<string, modelmetadata> propertymetadata { get; } // // Summary: // Gets or sets the value provider. // // return Results The: // value provider. public IValueProvider ValueProvider { get; set; } }
All we need to do here is to get a basic understanding of the Modelbindingcontext type, and go back to the topic, which is directly obtained from the reference to the current controller object, so let's take a look at the Valueprovider property in the controller. Let's take a look at the controller type, code 1-3.
Code 1-3
Public abstract class Controller:controllerbase, Iactionfilter, Iauthorizationfilter, IDisposable, Iexceptionfilter, Iresultfilter{...}
I had a joke with everyone to relieve the atmosphere. There is no attribute in the controller type that we are looking for, and some friends think about it in the base class type, indeed in the Controllerbase type (code 1-4).
Code 1-4
Public abstract class controllerbase:icontroller{... public ivalueprovider valueprovider {get; set;}}
Do we have to assign a value to the Controller object when we are using Ivalueprovider?
Of course not, let's take a look at the implementation of the Valueprovider property in code 1-4, example code 1-5.
Code 1-5
public ivalueprovider valueprovider { get { if (this._valueprovider == null) { this._valueProvider = ValueProviderFactories.Factories.GetValueProvider (this. ControllerContext); } return this._valueprovider; } set { this._valueProvider = value; } }
As you see here, it should be understood that the origin of the Ivalueprovider type is derived from the factories attribute of the system's valueproviderfactories type, based on the current controller context.
Here we look at the definitions of several related types that generate the Ivalueprovider type, example code 1-6.
Code 1-6
public static class valueproviderfactories { // Abstract: // gets the collection of application value provider factories. // // return Results A collection of: // value-Provider factory objects. public static ValueProviderFactoryCollection factories { get; } } public class valueproviderfactorycollection : collection<valueproviderfactory> { public valueproviderfactorycollection (); public valueproviderfactorycollection (IList<ValueProviderFactory> list); // Abstract: // Returns a value provider factory for the specified controller context. // // Parameters: // controllerContext: // an object that encapsulates information about the current HTTP request. // // return Results The: // is used to specify the value provider factory object for the controller context. public ivalueprovider getvalueprovider ( Controllercontext controllercontext); protected Override void insertitem (Int index, valueproviderfactory item); &nBsp; protected override void setitem (int index, Valueproviderfactory item); } public abstract class valueproviderfactory { protected valueproviderfactory (); // Summary: // Returns a value provider object for the specified controller context. // // Parameters: // controllerContext: // an object that encapsulates information about the current HTTP request. // // return Results : &NBSP;&NBSP;&NBSP;&NBSP;&NBThe sp; // value-provider object. public abstract ivalueprovider getvalueprovider (controllercontext controllercontext); }
Valueproviderfactories type of this pattern has seen too much before, it is not said, it has a valueproviderfactorycollection type of static properties, The valueproviderfactorycollection type is also the collection type of the Valueproviderfactory type, So when the Ivalueprovider type is eventually generated, the valueproviderfactorycollection type is traversed first, Get an instance of each valueproviderfactory type and generate the Ivalueprovider type, which is also the first match rather than the best match.
Incidentally, a controller context object can be used to classify the generation logic in the Valueproviderfactory type and to generate different ivalueprovider types for different controllers. The use of the Ivalueprovider type is explained in the following pages.
This article is from the "Jinyuan" blog, please be sure to keep this source http://jinyuan.blog.51cto.com/8854733/1433305