自定义模型粘合剂不会触发

时间:2013-04-05 00:18:32

标签: c# asp.net-mvc-4 model-binding

我在global.asax中为MyList注册了一个自定义模型绑定器。但是,模型绑定器不会触发嵌套属性,对于简单类型,它可以正常工作。在下面的示例中,它会触发Index()但不会触发Index2()

Global.asax中

protected void Application_Start()
{
    AreaRegistration.RegisterAllAreas();

    ModelBinders.Binders.Add(typeof(MyList), new MyListBinder());

    WebApiConfig.Register(GlobalConfiguration.Configuration);
    FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
    RouteConfig.RegisterRoutes(RouteTable.Routes);
}

代码:

public class MyListBinder : IModelBinder
{
    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        return new MyList();
    }
}

public class MyList
{
    public List<int> items { get; set; }
}

public class MyListWrapper
{
    public MyList listItems { get; set; }
}

public class TestController : Controller
{
    public ActionResult Index(MyList list)  // ModelBinder fires :-)
    {            
        return View();
    }

    public ActionResult Index2(MyListWrapper wrapper) // ModelBinder does not fire! :-(
    {
        return View();
    }
}

4 个答案:

答案 0 :(得分:2)

模型绑定器用于允许操作接受复杂对象类型作为参数。应通过POST请求生成这些复杂类型,例如,通过提交表单。如果您有一个高度复杂的对象,无法通过默认的模型绑定器绑定(或者它不会有效),您可以使用自定义模型绑定器。

回答您的问题: 如果您也没有为MyListWrapper类添加自定义模型绑定器,则不会在GET请求中调用MyListBinder)的BindModel,这就是ASP.NET MVC的工作方式。 但是,如果通过添加带有MyListWrapper参数的POST操作来修改代码,则可以看到正确调用了BindModel方法。

[HttpGet]
public ActionResult Index2()  // ModelBinder doesn't fire
{
    return View();
}

[HttpPost]
public ActionResult Index2(MyListWrapper wrapper) // ModelBinder fires
{
    return View();
}

和Index2视图

@model fun.web.MyListWrapper

@using (Html.BeginForm())
{
    @Html.HiddenFor(m => m.listItems)
    <input type="submit" value="Submit" />
}

如果您希望“控制”GET请求中的操作参数,则应使用action filters

答案 1 :(得分:2)

您为MyList定义了绑定器,因此仅当操作方法输入参数的类型为MyList时才触发。

ModelBinders.Binders.Add(typeof(MyList), new MyListBinder());

如果您希望模型绑定器在您的MyList嵌套到其他模型时触发,则必须执行此操作:

[ModelBinder(typeof(MyListBinder))] 
public class MyList
{
    public List<int> items { get; set; }
}

然后,模型绑定器会在遇到MyList类型时触发,即使它是嵌套的。

答案 2 :(得分:1)

将此添加到您的全局:

ModelBinders.Binders.Add(typeof(MyListWrapper), new MyListWrapperBinder());

然后创建一个可以处理绑定的MyListWrapperBinder。

答案 3 :(得分:0)

您的模型绑定器与您的MyList类匹配,而不是与MyListWrapper匹配。 MyListBinder仅用于MyList类或从MyClass继承的类。