Simulate the model binding mechanism of ASP.net MVC by example: Simple Type + Complex type

Source: Internet
Author: User
Tags bind empty execution visual studio

In general, model bindings for the target action method parameters are fully implemented by the component Modelbinder, and the Modelbinder type used by default is Defaultmodelbinder. Next, we will introduce the default model binding mechanism for implementation in Defaultmodelbinder, in a layered and in-depth manner. [Source code download from here]

One, Simple Type

For model, which is designed to bind the parameter values of the target action method, the simplest is the case of a simple parameter type. We know that the difference between a complex type and a simple type is only the support for a conversion to a string type. Because the data source of the parameter value exists as a string in the request, for simple types that support string conversions, you can get parameter values directly from type conversions. We use a simple example to simulate the implementation of the model bindings for simple types in Defaultmodelbinder. As shown below is our custom Defaultmodelbinder, whose property valueprovider is used to provide the corresponding data value from the request, which is initialized in the constructor.

1:public class Defaultmodelbinder
2: {
3:public Ivalueprovider Valueprovider {get; private set;}
4:public Defaultmodelbinder (Ivalueprovider valueprovider)
5: {
6:this. Valueprovider = Valueprovider;
7:}
8:
9:public ienumerable<object> getparametervalues (actiondescriptor actiondescriptor)
10: {
11:foreach (Parameterdescriptor parameterdescriptor in Actiondescriptor.getparameters ())
12: {
13:string prefix = parameterDescriptor.BindingInfo.Prefix?? Parameterdescriptor.parametername;
14:yield return Getparametervalue (parameterdescriptor, prefix);
15:}
16:}
17:
18:public Object Getparametervalue (parameterdescriptor parameterdescriptor, string prefix)
19: {
20:object ParameterValue = Bindmodel (parameterdescriptor.parametertype, prefix);
21:if (Null = = ParameterValue && string. IsNullOrEmpty (ParameterDescriptor.BindingInfo.Prefix))
22: {
23:parametervalue = Bindmodel (Parameterdescriptor.parametertype, "");
24:}
25:return parametervalue?? Parameterdescriptor.defaultvalue;
26:}
27:
28:public Object Bindmodel (Type parametertype, string prefix)
29: {
30:if (!this. Valueprovider.containsprefix (prefix))
31: {
32:return null;
33:}
34:return this. Valueprovider.getvalue (prefix). ConvertTo (ParameterType);
35:}
36:}

Method Getparametervalues obtains all the parameter values for the final execution of the method based on the specified actiondescriptor that describes the action method. In this method, we get all the Parameterdescriptor objects used to describe their parameters by calling the Actiondescriptor GetParameters method. And each parameterdescriptor as a parameter calls the Getparametervalue method to get the value of a specific parameter. In addition to accepting a parameter of type Parameterdescriptor, Getparametervalue accepts a string parameter to represent the prefix. If the Parameterbindinginfo object represented by the Bindinginfo property of Parameterdescriptor has a prefix, the prefix is used, otherwise the parameter name is used as the prefix.

For the Getparametervalue method, it also provides a specific parameter value by calling another Bindmodel method that takes the parameter type as a parameter, and the Bindmodel method also accepts a string representing the prefix as its second argument. Getparametervalue initially calls the Bindmodel method with the parameter values and prefixes obtained by parameterdescriptor, and if the return value is null and the argument does not show the execution prefix, An empty string is passed as a prefix to call the Bindmodel method again, which in effect simulates the fallback model binding mechanism (for the Modelbindingcontext Fallbacktoemptyprefix attribute) that was previously mentioned to remove the prefix. If the resulting object is not NULL, it is returned as a parameter value, otherwise the default value of the parameter is returned.

The logic of the Bindmodel method is very simple. The incoming prefix is invoked as a parameter to Valueprovider's Containsprefix method to determine whether the current Valueprovider persisted data has that prefix. If returned to False, NULL is returned directly, otherwise the GetValue method is called with the prefix as key to get a valueproviderresult call and the ConvertTo method is eventually converted to the parameter type and returned.

In order to verify that our custom defaultmodelbinder can really be used for model bindings for simple parameter types, we apply it to a specific asp.net MVC application. In an empty Web application created from the ASP.net MVC project template in Visual Studio, we created the following default HomeController. HomeController has a Modelbinder property whose type is our custom Defaultmodelbinder, which is provided through the method Getvalueprovider.

1:public class Homecontroller:controller
2: {
3:public Defaultmodelbinder Modelbinder {get; private set;}
4:public HomeController ()
5: {
6:this. Modelbinder = new Defaultmodelbinder (Getvalueprovider ());
7:}
8:private void Invokeaction (String actionname)
9: {
10:controllerdescriptor controllerdescriptor = new Reflectedcontrollerdescriptor (typeof (HomeController));
11:reflectedactiondescriptor actiondescriptor = (reflectedactiondescriptor) controllerdescriptor
12:. Findaction (ControllerContext, actionname);
13:actiondescriptor.methodinfo.invoke (this,this. Modelbinder.getparametervalues (Actiondescriptor). ToArray ());
14:}
15:public void Index ()
16: {
17:invokeaction ("Action");
18:}
19:
20:private Ivalueprovider Getvalueprovider ()
21: {
22:namevaluecollection requestdata = new NameValueCollection ();
23:requestdata.add ("foo", "abc");
24:requestdata.add ("Bar", "123");
25:requestdata.add ("Baz", "123.45");
26:return New Namevaluecollectionvalueprovider (RequestData, CultureInfo.InvariantCulture);
27:}
28:public void Action (string foo, [Bind (prefix= "baz")]double bar)
29: {
30:response.write (String. Format ("{0}: {1}<br/>", "foo", Foo));
31:response.write (String. Format ("{0}: {1}<br/>", "Bar", bar));
32:}
33:}

Related Article

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.