在发布/状态更改后,MVC3模型验证最佳实践重定向

Jac*_*ack 6 redirect asp.net-mvc-3

鉴于网络应用程序应始终在POST后重定向(或任何不可重复的请求更改服务器端状态)...

...人们如何使用MVC3模型验证执行强制重定向?

mar*_*pet 7

通常只有在成功发布后才会重定向(没有模型验证错误),否则您将发回带有验证错误消息的页面.

重定向PRG图案防止双重张贴,所以没有伤害发回同一页面(+错误消息),因为后没有成功,也不会是,除非有变化,使验证通过.

编辑:

看起来你正在寻找传递ModelState给下一个(重定向)请求.这可以通过使用TempData存储ModelState直到下一个请求来完成.仅供参考,TempData使用Session.

这可以通过实现ActionFilters.可以在MvcContrib项目代码中找到示例:ModelStateToTempDataAttribute

这也与weblogs.asp.net上的"最佳实践"文章中的其他提示一起被提及(似乎作者已移动了博客,但我在新博客上找不到该文章).来自文章:

此模式的一个问题是,当验证失败或发生任何异常时,您必须将ModelState复制到TempData中.如果您是手动执行此操作,请将其停止,您可以使用动作过滤器自动执行此操作,如下所示:

调节器

[AcceptVerbs(HttpVerbs.Get), OutputCache(CacheProfile = "Dashboard"), StoryListFilter, ImportModelStateFromTempData]
public ActionResult Dashboard(string userName, StoryListTab tab, OrderBy orderBy, int? page)
{
    //Other Codes
    return View();
}

[AcceptVerbs(HttpVerbs.Post), ExportModelStateToTempData]
public ActionResult Submit(string userName, string url)
{
    if (ValidateSubmit(url))
    {
        try
        {
            _storyService.Submit(userName, url);
        }
        catch (Exception e)
        {
            ModelState.AddModelError(ModelStateException, e);
        }
    }

    return Redirect(Url.Dashboard());
}
Run Code Online (Sandbox Code Playgroud)

动作过滤器

public abstract class ModelStateTempDataTransfer : ActionFilterAttribute
{
    protected static readonly string Key = typeof(ModelStateTempDataTransfer).FullName;
}

public class ExportModelStateToTempData : ModelStateTempDataTransfer
{
    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        //Only export when ModelState is not valid
        if (!filterContext.Controller.ViewData.ModelState.IsValid)
        {
            //Export if we are redirecting
            if ((filterContext.Result is RedirectResult) || (filterContext.Result is RedirectToRouteResult))
            {
                filterContext.Controller.TempData[Key] = filterContext.Controller.ViewData.ModelState;
            }
        }

        base.OnActionExecuted(filterContext);
    }
}

public class ImportModelStateFromTempData : ModelStateTempDataTransfer
{
    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        ModelStateDictionary modelState = filterContext.Controller.TempData[Key] as ModelStateDictionary;

        if (modelState != null)
        {
            //Only Import if we are viewing
            if (filterContext.Result is ViewResult)
            {
                filterContext.Controller.ViewData.ModelState.Merge(modelState);
            }
            else
            {
                //Otherwise remove it.
                filterContext.Controller.TempData.Remove(Key);
            }
        }

        base.OnActionExecuted(filterContext);
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 这是不正确的.有很多危害......所有POST必须遵循重定向.(1)这是从浏览器历史记录中删除POST请求的唯一方法(2)否则按下BACK或REFRESH的用户将会感到困惑和恼人的"重新发送"确认(3)选择"重新发送"的用户无法知道行动的最终结果可能是!15年来,这一直是专业品质网络应用程序的标志.(虽然在ASP或ASP.NET Web应用程序中不常见)此外,即使是*尝试*不可重复的状态更改的GET也应该重定向. (2认同)