私は次のようにTempDataを使用して、リダイレクト後にアクションにデータを渡そうとしました:
if (!ModelState.IsValid)
{
TempData["ErrorMessages"] = ModelState;
return RedirectToAction("Product", "ProductDetails", new { code = model.ProductCode });
}
ただし、残念ながら次のメッセージが表示されて失敗します。
'
System.InvalidOperationException
Microsoft.AspNet.Mvc.SessionStateTempDataProvider'
は'ModelStateDictionary'
型のオブジェクトをセッション状態にシリアル化できません。
GithubのMVCプロジェクト で問題を発見しましたが、このエラーが発生する理由は説明していますが、実行可能な代替案はわかりません。
1つのオプションは、オブジェクトをJSON文字列にシリアル化してから、逆シリアル化してModelState
を再構築することです。これが最善のアプローチですか?考慮する必要がある潜在的なパフォーマンスの問題はありますか?
最後に、複雑なオブジェクトのシリアル化、またはTempData
の使用を伴わない他のパターンの使用に代わるものはありますか?
次のような拡張メソッドを作成できます。
_public static class TempDataExtensions
{
public static void Put<T>(this ITempDataDictionary tempData, string key, T value) where T : class
{
tempData[key] = JsonConvert.SerializeObject(value);
}
public static T Get<T>(this ITempDataDictionary tempData, string key) where T : class
{
object o;
tempData.TryGetValue(key, out o);
return o == null ? null : JsonConvert.DeserializeObject<T>((string)o);
}
}
_
また、次のように使用できます。
objectA
はClassA
型であるとしましょう。次のような上記の拡張メソッドを使用して、これを一時データディクショナリに追加できます。
TempData.Put("key", objectA);
そしてそれを取得するには、これを行うことができます:
var value = TempData.Get<ClassA>("key")
ここで、取得されるvalue
はClassA
型になります
コメントすることはできませんが、PEEKを追加しました。これは、次のGETのために削除するのではなく、読み取るかどうかを確認するのに便利です。
public static T Peek<T>(this ITempDataDictionary tempData, string key) where T : class
{
object o = tempData.Peek(key);
return o == null ? null : JsonConvert.DeserializeObject<T>((string)o);
}
例
var value = TempData.Peek<ClassA>("key") where value retrieved will be of type ClassA