我应该使用TempData还是RedirectToAction?

时间:2013-12-23 18:17:22

标签: asp.net-mvc

我的控制器上有删除操作。它检查用户是否确实被允许删除。

我的问题是,如果他们不被允许删除:

我应该重定向回我的索引操作(列出他们可以删除的所有文件)并在TempData中传递一条错误消息,说“不允许您删除此资源”。

OR

我应该选择他们可以删除的所有文件,列出它们并在删除操作中显示错误吗?

最佳做法是什么?

注意:我不关心授权/身份验证。

2 个答案:

答案 0 :(得分:0)

假设通过HTTP帖子命中删除操作,Post/Redirect/Get通常是最好的做法,以防止双重帖子,所以我选择重定向临时数据。在这种特殊情况下,双重发布可能并不危险,但在其他条件相同的情况下,选择一致性。

答案 1 :(得分:0)

使用Post / Redirect / Get,这里是filter属性(不记得我发现的实际位置):

/// <summary>
/// When a RedirectToRouteResult is returned from an action, anything in the ViewData.ModelState dictionary will be copied into TempData.
/// When a ViewResultBase is returned from an action, any ModelState entries that were previously copied to TempData will be copied back to the ModelState dictionary.
/// </summary>
public class ModelStateToTempDataAttribute : ActionFilterAttribute
{
    public const string TempDataKey = "__MvcContrib_ValidationFailures__";

    /// <summary>
    /// When a RedirectToRouteResult is returned from an action, anything in the ViewData.ModelState dictionary will be copied into TempData.
    /// When a ViewResultBase is returned from an action, any ModelState entries that were previously copied to TempData will be copied back to the ModelState dictionary.
    /// </summary>
    /// <param name="filterContext"></param>
    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        var modelState = filterContext.Controller.ViewData.ModelState;

        var controller = filterContext.Controller;

        if (filterContext.Result is ViewResultBase)
        {
            //If there are failures in tempdata, copy them to the modelstate
            CopyTempDataToModelState(controller.ViewData.ModelState, controller.TempData);
            return;
        }

        //If we're redirecting and there are errors, put them in tempdata instead (so they can later be copied back to modelstate)
        if ((filterContext.Result is RedirectToRouteResult || filterContext.Result is RedirectResult) && !modelState.IsValid)
        {
            CopyModelStateToTempData(controller.ViewData.ModelState, controller.TempData);
        }
    }

    private void CopyTempDataToModelState(ModelStateDictionary modelState, TempDataDictionary tempData)
    {
        if (!tempData.ContainsKey(TempDataKey)) return;

        var fromTempData = tempData[TempDataKey] as ModelStateDictionary;
        if (fromTempData == null) return;

        foreach (var pair in fromTempData)
        {
            if (modelState.ContainsKey(pair.Key))
            {
                modelState[pair.Key].Value = pair.Value.Value;

                foreach (var error in pair.Value.Errors)
                {
                    modelState[pair.Key].Errors.Add(error);
                }
            }
            else
            {
                modelState.Add(pair.Key, pair.Value);
            }
        }
    }

    private static void CopyModelStateToTempData(ModelStateDictionary modelState, TempDataDictionary tempData)
    {
        tempData[TempDataKey] = modelState;
    }
}

您需要做的就是使用“ModelStateToTempData”标记您的操作(在两个操作中:使用HttpGet和HttpPost进行营销)。像这样(来自我的项目的代码):

    [ModelStateToTempData]
    public ActionResult Login()
    {
        if(Request.IsAuthenticated)
        {
            return View("AlreadyLoggedIn");
        }

        return View();
    }

    [HttpPost, ValidateAntiForgeryToken, ModelStateToTempData]
    public ActionResult Login(LoginViewModel viewModel)
    {
        if(ModelState.IsValid)
        {
            // other logic here
        }
        return RedirectToRoute("Login");
    }

路由配置(以防万一):

    routes.MapRoute("Login", "login", new { controller = "Login", action = "Login" });