有没有充分的理由不在OnActionExecuted中删除有效的ModelState条目?

时间:2013-11-13 01:12:36

标签: c# asp.net-mvc

我发现对ASP.NET MVC非常讨厌的一点是,在POST请求期间,ModelState值非常持久,使用@ Html。*扩展方法。我知道ModelState允许持久存在无效的用户输入值,但是,即使对于用户输入值有效的属性,MVC对ModelState的处理也会继续。有时,这是不良行为。

例如,如果您在URL中有ID,并且您在视图模型中将ID属性设置为不同的值(这是一个好的迹象,ID名称需要更具体,但请耐心等待) ,您设置的值将在GET请求期间生成,但在POST期间,将使用ModelState中的值,该值将来自路径。

发布的值也会发生这种情况。如果由于某种原因,您需要更改来自客户端的值,则将忽略模型中的新值;你还必须(或者更新)更新ModelState。

为解决这种不一致问题,我已将此动作过滤器添加到我的MVC项目中作为全局过滤器:

public class RemoveValidModelStateFilterAttribute : ActionFilterAttribute
{
    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        var modelState = filterContext.Controller.ViewData.ModelState;
        var keys = modelState.Keys.ToArray();
        foreach (var key in keys)
        {
            var entry = modelState[key];
            if (entry.Errors.Count == 0)
                modelState.Remove(key);
        }
    }
}

到目前为止,它一直很适合我,但我很好奇我是否无意中造成任何问题或失去功能。我只在我可以完全控制的新项目和项目上使用它,因此它不会创建隐藏的值,而不会传达值。

我可以看到其他开发人员在处理我的项目时可能会感到困惑,但我不知道任何其他副作用。

1 个答案:

答案 0 :(得分:0)

ModelState用于重新填充表单上未成功提交并读入模型的任何值。然后使用这些值重新填充表格。我认为最好的例子是用于验证目的,例如你有一个模特:

public class TestModel
{
    public DateTime { get;set;}
}

您的控制器可能如下所示:

public class TestController : Controller
{
    public ActionResult Index()
    {
        return View(new TestModel());
    }

    [HttpPost]
    public ActionResult Index(TestModel model)
    {
        return View(model);
    }
}

在您的视图中,您可以将该日期表示为文本框输入。如果用户键入有效日期并提交表单,则页面将使用提交的模型中该文本框中填充的值重新加载。到现在为止还挺好。但是,如果用户输入无效日期,则TestModel不能被打包(因为该属性将无效),因此MVC使用ModelState来重新填充文本框。如果每次都清除模型状态,最终会出现验证错误,但会出现空白文本框而不是用户先前输入的内容。

在您的情况下可能不是问题,但我会谨慎地清除所有操作,以防您以后需要此功能。