关于C#:请勿绑定操作的一个参数

Do not bind one parameter of action

我有一个看起来像这样的动作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[Post]
[PopulateModelFromId]
public ActionResult ChangeName( string name, MyModel model )
{
    try
    {
        model.changeName
        return JSONSuccess();
    }
    catch( ModelUpdateException )
    {
        return JSONFail();
    }
}

名称和模型ID由ajax POST发送,并且模型由一个自定义操作过滤器填充,该过滤器采用id并从数据库中检索模型。

actionfilter看起来像这样:

1
2
3
4
5
6
7
8
...
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
    // parse the id from the request
    MyModel model = getModelFromDataStoreById( id );
    filterContext.ActionParameters["model"] = model;
}
...

问题在于MyModel对象没有无参数构造函数,并且MVC甚至在调用ActionFilter之前尝试创建并绑定到MyModel对象,但由于无法实例化MyModel对象而引发异常。铅>

我的第一个问题是我是否正确执行了此操作,还是应该使用HttpContext.Items之类的东西在筛选器和操作之间传输数据?其次,是否有一种方法可以告诉MVC不要尝试绑定MyModel对象,因为它将在以后创建?


自定义模型联编程序似乎比自定义操作过滤器更适合此任务:

1
2
3
4
5
6
7
8
9
10
11
12
public class MyModelBinder : DefaultModelBinder
{
    protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType)
    {
        var id = bindingContext.ValueProvider.GetValue("id");
        if (id != null)
        {
            return GetModelFromDataStoreById(id.AttemptedValue);
        }
        return base.CreateModel(controllerContext, bindingContext, modelType);
    }
}

您要在Application_Start中注册的内容:

1
ModelBinders.Binders.Add(typeof(MyModel), new MyModelBinder());

现在您的控制器动作可能如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
[HttpPost]
public ActionResult ChangeName(string name, MyModel model)
{
    try
    {
        model.ChangeName();
        return JSONSuccess();
    }
    catch (ModelUpdateException)
    {
        return JSONFail();
    }
}