2

我发现 ASP.NET MVC 非常烦人的一点是 ModelState 值在 POST 请求期间使用 @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);
        }
    }
}

到目前为止,它对我来说一直运行良好,但我很好奇我是否无意中制造了任何问题或失去了功能。我只在新项目和我可以完全控制的项目上使用它,所以它不会产生价值不被传达的隐藏问题。

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

4

1 回答 1

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 来重新填充文本框。如果每次都清除模型状态,最终会出现验证错误,但会出现空白文本框,而不是用户之前输入的内容。

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

于 2013-11-13T01:37:31.717 回答