Here, my trick is a custom mediator that, when requested by GetPropertyValue, checks to see if the property is an object from my model assembly and has an IRepository <> registered in my NInject IKernel. If he can get an IRepository from Ninject, he uses this to retrieve the foreign key object.
public class ForeignKeyModelBinder : System.Web.Mvc.DefaultModelBinder { private IKernel serviceLocator; public ForeignKeyModelBinder( IKernel serviceLocator ) { Check.Require( serviceLocator, "IKernel is required" ); this.serviceLocator = serviceLocator; } /// <summary> /// if the property type being asked for has a IRepository registered in the service locator, /// use that to retrieve the instance. if not, use the default behavior. /// </summary> protected override object GetPropertyValue( ControllerContext controllerContext, ModelBindingContext bindingContext, PropertyDescriptor propertyDescriptor, IModelBinder propertyBinder ) { var submittedValue = bindingContext.ValueProvider.GetValue( bindingContext.ModelName ); if ( submittedValue == null ) { string fullPropertyKey = CreateSubPropertyName( bindingContext.ModelName, "Id" ); submittedValue = bindingContext.ValueProvider.GetValue( fullPropertyKey ); } if ( submittedValue != null ) { var value = TryGetFromRepository( submittedValue.AttemptedValue, propertyDescriptor.PropertyType ); if ( value != null ) return value; } return base.GetPropertyValue( controllerContext, bindingContext, propertyDescriptor, propertyBinder ); } protected override object CreateModel( ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType ) { string fullPropertyKey = CreateSubPropertyName( bindingContext.ModelName, "Id" ); var submittedValue = bindingContext.ValueProvider.GetValue( fullPropertyKey ); if ( submittedValue != null ) { var value = TryGetFromRepository( submittedValue.AttemptedValue, modelType ); if ( value != null ) return value; } return base.CreateModel( controllerContext, bindingContext, modelType ); } private object TryGetFromRepository( string key, Type propertyType ) { if ( CheckRepository( propertyType ) && !string.IsNullOrEmpty( key ) ) { Type genericRepositoryType = typeof( IRepository<> ); Type specificRepositoryType = genericRepositoryType.MakeGenericType( propertyType ); var repository = serviceLocator.TryGet( specificRepositoryType ); int id = 0;
you can obviously replace Ninject for your DI container and your own repository type.
dave thieben
source share