重定向到操作并需要传递数据

时间:2010-07-29 14:56:22

标签: asp.net-mvc redirect

我有一个控制器可以处理三个特定于我的问题的操作。

第一个是编辑操作,它返回一个HTML表单视图,用户可以编辑给定项目的属性。

第二个是更新操作,它接受来自浏览器的回发并更新数据库。更新成功后,我们会重定向到操作。

第三个是show动作,显示给定项目的详细信息。此操作是我们在成功更新后重定向到的位置。

流程是:

显示 - >编辑 - >更新(成功:y - >重定向到显示,n - >返回编辑)

我想要实现的是在更新成功时触发标记,以便在下一个Show视图中我可以为用户显示确认消息。问题是我不能100%确定通过RedirectToAction()调用传输数据的最佳方法。有人以为我在使用查询字符串?我们已经在查询字符串中携带变量用于其他目的,但我的一部分对滥用它持怀疑态度。对重定向的调用如下。

RouteValueDictionary dict = Foo.GetRouteValues(bar);

RedirectToAction("Show", dict);

我也读过这个问题,但如果我不需要,请使用TempData属性。

Question

感谢您的一些建议!

2 个答案:

答案 0 :(得分:41)

编辑:抱歉,最初没有看到你关于不想使用TempData的说明。

简而言之 - 如果客户端刷新/重新加载他们被重定向到的页面,您是否希望重新显示您的消息?

如果你这样做,那么使用查询字符串,如:

return(RedirectToAction("Index", new { message = "hi there!" }));

然后定义

public ActionResult Index(string message) { }

或显式提取Request.QueryString [“message”]并以通常的方式通过ViewData将其传递给View。这也适用于不接受来自您网站的Cookie的浏览器。

如果您不希望再次显示该消息,则ASP.NET MVC 1.0会为此目的提供TempData集合。

TempData属性值存储在会话状态,直到来自同一浏览器的下一个请求,之后它们被清除 - 所以如果你在返回RedirectToAction之前立即在TempData中放入一些东西,它将是可用的关于重定向的结果,但之后会立即清除。

这是对ASP.NET MVC启动项目中HomeController的简单更改:

public ActionResult Index() {
    ViewData["Message"] = "Welcome to ASP.NET MVC!";
    return View();
}

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Index(string submitButton) {
    TempData["message"] = "You clicked " + submitButton;
return(RedirectToAction("Index"));
}

public ActionResult About() {
    return View();
}

和相应的视图/Views/Home/Index.aspx应该包含这样的内容:

<asp:Content ID="indexContent" ContentPlaceHolderID="MainContent" runat="server">
  <% if (TempData["message"] != null) { %>
    <p><%= Html.Encode(TempData["message"]) %></p>
  <% } %>
  <% using (Html.BeginForm()) { %>
    <input type="submit" name="submitButton" value="Button One" />
    <input type="submit" name="submitButton" value="Button Two" />
  <% } %>
</asp:Content>

您会注意到POST-REDIRECT-GET序列后立即显示TempData消息,但如果刷新页面,则不会再次显示。

请注意,ASP.NET MVC 2中的此行为已更改 - 有关详细信息,请参阅this article中的“在操作方法之间传递状态”。

答案 1 :(得分:4)

从未成为TempData的粉丝,另外我不想传递URL中的成功标志,因为我不想看到

  

应用/设置?saveSuccess =真

在浏览器的网址栏中。

我的解决方案使用临时cookie:

[HttpPost]
public ActionResult Settings(SettingsViewModel view)
{
    if (ModelState.IsValid)
    {
        //save
        Response.SetCookie(new HttpCookie("SettingsSaveSuccess", ""));
        return RedirectToAction("Settings");
    }
    else
    {
        return View(view);
    }     
}

并在相应的Get操作中检查是否存在此Cookie并将其删除:

[HttpGet]
public ActionResult Settings()
{
    var view = new SettingsViewModel();
    //fetch from db and do your mapping
    bool saveSuccess = false;
    if (Request.Cookies["SettingsSaveSuccess"] != null)
    {
        Response.SetCookie(new HttpCookie("SettingsSaveSuccess", "") { Expires = DateTime.Now.AddDays(-1) });
        saveSuccess = true;
    }
    view.SaveSuccess = saveSuccess;
    return View(view);
}

nb 如果你开始传递比布尔标志更复杂的东西,这可能是一个相当滑的斜率