59

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

该类具有以下私有变量:

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

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

[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 并将它传递给我的列表时,为什么它在视图的模型对象中无法访问?
  2. 做我想做的事情的正确方法是什么,即将字符串集合传递给视图以在那里显示?
4

8 回答 8

57

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

于 2009-03-23T03:51:19.913 回答
14

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

于 2012-04-25T19:24:21.877 回答
8

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

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

尝试对模型使用 TempData。它用于在重定向之间保留数据。

于 2009-03-23T21:43:23.737 回答
4

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

于 2009-03-23T03:35:38.780 回答
3

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

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

所以,而不是:

return RedirectToAction("Preview", _pagecontent);

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

return PreviewLogic(_pagecontent);

您也可以像其他人所说的那样使用 TempData[] dic 为下一个请求保留数据,但是您将无法避免到服务器的 302 额外往返。

于 2009-07-24T13:06:37.200 回答
2

听起来您正在尝试这样做:

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

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

于 2009-03-23T15:33:04.780 回答
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);
    }
于 2014-05-05T17:36:19.453 回答
-3

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

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

改进的 UpdateModel 和 TryUpdateModel 方法

于 2009-03-23T14:59:52.770 回答