1. ホーム
  2. asp.net-mvc

RedirectToActionを持つモデルを含めるにはどうしたらいいですか?

2023-10-23 16:05:22

質問

RedirectToAction を渡すと、以下のようになります。 viewmodel . リダイレクトにモデルを渡すにはどうしたらいいでしょうか?

モデルが正しく作成されていることを確認するために、モデルの値をチェックするブレークポイントを設定しました。それは正しいのですが、結果のビューはモデルのプロパティで見つかった値を含んでいません。

//
// model created up here...
//
return RedirectToAction("actionName", "controllerName", model);

asp.net mvc 4 rc

どのように解決するのですか?

RedirectToAction はクライアントのブラウザに302応答を返すので、ブラウザはブラウザに来た応答のロケーションヘッダの値のurlに新しいGET要求を行います。

シンプルなリーンフラットビューモデルを2番目のアクションメソッドに渡そうとしている場合は このオーバーロード RedirectToAction メソッドのオーバーロードです。

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

RedirectToAction は渡されたオブジェクト(routeValues)をクエリ文字列に変換し、それを(渡した最初の2つのパラメータから生成された)URLに追加し、結果のurlを の場所に埋め込みます。 ヘッダに埋め込みます。

ビューモデルが次のようなものだとしましょう。

public class StoreVm
{
    public int StoreId { get; set; }
    public string Name { get; set; }
    public string Code { set; get; } 
}

そして、最初のアクションメソッドで、このオブジェクトを RedirectToAction メソッドに渡すことができます。

var m = new Store { StoreId =101, Name = "Kroger", Code = "KRO"};
return RedirectToAction("Details","Store", m);

このコードは、ブラウザに302レスポンスを送信し、ロケーションヘッダの値を

Store/Details?StoreId=101&Name=Kroger&Code=KRO

仮にあなたの Details アクションメソッドのパラメータが StoreVm である場合、クエリストリングのパラメータ値はパラメータのプロパティに適切にマッピングされます。

public ActionResult Details(StoreVm model)
{
  // model.Name & model.Id will have values mapped from the request querystring
  // to do  : Return something. 
}

上記は小さなフラットリーン・ビューモデルを渡す場合には有効でしょう。しかし、複雑なオブジェクトを渡したい場合は、PRGパターンに従うようにする必要があります。

PRGパターン

PRGは以下の略です。 POST - 再導入 - 取得 . このアプローチでは、クエリ文字列に一意の ID を含むリダイレクトレスポンスを発行し、それを使って 2 番目の GET アクションメソッドがリソースに再度問い合わせ、ビューに何かを返せるようにします。

int newStoreId=101;
return RedirectToAction("Details", "Store", new { storeId=newStoreId} );

これは、urlを作成します。 Store/Details?storeId=101 を作成し、あなたの詳細で GET アクションで、渡された storeId を使って StoreVm オブジェクトをどこかから (サービスから、あるいはデータベースへの問い合わせ等から) 取得/構築します。

public ActionResult Details(string storeId)
{
   // from the storeId value, get the entity/object/resource
   var store = yourRepo.GetStore(storeId);
   if(store!=null)
   {
      // Map the the view model
      var storeVm = new StoreVm { Id=storeId, Name=store.Name,Code=store.Code};
      return View(storeVm);
   }
   return View("StoreNotFound"); // view to render when we get invalid store id
}

TempData

に続いて PRGパターン は、このユースケースを処理するためのより良いソリューションです。しかし、もしあなたがそれを望まず、本当に複雑なデータを ステートレス HTTP のような一時的なストレージ機構を使用することができます。 TempData

TempData["NewCustomer"] = model;
return RedirectToAction("Index", "Users");

そして、それをあなたの GET Actionメソッドで再度読み込みます。

public ActionResult Index()
{      
  var model=TempData["NewCustomer"] as Customer
  return View(model);
}

TempData 用途 Session オブジェクトを背後に置いてデータを保存しています。しかし、データが読み込まれると、データは終了します。

Rachelが書いた素敵なブログ ポスト で、TempData /ViewData をいつ使うかについて説明しています。一読の価値ありです。

Asp.Net CoreでTempDataを使用してリダイレクトリクエストにモデルデータを渡す

Asp.Netコアでは では、TempDataに複雑な型を渡すことはできません。 . のような単純な型は渡すことができます。 string , int , Guid など。

どうしてもTempData経由で複雑な型のオブジェクトを渡したい場合、2つの選択肢があります。

1) オブジェクトを文字列にシリアライズして、それを渡す。

Json.NETを使って、オブジェクトを文字列にシリアライズするサンプルは次のとおりです。

var s = Newtonsoft.Json.JsonConvert.SerializeObject(createUserVm);
TempData["newuser"] = s;
return RedirectToAction("Index", "Users");

では、あなたの Index アクションメソッドで、TempData からこの値を読み込んで、デシリアライズして CreateUserViewModel クラスオブジェクトにデシリアライズします。

public IActionResult Index()
{
   if (TempData["newuser"] is string s)
   {
       var newUser = JsonConvert.DeserializeObject<CreateUserViewModel>(s);
       // use newUser object now as needed
   }
   // to do : return something
}

2) TempDataに単純型の辞書を設定する。

var d = new Dictionary<string, string>
{
    ["FullName"] = rvm.FullName,
    ["Email"] = rvm.Email;
};
TempData["MyModelDict"] = d;
return RedirectToAction("Index", "Users");

で、後で読む

public IActionResult Index()
{
   if (TempData["MyModelDict"] is Dictionary<string,string> dict)
   {
      var name = dict["Name"];
      var email =  dict["Email"];
   }
   // to do : return something
}