web-dev-qa-db-ja.com

MVC-RedirectToAction()でデータを渡す

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") { %>

http://localhost:1894/Admin/Preview?Capacity=4&Count=3に解決されるため、URLにいくつかの奇妙なパラメーターが追加されました

そこで、2つの質問があります。

  1. RedirectToActionを呼び出してリストを渡すと、ビューのModelオブジェクトでアクセスできないのはなぜですか?
  2. 私がやろうとしていること、つまり文字列のコレクションをビューに渡して表示するための適切な方法は何ですか?
59
splatto

TempDataを使用してみてください。これは、単発のセッションオブジェクトのようなものです。必要な値をTempDataに入れ、すぐにリダイレクトして取得します。ここに良い記事があります: http://blogs.teamb.com/craigstuntz/2009/01/23/37947/

55
MichaelGG

TempDataを使用するときは注意してください。単一サーバー環境ではうまく機能しますが、クラウド環境では、リクエストが同じマシンにヒットすることを保証できないため、期待どおりに機能しない場合があります。これは、TempDataがasp.netセッションに依存しているために発生します。ただし、SQLやAppFabric Cacheなどの他のセッションマネージャーを使用している場合は、正常に機能します。

11
João Miguel

RedirectActionの2番目のパラメーターは、modelではなくrouteValuesです。

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

モデルにTempDataを使用してみてください。リダイレクト間でデータを保持します。

7
AndreasN

RedirectToActionの問題は、HTTP 302を返していることと、ブラウザーが独自に進んで新しいHTTP要求を実行することです。 Cookieやセッションオブジェクトを使用して、リクエスト間でデータを保持することを検討できます。

4
Chad Moran

RedirectToActionが実際にブラウザにHTTP 302を送り返しているため、これは機能しません。ブラウザはこの302を受信すると、新しいページを要求する新しいリクエストをサーバーに送信します。新しいリクエスト、新しい一時変数。

何かを保存/編集/削除しようとすると、何らかの理由でそれを拒否し、古いフォームを再度返さなければならないときにも、この問題に直面します。

したがって、代わりに:

return RedirectToAction("Preview", _pagecontent);

プレビューロジックを別のメソッドに入れて呼び出すだけです:

return PreviewLogic(_pagecontent);

TempData [] dicを使用して、他の人が言ったように次のリクエストのためにデータを保持することもできますが、サーバーへの302の追加ラウンドトリップは回避できません。

3
andrecarlucci

あなたがやろうとしているように聞こえます:

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

リダイレクトは、ブラウザの「クリーンな状態」であることに注意してください(認証Cookieなどを除く)。次のリクエストは独立している必要があるため、ブラウザに次のリクエストに情報を渡すように指示することはできません。できることは、次に要求するURLをブラウザーに伝えることだけです。 ASP.NET MVCでは、arguments-objectをRedirectToActionに渡すと、そのオブジェクトのパブリックプロパティがクエリ文字列パラメーターとして生成されたURLに追加されます。

2
yfeldblum

同じ名前で2つのアクション結果を作成し、それらの1つを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);
    }
0
TeamEASI.com