Learning notes for ASP. net mvc 4 practice 11: Model binder and value providers,
1. Create a custom model Binder:
The process of creating a Model object using request data and passing the object to an action parameter is called Model Binding ).
Most of the time, the action parameter is the primary key of the object or other unique identifiers, so we do not have to place a piece of repeated data access code in all actions (the code "\ Before" below ), instead, use a custom model binder (the code "\ After" below ). It can load the storage object before the action is executed, so the action is no longer a unique identifier but a persistent object type as a parameter.
// Beforepublic ViewResult Edit (Guid id){ var profile=_profileRepository.GetById(id); return View(new ProfileEditModel(profile)); }// Afterpublic ViewResult Edit (Profile id){ return View(new ProfileEditModel(id)); }
The scalability of MVC allows us to register the model binder, which is achieved by specifying the binder that should be used for a model type. However, when there are many entities, the ideal situation is that we only have one Common Base Type) the user-defined model Binder for one registration or let each user-defined binder decide whether to bind. To implement this function, we need to provide both the user-defined model binder and the user-defined model binder. The provider is used by the MVC framework to determine which model binder to use for model binding.
To implement a custom model binder provider, we need to implement the IModelBinderProvider interface:
public interface IModelBinderProvider{ IModelBinder GetBinder(Type modelType) }
Any implementation of IModelBinderProvider that wants to use the custom matching logic only needs to detect the passed model type and determine whether to return the custom model binder instance.
An Implementation of the custom model binder provider:
public class EntityModelBinderProvider:IModelBinderProvider{ public IModelBinder GetBinder(Type modelType) { if(!typeof(Entity).IsAssignable(modelType)) return null; return new EntityModelBinder(); }}
In the above example, we first check whether the modelType parameter inherits from Entity. If not, null is returned, indicating that the model binder provider cannot provide the model Binder for the given type, otherwise, a new instance of EntityModelBinder is returned.
The complete model binder must implement the IModelBinder interface:
public class EntityModelBinder:IModelBinder{ public object BindModel( ControllerContext controllerContext, ModelBinderContext bindingContext) { ValueProviderResult value= bindingContext.ValueProvider .GetValue(bindingContext.ModelName); if(value==null) return null; if(string.IsNullOrEmpty(value.AttemptedValue)) return null; int entityId; if(!int.TryParse(value.AttemptedValue,out entityId)) { return null; } Type repositoryType=typeof(IRepository<>) .MakeGenericType(bindingContext.ModelType); var repository=(IRepository)ServiceLocator .Resolve(repositoryType); Entity entity=repository.GetById(entityId); return entity; }}
public interface IRepository<TEntity> where TEntity:Entity{ TEntity Get(int id);}
Register the custom model binder provider:
protected void Application_Start(){ ModelBinderProviders.BinderProviders .Add(new EntityModelBinderProvider());}
2. Use the custom value provider:
By creating an additional custom value provider, we can further eliminate the query code in the Controller action:
// Beforepublic ViewResult LogOnWidget(LogOnWidgetModel model){ bool inAuthenticated=Request.IsAuthenticated; model.IsAuthenticated=isAuthenticated; model.CurrentUser=Session[""]; return View(model);}// Afterpublic ViewResult LogOnWidget(LogOnWidgetModel model){ bool inAuthenticated=Request.IsAuthenticated; model.IsAuthenticated=isAuthenticated; return View(model);}
I feel like I have skipped it for the moment. I don't understand it...