Custom model bindings for ASP.

Source: Internet
Author: User

Recently in the study of the ASP. NET MVC model, it is found that Defaultmodelbinder has a disadvantage, that is, the browser request parameters can not be customized, the original idea is to set the attributes of the Entity model properties (Attribute), Then, by obtaining the attribute value of the set, we study the long-time MVC source and find that the BindProperty method can be used to achieve the desired goal by rewriting the Defaultmodelbinder.

There is a custom model binding attribute in ASP. Custommodelbinderattribute, which is intended to be done by overriding the Custommodelbinderattribute to the entity properties, as follows:

[AttributeUsageAttribute (attributetargets.class| Attributetargets.struct| attributetargets.enum| attributetargets.interface| Attributetargets.parameter, AllowMultiple = False, inherited = False)]public abstract class Custommodelbinderattribute: Attribute

However, since Custommodelbinderattribute does not support setting attributes on properties, it has to inherit the Attribute class to write a feature, the code is as follows:

    <summary>///Represents an attribute that invokes a custom model binder. </summary> [AttributeUsage (validtargets, AllowMultiple = False, inherited = False)] public class Propertym        Odelbinderattribute:attribute {//<summary>///Specify the application element that this attribute can apply attributes to. </summary> Internal const AttributeTargets Validtargets = Attributetargets.field | Attributetargets.enum | Attributetargets.property |        Attributetargets.parameter;        <summary>//Declaration property name. </summary> private String _propertyname = String.        Empty;        <summary>////Gets or sets the property alias.        </summary> public string PropertyName {get {return _propertyname;}        }///<summary>//Use the specified property alias. </summary>//<param name= "propertyname" > Specified property alias. </param> public Propertymodelbinderattribute (String propertyname) {_propertyname = prOpertyname;        }///<summary>///Retrieve the associated model binder: </summary>///<returns> references to objects that implement the System.Web.Mvc.IModelBinder interface.        </returns> public Imodelbinder Getbinder () {return new Propertymodelbinder (); }

This allows you to set an alias on the properties of the entity model.

    <summary>///    represents a City filter entity Object model. //    </summary>    [Modelbinder (typeof (Propertymodelbinder))]    public class Cityfilteringmodel:baseentitymodel    {        //<summary>///To get or set the city English name. //        </summary> public        string Cityenglishname {get; set;}        <summary>        ///Get or set the city number. //        </summary>        [Propertymodelbinder ("CID")]        public int Cityid {get; set;}        <summary>        ///Get or set the city name. //        </summary>        [Propertymodelbinder ("CNAME")]        public string CityName {get; set;}    }

Finally, the BindProperty and SetProperty methods of overriding defaultmodelbinder can be used to customize the properties of the model binding.

    <summary>///Map a browser request to a data object. </summary> public class Propertymodelbinder:defaultmodelbinder {//<summary>//early        Initializes a new instance of the <see cref= "Propertymodelbinder"/> class. </summary> public Propertymodelbinder () {}///<summary>//using the specified controller        The following and binding contexts bind the model. </summary>//<param name= "ControllerContext" > Run the controller's context. </param>//<param name= "BindingContext" > the context of the binding model. </param>///<returns> objects that are bound. </returns> public override Object Bindmodel (ControllerContext controllercontext, Modelbindingcontext BINDINGC Ontext) {var model = base.            Bindmodel (ControllerContext, BindingContext); if (model is Baseentirymodel) ((Baseentirymodel) model).            Bindmodel (ControllerContext, BindingContext);        return model; }///<summary>///Use the specified controller context, binding context, property descriptor, and property binder to returnReturns the property value. </summary>//<param name= "ControllerContext" > Run the controller's context. </param>//<param name= "BindingContext" > the context of the binding model. </param>//<param name= "PropertyDescriptor" > Descriptor of the property to be accessed. </param>//<param name= "Propertybinder" > An object that provides a way to bind properties. </param>///<returns> An object that represents the property value. </returns> protected Override Object GetPropertyValue (ControllerContext controllercontext, Modelbindingcontex            T BindingContext, System.ComponentModel.PropertyDescriptor PropertyDescriptor, Imodelbinder propertybinder) { var value = base.            GetPropertyValue (ControllerContext, BindingContext, PropertyDescriptor, Propertybinder);        return value;        }///<summary> binds the specified property with the specified controller context, binding context, and specified property descriptor. </summary>//<param name= "ControllerContext" > Run the controller's context. </param>//<param name= "BindingContext" > the context of the binding model. </param>//<param name= "PropertyDescriptor" > describes the properties to bind. </param> protected override void BindProperty (ControllerContext controllercontext, Modelbindingcontext Bindin Gcontext, PropertyDescriptor propertydescriptor) {string fullpropertykey = Createsubpropertyname (Bindin            Gcontext.modelname, Propertydescriptor.name);            Object propertyvalue = null;  if (propertydescriptor.attributes[typeof (propertymodelbinderattribute)]! = null) {var attribute                = (Propertymodelbinderattribute) propertydescriptor.attributes[typeof (Propertymodelbinderattribute)]; String propertyname = attribute.                PropertyName;                var valueresult = BindingContext.ValueProvider.GetValue (PropertyName);            if (Valueresult! = null) PropertyValue = Valueresult.attemptedvalue; } else {if (!bindingcontext.valueprovider.containsprefix (Fullpropertykey)) {return; }}//Call to the property ' s model binder Imodelbinder Propertybinder = Binders.getbin            Der (Propertydescriptor.propertytype);            Object originalpropertyvalue = Propertydescriptor.getvalue (Bindingcontext.model);            Modelmetadata propertymetadata = Bindingcontext.propertymetadata[propertydescriptor.name];            Propertymetadata.model = Originalpropertyvalue; Modelbindingcontext innerbindingcontext = new Modelbindingcontext () {modelmetadata = Propertyme                Tadata, modelname = fullpropertykey, modelstate = Bindingcontext.modelstate,            Valueprovider = Bindingcontext.valueprovider}; Object newpropertyvalue = GetPropertyValue (ControllerContext, Innerbindingcontext, PropertyDescriptor,            Propertybinder); if (Newpropertyvalue = = null) {NewpropertYvalue = PropertyValue;            } Propertymetadata.model = Newpropertyvalue;            Validation modelstate modelstate = Bindingcontext.modelstate[fullpropertykey]; if (modelstate = = NULL | | modelState.Errors.Count = = 0) {if (Onpropertyvalidating (Controllercon Text, BindingContext, PropertyDescriptor, Newpropertyvalue)) {SetProperty (Controllercon                    Text, BindingContext, PropertyDescriptor, Newpropertyvalue);                Onpropertyvalidated (ControllerContext, BindingContext, PropertyDescriptor, Newpropertyvalue); }} else {SetProperty (ControllerContext, BindingContext, Propertydescript                Or, Newpropertyvalue);  Convert formatexceptions (type conversion failures) into Invalidvalue messages foreach (modelerror error In ModelState.Errors.Where (err = String.IsNullOrEmpty (err. ErrorMessage) &Amp;& Err. Exception! = null). ToList ()) {for (Exception Exception = error. Exception; Exception! = NULL; Exception = exception. innerexception) {//We only consider ' known ' type of exception and do                        Too aggressive changes here if (Exception are FormatException | | exception is OverflowException)                            {String displayName = Propertymetadata.getdisplayname ();                            String errormessagetemplate = Getvalueinvalidresource (ControllerContext); String errormessage = String.Format (CultureInfo.CurrentCulture, Errormessagetemplate,                            ModelState.Value.AttemptedValue, DisplayName);                            ModelState.Errors.Remove (Error);                            MODELSTATE.ERRORS.ADD (errormessage);                        Break       }                    }                }     }//base.        BindProperty (ControllerContext, BindingContext, PropertyDescriptor);        }///<summary>///Use the specified controller context, binding context, and property value to set the specified property. </summary>//<param name= "ControllerContext" > Run the controller's context. </param>//<param name= "BindingContext" > the context of the binding model. </param>//<param name= "PropertyDescriptor" > describes the properties to bind. </param>//<param name= "value" > the value set for the property. </param> protected override void SetProperty (ControllerContext controllercontext, modelbindingcontext binding Context, PropertyDescriptor PropertyDescriptor, object value) {Modelmetadata PropertyMetadata = Binding            Context.propertymetadata[propertydescriptor.name];            Propertymetadata.model = value;            String modelstatekey = Createsubpropertyname (Bindingcontext.modelname, propertymetadata.propertyname); if (value = = null && BindingContext.ModelState.IsValidField (ModelSTatekey)) {Modelvalidator requiredvalidator = ModelValidatorProviders.Providers.GetValidators (P Ropertymetadata, ControllerContext). Where (v = v.isrequired).                FirstOrDefault (); if (requiredvalidator! = null) {foreach (Modelvalidationresult validationresult in requ Iredvalidator.validate (Bindingcontext.model)) {BindingContext.ModelState.AddMod                    Elerror (Modelstatekey, validationresult.message); }}} bool Isnullvalueonnonnullabletype = value = = NULL &&!            Typeallowsnullvalue (Propertydescriptor.propertytype);                if (!propertydescriptor.isreadonly &&!isnullvalueonnonnullabletype) {try {var typevalue = Convert.changetype (value, Propertydescriptor.propertytype, Cultureinfo.invariantcul                    ture); Propertydescriptor.setvalue (Bindingcontext.model, Typevalue); } catch (Exception ex) {if (BindingContext.ModelState.IsValidField (model                    Statekey)) {bindingContext.ModelState.AddModelError (Modelstatekey, ex); }}} if (Isnullvalueonnonnullabletype && bindingcontext.modelst Ate. Isvalidfield (Modelstatekey)) {BindingContext.ModelState.AddModelError (Modelstatekey, Getvaluere            Quiredresource (ControllerContext));        }}///<summary>///Use the specified controller context and binding context to return the properties of the model. </summary>//<param name= "ControllerContext" > Run the controller's context. </param>//<param name= "BindingContext" > the context of the binding model. </param>///<returns> A collection of property descriptors. </returns> protected override PropertyDescriptorCollection getmodelproperties (ControllerContext Controllercon Text, MoDelbindingcontext bindingcontext) {bindingcontext.propertyfilter = new predicate<string> (pred); var values = base.            Getmodelproperties (ControllerContext, BindingContext);        return values;        }///<summary>///Get the decision object for the property filter. </summary>//<param name= The properties of the "target" > property filter. </param>///<returns> a Boolean value.        </returns> protected bool Pred (string target) {return true;        #region Private ...///<summary>///type allows null values. </summary>//<param name= "type" > Specified type. </param>///<returns> returns True if the type value is NULL, otherwise false is returned. </returns> private static bool Typeallowsnullvalue (type type) {return (!type. Isvaluetype | |        Isnullablevaluetype (type));        }///<summary>//is a nullable value type. </summary>//<param name= "type" > Specifyof the type. </param>///<returns> returns True if the type value is NULL, otherwise false is returned. </returns> private static bool Isnullablevaluetype (type type) {return Nullable.getunderlyi        Ngtype (type)! = NULL;        }///<summary>///For resources with invalid value. </summary>//<param name= "ControllerContext" ></param>//<returns></return  s> private static string Getvalueinvalidresource (ControllerContext controllercontext) {return Getuserresourcestring (ControllerContext, "Propertyvalueinvalid")??        "The value ' {0} ' is not valid for {1}.";        }///<summary>///Get the resources you need for value. </summary>//<param name= "ControllerContext" ></param>//<returns></return s> private static string Getvaluerequiredresource (ControllerContext controllercontext) {retur N getuserresourcestring (ControllerContext, "PropertyvaluErequired ")??        "A value is required.";            } private static string getuserresourcestring (ControllerContext controllercontext, string resourcename) {            string result = NULL; if (! String.IsNullOrEmpty (Resourceclasskey) && (controllercontext! = null) && ( Controllercontext.httpcontext = null)) {result = ControllerContext.HttpContext.GetGlobalResour            Ceobject (Resourceclasskey, resourcename, cultureinfo.currentuiculture) as String;        } return result; } #endregion}

It is important to note that [Modelbinder (typeof (Propertymodelbinder)]) is set on the class of the entity model and is registered in Global.

        ModelBinders.Binders.Clear ();        ModelBinders.Binders.Add (typeof (Propertysoukemodel), New Propertymodelbinder ());

  

Custom model bindings for ASP.

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.