MVC - 使用 RedirectToAction() 传递数据

Posted

技术标签:

【中文标题】MVC - 使用 RedirectToAction() 传递数据【英文标题】:MVC - Passing Data with RedirectToAction() 【发布时间】:2010-10-14 21:38:57 【问题描述】:

我想获取在 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&amp;Count=3

所以我有两个问题:

    当我调用 RedirectToAction 并将我的 List 传递给它时,为什么它在视图的 Model 对象中无法访问? 做我想做的事情的正确方法是什么,即将字符串集合传递给视图以在那里显示?

【问题讨论】:

【参考方案1】:

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

【讨论】:

我确实尝试过 ViewData 但无法正常工作。与 TempData 相同,但我昨晚睡前只给了它一个简短的尝试。最重要的是,我真的很想避免使用这些字典并使用强类型的 View Model 对象 是的,但是您的 View Model 对象——它不会在 HTTP 302 上保留强类型。您可以将模型粘贴到 TempData 中并将其丢弃。 (老实说,我发现在使用 ASP.NET MVC 时更容易半途而废,因为它做得不好。) 链接不再有效【参考方案2】:

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

【讨论】:

【参考方案3】:

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

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

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

【讨论】:

【参考方案4】:

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

【讨论】:

【参考方案5】:

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

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

所以,而不是:

return RedirectToAction("Preview", _pagecontent);

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

return PreviewLogic(_pagecontent);

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

【讨论】:

【参考方案6】:

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

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

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

【讨论】:

我不使用 return View() 的原因是因为 url 将显示调用视图(AddContent),而不是呈现的视图(预览)。当用户单击“提交”按钮时,它会调用刚刚呈现预览视图的相同 AddContent [Post] 操作,因此我无法点击 Preview [post] 操作。 您为什么要发布到 /MyController/AddContent?为什么不发布到 /MyController/Preview? 我试图将我的 AddContent 操作发布到 Preview,但是当我返回 View("Preview", _pagecontent) 时,它会呈现 Preview,但 url 显示的是“/Controller/AddContent”。然后,当我单击按钮以持久保存到数据库时,它再次调用 Addcontent 发布操作而不是 Preview 发布操作。【参考方案7】:

你不能只制作 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);
    

【讨论】:

【参考方案8】:

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

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

Improved UpdateModel and TryUpdateModel methods

【讨论】:

以上是关于MVC - 使用 RedirectToAction() 传递数据的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Asp.NET MVC 中使用 RedirectToAction() 传递多个对象?

.NET MVC 是不是具有强类型的 RedirectToAction?

ASP.Net MVC:使用 RedirectToAction() 将字符串参数传递给操作

asp.net mvc 2 - 当 RedirectToAction 使用 JSON 数据时失去授权

传递参数的mvc RedirectToAction [重复]

RedirectToAction 不适用于 Tempdata - ASP.net 核心 MVC