MVC - 使用 RedirectToAction() 传递数据

发布于 2024-07-15 01:21:50 字数 1414 浏览 9 评论 0原文

我想获取在 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>>" %>

I我希望能够使用 Model 对象来获取我的数据,但可惜我不能。 在下面的行中,我收到一个错误索引超出范围异常,指出索引必须为非负数并且小于集合的大小:

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

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

所以我有两个问题:

  1. 当我调用 RedirectToAction 并将其传递给我的列表时,为什么在视图的模型中无法访问它目的?
  2. 执行我想做的事情的正确方法是什么,即将字符串集合传递到视图以在那里显示?

I'd like to take data entered in an MVC user form and display it in a different view.

The class has the following private variable:

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

The following action accepts a FormCollection object, validates it, and passes it on to the "Preview" view as a List:

[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);
}

The Preview view has the following Page Directive for passing a strongly typed object List:

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

I would expect to be able to use the Model object to get my data, but alas I cannot. At the following line, I get an error index out of bounds exception, stating the index must be non-negative and less than the size of the collection:

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

And some strange parameters have been added to the URL, as it resolves to
http://localhost:1894/Admin/Preview?Capacity=4&Count=3

So I have two questions:

  1. When I call RedirectToAction and pass it my List, why is it inaccessible in the view's Model object?
  2. What is the proper way to go about doing what I'm trying to do, namely pass a collection of strings to a view for display there?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

帅冕 2024-07-22 01:21:51

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

Can't you just make 2 action results with the same name and mark 1 of them with HttpPost?

    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);
    }
白昼 2024-07-22 01:21:51

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

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

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

It sounds like you're trying to do:

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

Note that a redirection is supposed to be a "clean slate" for the browser (except for things like the auth cookie). You don't get to tell the browser to pass information along to the next request, since the next request should be able to stand on its own. All you get to do is tell the browser what URL to request next. In ASP.NET MVC, when you pass an arguments-object to RedirectToAction, the public properties of that object are appended as query-string parameters to the generated URL.

檐上三寸雪 2024-07-22 01:21:51

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

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

因此,不要:

return RedirectToAction("Preview", _pagecontent);

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

return PreviewLogic(_pagecontent);

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

This is not working because RedirectToAction is actually sending back a Http 302 to the browser. When the browser receives this 302, it does a new request to the server asking for the new page. New request, new temp variables.

You will also face this problem when you try to save/edit/delete something and for some reason you deny it and you have to return the old form again.

So, instead of:

return RedirectToAction("Preview", _pagecontent);

Put the Preview logic in a separate method and just call it:

return PreviewLogic(_pagecontent);

You can also use the TempData[] dic to persist data for the next request like others have said, but then you will not avoid the 302 additional round trip to the server.

静赏你的温柔 2024-07-22 01:21:51

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

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

改进的 UpdateModel 和 TryUpdateModel 方法

It looks like you are looking for the UpdateModel command:

Check out ScottGu's blog post on the topic:

Improved UpdateModel and TryUpdateModel methods

清晰传感 2024-07-22 01:21:50

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

Be careful when using TempData. It works great in a single server environment but in a cloud environment it may not work as expected since you cannot guarantee that the request will hit the same machine. This happens because TempData rely on the asp.net session. But if you are using other session manager like SQL or AppFabric Cache it will work fine.

清晰传感 2024-07-22 01:21:50

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

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

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

The second parameter to RedirectAction is routeValues, not model.

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

Try using TempData for the model. Its for persisting data between redirects.

梦在夏天 2024-07-22 01:21:50

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

Try using TempData. It is like a single-shot session object. You put values you want into TempData, immediately redirect and get them out. There is a good writeup here: http://blogs.teamb.com/craigstuntz/2009/01/23/37947/

_失温 2024-07-22 01:21:50

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

The problem with RedirectToAction is it's returning a HTTP 302 and the browser is then on it's own going and doing a brand new HTTP request. You may want to consider using a cookie and/or session object to persist the data between requests.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文