MVC - 使用RedirectToAction传递数据()

时间:2009-03-23 03:27:40

标签: c# asp.net-mvc redirecttoaction

我想在MVC用户表单中输入数据并将其显示在不同的视图中。

该类具有以下私有变量:

IList<string> _pagecontent = new List<string>();

以下操作接受FormCollection对象,对其进行验证,并将其作为List传递给“Preview”视图:

[Authorize(Roles = "Admins")]
[ValidateInput(false)]
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult UpdateContent(FormCollection collection)
{
    if (ModelState.IsValid)
    {
        string PageToInsert = collection["PageToInsert"];
        string PageHeader = collection["PageHeader"];
        string PageBody = collection["PageBody"];

        //validate, excluded...

        _pagecontent.Add(PageToInsert);
        _pagecontent.Add(PageHeader);
        _pagecontent.Add(PageBody);

    }
    return RedirectToAction("Preview", _pagecontent);
}

预览视图具有以下页面指令,用于传递强类型对象列表:

<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Template.Master" Inherits="System.Web.Mvc.ViewPage<List<string>>" %>

我希望能够使用Model对象来获取我的数据,但是我不能。在接下来的行中,我得到一个error index out of bounds异常,声明索引必须是非负数且小于集合的大小:

<% if (Model[0].ToString() == "0") { %>

一些奇怪的参数已经添加到URL中,因为它解析为 http://localhost:1894/Admin/Preview?Capacity=4&Count=3

所以我有两个问题:

  1. 当我调用RedirectToAction并将其传递给我的List时,为什么在视图的Model对象中无法访问它?
  2. 正在做我正在尝试做的事情的正确方法是什么,即将一组字符串传递给视图以便在那里显示?

8 个答案:

答案 0 :(得分:55)

尝试使用TempData。它就像一个单次会话对象。您将所需的值放入TempData,立即重定向并将其取出。这里有一篇很好的文章:http://blogs.teamb.com/craigstuntz/2009/01/23/37947/

答案 1 :(得分:11)

使用TempData时要小心。它在单个服务器环境中运行良好,但在云环境中,它可能无法按预期工作,因为您无法保证请求将在同一台计算机上运行。这是因为TempData依赖于asp.net会话。但是如果您使用其他会话管理器(如SQL或AppFabric Cache),它将正常工作。

答案 2 :(得分:7)

RedirectAction的第二个参数是routeValues,而不是model。

protected internal RedirectToRouteResult RedirectToAction(string actionName, object routeValues);

尝试将TempData用于模型。它用于在重定向之间保持数据。

答案 3 :(得分:4)

RedirectToAction的问题在于它返回了一个HTTP 302,然后浏览器自行开始并执行一个全新的HTTP请求。您可能需要考虑使用cookie和/或会话对象在请求之间保留数据。

答案 4 :(得分:3)

这不起作用,因为RedirectToAction实际上是将Http 302发送回浏览器。当浏览器接收到该302时,它向服务器发出新请求以请求新页面。新请求,新临时变量。

当您尝试保存/编辑/删除某些内容时,您也会遇到此问题,并且由于某种原因您拒绝它并且您必须再次返回旧表单。

所以,而不是:

return RedirectToAction("Preview", _pagecontent);

将预览逻辑放在一个单独的方法中,然后调用它:

return PreviewLogic(_pagecontent);

你也可以像其他人所说的那样使用TempData [] dic来保存下一个请求的数据,但是你不会避免额外往返服务器的302次。

答案 5 :(得分:2)

听起来你正试图这样做:

public ActionResult UpdateContent(FormCollection form) {
    ...
    return View("Preview", _pagecontent);
}

请注意,重定向应该是浏览器的“清单”(除了auth cookie之类的东西)。您无法告诉浏览器将信息传递给下一个请求,因为下一个请求应该能够独立存在。您要做的就是告诉浏览器接下来要请求的URL。在ASP.NET MVC中,当您将arguments-object传递给RedirectToAction时,该对象的公共属性将作为查询字符串参数附加到生成的URL中。

答案 6 :(得分:0)

你不能只用同一个名字制作2个动作结果,用HttpPost标记其中的1个吗?

    public ActionResult UpdateContent(FormCollection preview = null)
    {
        return View(preview);
    }
    [HttpPost]
    public ActionResult UpdateContent(FormCollection collection = null, bool preview = false)
    {
        if (preview)
            return UpdateContent(collection);
        else
            return UpdateContent(null);
    }

答案 7 :(得分:-3)

看起来您正在寻找UpdateModel命令:

查看ScottGu关于该主题的博文:

Improved UpdateModel and TryUpdateModel methods