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&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 数据时失去授权