asp.net-mvc - ASP.NET MVC 模型绑定(bind)外键关系

标签 asp.net-mvc model-binding

是否可以将我的模型上的外键关系绑定(bind)到表单输入?

假设我在 Car 之间存在一对多关系和 Manufacturer .我想要一个更新表格Car包括用于设置 Manufacturer 的选择输入.我希望能够使用内置模型绑定(bind)来做到这一点,但我开始认为我必须自己做。

我的操作方法签名如下所示:

public JsonResult Save(int id, [Bind(Include="Name, Description, Manufacturer")]Car car)

表单发布值名称、描述和制造商,其中制造商是 int 类型的主键.名称和描述设置正确,但制造商设置不正确,这是有道理的,因为模型绑定(bind)器不知道 PK 字段是什么。这是否意味着我必须编写自定义 IModelBinder那它知道吗?我不确定这将如何工作,因为我的数据访问存储库是通过每个 Controller 上的 IoC 容器加载的。构造函数。

最佳答案

这是我的看法 - 这是一个自定义模型绑定(bind)器,当要求 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>();
    }

}

您显然可以用 Ninject 代替您的 DI 容器和您自己的存储库类型。

关于asp.net-mvc - ASP.NET MVC 模型绑定(bind)外键关系,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/662651/

相关文章:

jquery - ASP.NET-MVC jQuery 不显眼的远程验证返回误报

c# - 使用 Apache Lucene 进行搜索

c# - 如何在 Azure Functions 中使用 Http 触发器进行模型绑定(bind)?

asp.net-mvc - Asp mvc 4模型与post方法绑定(bind)

c# - 如何获得对模型绑定(bind)的控制?

asp.net-mvc - {01/01/0001 00 :00:00} being passed as default date and time, MVC 2

c# - 如何从集成测试将文件上传到端点

c# - MVC 5 : Custom AuthorizeAttribute and Caching

c# - 默认模型绑定(bind)器不绑定(bind) IEnumerable 中的 Nullable 类型

asp.net-mvc - 如何使 ASP.Net MVC 模型绑定(bind)器将传入日期视为 UTC?