【转】ASP.NET MVC 3 Service Location, Part 9: Model Binders
Model Binders
ASP.NET MVC 1.0 introduced the IModelBinder interface. Developers who implement this interface are responsible for creating models from values obtained from value providers. In ASP.NET MVC 3, we introduced a new interface (IModelBinderProvider) which allows developers to dynamically provide implementations of IModelBinder. We have made IModelBinderProvider instances findable via the dependency resolver.
Disclaimer
This blog post talks about ASP.NET MVC 3 Beta, which is a pre-release version. Specific technical details may change before the final release of MVC 3. This release is designed to elicit feedback on features with enough time to make meaningful changes before MVC 3 ships, so please comment on this blog post or contact me if you have comments.
Implementing IModelBinderProvider
In prior versions of MVC, developers could only register static mappings from types to model binder instances (throughModelBinders.Binders). While this satisfied simple uses, it made complex and powerful model binders a little more challenging to write.
When we decided to open model binding up for dependency resolution, we knew that we were going to need to introduce a layer of indirection, since model binders are usually only valid for a limited number of types (unless you are the default model binder).
We solved both problems by introducing a new interface:
public interface IModelBinderProvider { IModelBinder GetBinder(Type modelType); }
Developers who implement this interface can optionally return an implementation of IModelBinder for a given type (they should return null if they cannot create a binder for the given type).
The system continues to rely on a “default model binder” if the system cannot find any appropriate model binder for the given type. You can change the default model binder by setting ModelBinders.Binders.DefaultBinder. Out of the box, this is set to an instance of DefaultModelBinder.
There are no implementations of IModelBinderProvider in MVC. However, there is a similar system in MVC Futures from MVC 2 (in the ModelBinding folder), and there are several model binder providers that could be used to spark ideas about writing providers for MVC 3, including model binder providers for arrays, binary data, collections, complex objects, and dictionaries.
Location: IModelBinderProvider
This is a “multiply registered” style service introduced in MVC 3. The static registration point for this service is at ModelBinderProviders.BinderProviders for non-DI users.
The logic in ModelBinderProviderCollection (which implements ModelBinderProviders.BinderProviders) consults the dependency resolver, calling GetSerivces(typeof(IModelBinderProvider)) and adding any services found to the list of statically registered services. Model binder provides are run in-order, with a “first one to provide a model binder wins” strategy, so registration order is important. The providers found in the dependency resolver will always run in the order they are returned from the resolver (and before the static registered providers).
What’s Next?
Next up we’ll look at the new Controller Activator service.