First, create a custom model binder:
The process of modeling a model object with request data and passing an object to an action parameter is called model binding.
Most of the time the action parameter is the primary key or other unique identifier of the object, so we do not have to place a duplicate data access code in all the actions (the "\\Before" section of the code below), but instead use a custom model binder (the "\\After" section of the code below). It can load the storage object before the action executes, so the action no longer has a unique identifier but a persisted object type as a parameter.
// before var profile=_profilerepository.getbyid (ID); return View (new Profileeditmodel (profile)); // after return View (new Profileeditmodel (id)); }
The extensibility of MVC allows us to register the model binder, which is achieved by specifying the binder that should be used for a model type. But in the case of many entities, it is desirable that we only register a custom model binder for a common base type (Common base types) or let each custom binder decide for itself whether it should be bound. To achieve this, we need to provide both a custom model binder provider and a custom model binder. The provider is used by the MVC framework to determine which model binder to use for model binding.
In order to implement a custom model binder provider, we need to implement the Imodelbinderprovider interface:
Public Interface imodelbinderprovider{ imodelbinder getbinder (Type modeltype) }
Any implementation of the Imodelbinderprovider that wants to use custom matching logic only needs to detect the type of model passed in and determine if a custom model binder instance can be returned.
An implementation of the custom model binder provider:
Public class entitymodelbinderprovider:imodelbinderprovider{ public imodelbinder getbinder (Type Modeltype) { if(! typeof(Entity). Isassignable (Modeltype)) returnnull; return New Entitymodelbinder (); }}
In the previous example, we first check whether the Modeltype parameter inherits from entity, and if not, returns Null to indicate that the model binder provider cannot provide a model binder for this given type, and instead returns a new instance of the Entitymodelbinder (Entity model Binder).
The complete model binder needs to implement the Imodelbinder interface:
Public classentitymodelbinder:imodelbinder{ Public ObjectBindmodel (ControllerContext controllercontext, Modelbindercontext bindingcontext) {ValuePro Viderresult value=Bindingcontext.valueprovider. GetValue (Bindingcontext.modelname); if(value==NULL) return NULL; if(string. IsNullOrEmpty (value. Attemptedvalue))return NULL; intEntityId; if(!int. TryParse (value. Attemptedvalue, outEntityId)) { return NULL; } Type Repositorytype=typeof(irepository<>) . MakeGenericType (Bindingcontext.modeltype); varrepository=(irepository) servicelocator. Resolve (Repositorytype); Entity entity=Repository. GetById (EntityId); returnentity; }}
Public Interface Irepository<tentity> where tentity:entity{ TEntity Get (int ID);}
To register a custom model binder provider:
protected void Application_Start () { modelbinderproviders.binderproviders . ADD (new Entitymodelbinderprovider ());}
Second, use a custom value provider:
By creating an additional custom value provider we can further eliminate the query code in the controller action:
//before PublicViewResult Logonwidget (Logonwidgetmodel model) {BOOLInauthenticated=request.isauthenticated; Model. IsAuthenticated=isauthenticated; Model. CurrentUser=session[""]; returnView (model);}// After PublicViewResult Logonwidget (Logonwidgetmodel model) {BOOLInauthenticated=request.isauthenticated; Model. IsAuthenticated=isauthenticated; returnView (model);}
I feel that I would like to skip it, do not understand ...
"ASP 4 Real Combat" Learning Note 11: Model Binder and value provider