ror*_*ryf 7 asp.net-mvc model-binding
是否可以将我的模型上的外键关系绑定到表单输入?
说我Car和之间有一对多的关系Manufacturer.我想要一个更新表单,Car其中包括用于设置的选择输入Manufacturer.我希望能够使用内置的模型绑定来做到这一点,但我开始认为我必须自己做.
我的动作方法签名如下所示:
public JsonResult Save(int id, [Bind(Include="Name, Description, Manufacturer")]Car car)
Run Code Online (Sandbox Code Playgroud)
表单发布值Name,Description和Manufacturer,其中Manufacturer是类型的主键int.名称和描述设置正确,但不是制造商,这是有道理的,因为模型绑定器不知道PK字段是什么.这是否意味着我必须写一个IModelBinder它知道这个的自定义?我不确定这是如何工作的,因为我的数据访问存储库是通过每个Controller构造函数上的IoC容器加载的.
这是我的看法 - 这是一个自定义模型绑定器,当被问到GetPropertyValue时,查看该属性是否是我的模型程序集中的对象,并在我的NInject IKernel中注册了一个IRepository <>.如果它可以从Ninject获取IRepository,它会使用它来检索外键对象.
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;
#if DEBUG
Check.Require( repository, "{0} is not available for use in binding".FormatWith( specificRepositoryType.FullName ) );
#endif
if ( repository != null && Int32.TryParse( key, out id ) )
{
return repository.InvokeMethod( "GetById", id );
}
}
return null;
}
/// <summary>
/// perform simple check to see if we should even bother looking for a repository
/// </summary>
private bool CheckRepository( Type propertyType )
{
return propertyType.HasInterface<IModelObject>();
}
}
Run Code Online (Sandbox Code Playgroud)
您显然可以将Ninject替换为您的DI容器和您自己的存储库类型.
| 归档时间: |
|
| 查看次数: |
9564 次 |
| 最近记录: |