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

时间:2011-10-29 18:49:41

标签: asp.net-mvc-3 redirect

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

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

2 个答案:

答案 0 :(得分:7)

通常只有在成功帖子后才会重定向(没有模型验证错误),否则您会发回包含验证错误消息的页面。

PRG模式中的重定向可防止双重发布,因此发回同一页面(+错误消息)没有坏处,因为帖子不成功且不会除非有什么改变才能通过验证。

修改

看起来您正在寻找将ModelState传递给下一个(重定向)请求。这可以通过使用TempDataModelState存储到下一个请求来完成。仅供参考,TempData使用会话。

这可以使用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());
}

动作过滤器

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);
    }
}

答案 1 :(得分:0)

“强制”重定向是什么意思?通常我们在控制器中使用try / catch,如果尝试成功,您可以重定向到View(如果您需要),也可以返回任何部分视图或任何您需要的视图。捕获通常会重新显示原始页面并显示错误消息,因为发布请求不成功。

希望我没有误会你:)