[MVC] Custom model binder, assigning a value from a form to a model

Source: Internet
Author: User

First, the problem of wonderful flowers

Before I built the wheel, encountered a very strange problem, although the demand is very wonderful, but still try to solve the

When a submitted form contains multiple fields with duplicate names, for example

<form action="/test/save"Method="Post"> <!--omit other fields-<input type="text"Name="value"/> <input type="text"Name="value"/> <input type="text"Name="value"/> <!--There may be more input--> <input with name value type="Submit"Value="Submit"/></form>
Html

If a model needs to be received in action, the usual solution is to use a ienumerable<t> type or its derived type to receive data to ensure the completion of the data, such as a model

    Public class Test    {        // omit other fields         Public string Get Set ; }    }    
Model

Generally speaking, there's nothing wrong with this, but the problem is.

If I need to split the result with a comma (,) and output it, then I need to write a line of code string. Join (",", model. Test); , no matter where it is.

If you do not do string concatenation on the model field, it will also cause the model to not be reused. And the code looks very elegant.

Second, the question of thinking

I sent the question to Bo . The. Net MVC model receives parameter issues

The general answer is the solution I said above, which seems to be not what I want.

Try to think for a moment.

The standard HTTP request is received when, for MVC, he is just a form or a querystring (if you understand the error, please correct), then how does the MVC framework do to bind a form to a model?

Why did the corresponding field in HttpContext.Request.Form complete the string concatenation?

Why is the assignment of the form and the model different? Can I use the values in the form?

With the problem, poked a degree Niang, found a surprise thing, model Binder (Modelbinder)

Concept I will not post, see this great God's blog ASP. MVC5 Modelbinder

This is a core, ASP. NET core MVC Model Binding:custom binders

Third, the solution

1. Build a model binder of your own

Framework:

     Public class Testmodelbinder:defaultmodelbinder, Imodelbinder    {        publicoverrideobject  Bindmodel (ControllerContext controllercontext, Modelbindingcontext BindingContext)        {            varbase. Bindmodel (ControllerContext, BindingContext);             // Do something for model to format from Form or            Other place return model;        }    }

Core:

     Public class Testmodelbinder:imodelbinder    {        public  Task bindmodelasync (modelbindingcontext bindingcontext)        {            var model = Bindingcontext.model;             // Do something for model to format from Form or other place = modelbindingresult.success (model);                          return task.completedtask;        }    }

As long as the annotation is in place, the model needs to be assigned a field to operate on it.

PS: The specific operation of the benevolent see, simply say my own practice, reflection traversal of the model type string field, if the Model field value is inconsistent with the name of the form, the form is assigned a value from the new field.

The efficiency of this approach has yet to be improved, but this is the first solution.

Okay, the model binder is there, but it's not available yet.

2. Define the provider of the model binder

This method is written in the blog of the Great God above.

Framework:

 Public class testmodelbinderprovider:imodelbinderprovider{    public  imodelbinder getbinder (Type Modeltype)        {iftypeof(Test))        {            returnNew  Testmodelbinder ();        }         return NULL ;    }}

The type passed in here is the type of the model itself and is used to filter for some models to take effect, typically using the default binder Defaultmodelbinder .

Core:

 Public class Testmodelbinderprovider:imodelbinderprovider    {        public  imodelbinder getbinder (modelbinderprovidercontext context)        {            if  typeof(DateTime))            {                returnnew  Testmodelbinder () ;            }             return  NULL ;        }    }

In addition to the same parameters, the two versions are basically a bit of a hair.

3. Global Registration

A model binder that is defined as a global can be started when all models are bound. There is no need to add anything else, but at the same time the problem is that using a native binder requires a separate declaration on the parameters.

The framework is inside the global.asax.

 Public class mvcapplication:system.web.httpapplication{    protectedvoid  Application_Start ()    {        ModelBinderProviders.BinderProviders.Insert (0New   Testmodelbinderprovider ());     // or you can do the following, two options        // ModelBinders.Binders.Add (typeof (Test), New Testmodelbinder ());       }}

The core is in the Startup.cs.

 Public void configureservices (iservicecollection services) {        = = {                option. Modelbinderproviders.insert (0new  Testmodelbinderprovider ());    })

4. Defining Model Binding Properties

In the case of a special binder, we can choose to define the binder as a property

Framework:

false false )]    publicclass  formformatattribute:custommodelbinderattribute    {         publicoverride  imodelbinder getbinder ()        {            return  New  Testmodelbinder ();        }    }

Core:

    false false )]    publicclass  testmodelbinderattribute:modelbinderattribute    {          Public Base (typeof(testmodelbinder))        {        }    }

It's almost like a hair.

The invocation method of the property is identical, and the parameter is preceded by [Testmodelbinder] .

Summarize:

After a toss-up, the model binder is done, and the variable can be more elegantly bound. There's no need for a bunch of stitching strings ah, extra attributes ah, that sort of thing.

However, it is important to note that the core binder does not have a default base class (or maybe I did not find, if found, if there is trouble to find the Welcome to share), so you can not like the framework first let the default processing, processing and processing. Instead, it needs to be handled manually by the developer.

[MVC] Custom model binder, assigning a value from a form to a model

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.