MVC Source Analysis-Modelbinder binding/Custom data binding

Source: Internet
Author: User

These days old feel wrong, always feel less what, today only found, in front 3 inside, in get action parameter information, less parse. There is a more important thing in it. The same is true for today's watch.

In the Invokeaction () method, there is a code:

idictionary<stringobjectthis. Getparametervalues (ControllerContext, actiondescriptor);

This is used to get the parameters. So is the parameter freely available? In MVC, when the page to the action, there is no attempt to pass an array, and then receive the time, also directly parse the group? Or to receive more complex types?

The answer is in this article. First look at the source code.

protected Virtualidictionary<string,Object>getparametervalues (ControllerContext controllercontext,
Actiondescriptor actiondescriptor) {Dictionary<string,Object> dictionary =Newdictionary<string,Object>(stringcomparer.ordinalignorecase); foreach(Parameterdescriptor DescriptorinchActiondescriptor. GetParameters ()) {Dictionary[descriptor. ParameterName]= This. Getparametervalue (ControllerContext, descriptor); } returndictionary;}

First, source code analysis

1. Actiondescriptor.getparameters ()

// System.Web.Mvc.ReflectedActionDescriptor  Public Override parameterdescriptor[] GetParameters () {    return actiondescriptorhelper.getparameters (  This isrefthis. _parameterscache);}

This should be to get all the parameters and their descriptive information.

2. This. Getparametervalue ()--Main method

protected Virtual ObjectGetparametervalue (ControllerContext ControllerContext,
Parameterdescriptor parameterdescriptor) {Type parametertype=Parameterdescriptor.parametertype;
   //Parameter description to get the processing interface of the parameter Imodelbinder Modelbinder= This. Getmodelbinder (Parameterdescriptor); Ivalueprovider Valueprovider=ControllerContext.Controller.ValueProvider; stringstr = ParameterDescriptor.BindingInfo.Prefix??Parameterdescriptor.parametername;
   //Get the filter above the parameter and put it in the parameter parsing context below (Modelbindingcontext) predicate<string> propertyfilter = getpropertyfilter(parameterdescriptor); Modelbindingcontext BindingContext=NewModelbindingcontext {fallbacktoemptyprefix= ParameterDescriptor.BindingInfo.Prefix = =NULL, Modelmetadata= ModelMetadataProviders.Current.GetMetadataForType (NULL, ParameterType), ModelName=str, modelstate=controllerContext.Controller.ViewData.ModelState, propertyfilter = propertyfilter, valueprovider=Valueprovider};
   //handler for execution parameters return(Modelbinder.Bindmodel(ControllerContext, BindingContext)??parameterdescriptor.defaultvalue);}

2.1 Getmodelbinder () method

Private imodelbinder Getmodelbinder (parameterdescriptor parameterdescriptor) {    return
This . Binders.getbinder (Parameterdescriptor.parametertype));}

Here is the processing interface to get the parameters according to the parameter description

 Public Interface  imodelbinder{    //  Methods    object   Bindmodel (ControllerContext controllercontext, Modelbindingcontext bindingcontext);}

2.2 Bindmodel () method-Here you see Defaultmodelbinder, which will customize a

 Public Virtual ObjectBindmodel (ControllerContext controllercontext, Modelbindingcontext BindingContext) {    Ensurestackhelper.ensurestack (); if(BindingContext = =NULL)    {        Throw NewArgumentNullException ("BindingContext"); }    BOOLFlag =false; if(!string. IsNullOrEmpty (Bindingcontext.modelname)
&&!BindingContext.ValueProvider.ContainsPrefix (Bindingcontext.modelname)) { if(!bindingcontext.fallbacktoemptyprefix) {return NULL; } Modelbindingcontext Context=NewModelbindingcontext {modelmetadata=Bindingcontext.modelmetadata, Modelstate=bindingcontext.modelstate, PropertyFilter=Bindingcontext.propertyfilter, Valueprovider=Bindingcontext.valueprovider}; BindingContext=context; Flag=true; } if(!flag) { BOOLFlag2 =shouldperformrequestvalidation (ControllerContext, BindingContext); BOOLSkipvalidation =!Flag2; Valueproviderresult Valueproviderresult=Bindingcontext.unvalidatedvalueprovider
. GetValue (Bindingcontext.modelname, skipvalidation); if(Valueproviderresult! =NULL) {
       //Return parameter values for simple objects return This. Bindsimplemodel (ControllerContext, BindingContext, Valueproviderresult); } } if(!bindingContext.ModelMetadata.IsComplexType) {return NULL; } return This. Bindcomplexmodel (ControllerContext, BindingContext);}

This is a bit more content, but also a bit complex, in fact, the resolution here, almost already get what I want.

Second, custom Modelbinder

1. Imodelbinder-for relatively simple types, you can use this method

Start by creating a slightly more complex class.

 Public enumgenderenum{Female, Male, unknow} Public classextinfo{ Public stringQQ {Get;Set; }  Public stringPhone {Get;Set; }} Public classuser{
   //The constructor here, I created a extinfo instance, otherwise, this Extinfo object is empty, affecting my demo PublicUser () {Extension=NewExtinfo (); }
Public intId {Get;Set; } Public stringName {Get;Set; } PublicGenderenum Gender {Get;Set; } PublicExtinfo Extension {Get;Set; }}

Next, take a look at the controller code

 Public class modelcontroller:controller{    public  actionresult Get (user user)    {          return  View (user);      Public ActionResult Index ([modelbinder(typeof(modelindexbinder))]user User)    {        return  View (user);}    }

The part of the controller that needs attention, I'm already marked red. Next look at my custom modelbinder.

 Public class modelindexbinder : imodelbinder{ Public ObjectBindmodel (ControllerContext controllercontext, Modelbindingcontext bindingcontext) {varRequest =controllerContext.HttpContext.Request; User User=NewUser {Id= Convert.ToInt32 (Request. params["Id"]), Name= Request. params["Name"]. ToString (), Gender= (genderenum) convert.toint32 (request. params["Gender"]), Extension=NewExtinfo {QQ= Request. params["QQ"]. ToString (), Phone= Request. params["Phone"].        ToString ()}}; returnuser; }}

Let's take a look at the effect of two methods.

Index Get

Note: Here is a different way to achieve the purpose, only need to modify the URL can be:

http://localhost:11620/model/get?id=1&name=haha&gender=0&extension.qq= 123123123&extension.phone=12312341234

Here is to give an example, only to do so.

For relatively simple, with Imodelbinder is very convenient, but for a little more complex, you can achieve defaultmodelbinder to achieve.

But this part of the implementation is not resolved, I temporarily useless.

Generally for URL get requests, it is not very complex, only when you use the POST request, you will encounter more complex processing methods. But for this kind of complex processing, there is a more common way, is to use the way of deserialization, I commonly used is newtonsoft.

Reference:

  MVC extension

Dive into ASP. NET MVC

Directory is synchronized

MVC Source Analysis-Modelbinder binding/Custom data binding

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.