【问题标题】:ASP.NET MVC - Mixing Custom and Default Model BindingASP.NET MVC - 混合自定义和默认模型绑定
【发布时间】:2010-03-04 03:48:21
【问题描述】:

我有一个类型:

public class IssueForm
{
    Order Order {get; set;}
    Item Item {get; set;}
    Range Range {get; set;}
}

由于对订单和项目的要求,我创建了一个自定义模型绑定器,但 Range 仍然可以使用默认模型绑定器。

我的自定义模型绑定器中是否有一种方法可以调用默认模型绑定器以返回 Range 对象?我想我只需要正确设置 ModelBindingContext,但我不知道如何。


编辑

查看第一条评论和答案——似乎从默认模型绑定器继承可能很有用。

到目前为止,要为我的设置添加更多细节:

public IssueFormModelBinder : IModelBinder
{
    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        Order = //code to pull the OrderNumber from the context and create an Order
        Item = //code to pull the ItemNumber from the context and create an Item

        IssueForm form = IssueFormFactory.Create(Order, Item);

        form.Range = // ** I'd like to replace my code with a call to the default binder **

        return form
    }
}

这可能是一种愚蠢的做法……这是我的第一个模型活页夹。只是指出我当前的实现。


编辑#2

因此,如果我可以像“我已经完成绑定”方法一样挂钩并使用属性调用 Factory 方法,那么覆盖 BindProperty 的答案将起作用。

我想我真的应该看看 DefaultModelBinder 的实现,别再傻了。

【问题讨论】:

  • 我不确定这是否是最优雅的解决方案,但您能否从 DefaultModelBinder 派生自定义模型绑定器而不是实现 IModelBinder?然后,当您覆盖 BindModel 时,在适当的地方将责任传递给 DefaultModelBinder。否则,使用自定义绑定。
  • 是的,我看到一些模型绑定器脱离了 IModelBinder 和 DefaultModelBinder。我猜 DefaultModelBinder 有一些额外的方法,我假设它是从 BindModel 方法调用的,所以您可以更加关注您的需求?
  • 它只是证实了我决定忽略 ModelBinder 和手动代码输入处理和验证。现在,我拥有一致、透明且可调整的内容,以满足当前和可想象的未来需求。

标签: asp.net-mvc modelbinders


【解决方案1】:

从 DefaultModelBinder 覆盖 BindProperty:

public class CustomModelBinder:DefaultModelBinder
        {
            protected override void BindProperty( ControllerContext controllerContext, ModelBindingContext bindingContext, System.ComponentModel.PropertyDescriptor propertyDescriptor )
            {
                if (propertyDescriptor.PropertyType == typeof(Range))
                {
                    base.BindProperty(controllerContext, bindingContext, propertyDescriptor);
                }
                // bind the other properties here
            }
        }

【讨论】:

  • +1 用于检查属性类型而不是名称。怪魔弦!
【解决方案2】:

试试这样的:

public class CustomModelBinder :  DefaultModelBinder {
    protected override void BindProperty(ControllerContext controllerContext, ModelBindingContext bindingContext, PropertyDescriptor propertyDescriptor) {
        if(propertyDescriptor.Name == "Order") {
            ...
            return;
        }

        if(propertyDescriptor.Name == "Item") {
            ...
            return;
        }

        base.BindProperty(controllerContext, bindingContext, propertyDescriptor);
    }

}

【讨论】:

  • 我可能在这里很愚蠢,但是您如何实现 CustomModelBinder 类,肯定必须在某个地方实例化才能使其工作?也许作为 ActionResult 参数中的一个属性?
【解决方案3】:

我想我会注册两个不同的自定义模型绑定器,一个用于 Order,一个用于 Item,并让默认模型绑定器处理 Range 和 IssueForm。

【讨论】:

  • 是的,我问这个问题显然已经有一段时间了。我最终查看了 DefaultModelBinder 代码并意识到模型绑定的递归性质。我没有意识到对于包含其他复杂类型的复杂类型,我可以为每个单独定义一个模型绑定器。相反,我认为复杂的父母必须知道每个复杂孩子的详细信息。
猜你喜欢
  • 2018-10-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-14
相关资源
最近更新 更多