web-dev-qa-db-fra.com

Stocker un objet complexe dans TempData

J'ai essayé de passer des données à une action après une redirection en utilisant TempData comme ceci:

if (!ModelState.IsValid)
{
    TempData["ErrorMessages"] = ModelState;
    return RedirectToAction("Product", "ProductDetails", new { code = model.ProductCode });
}

mais malheureusement, il échoue avec le message suivant:

"System.InvalidOperationException Le Microsoft.AspNet.Mvc.SessionStateTempDataProvider' ne peut pas sérialiser un objet de type 'ModelStateDictionary' à l'état de la session. '

J'ai trouvé un problème dans le projet MVC dans Github , mais bien qu'il explique pourquoi j'obtiens cette erreur, je ne vois pas ce qui serait une alternative viable.

Une option serait de sérialiser l'objet en une chaîne json, puis de le désérialiser et de reconstruire le ModelState. Est-ce la meilleure approche? Existe-t-il des problèmes de performances potentiels dont je dois tenir compte?

Et enfin, existe-t-il des alternatives pour sérialiser un objet complexe ou utiliser un autre modèle qui n'implique pas l'utilisation de TempData?

47
elolos

Vous pouvez créer les méthodes d'extension comme ceci:

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

Et, vous pouvez les utiliser comme suit:

Supposons que objectA est de type ClassA. Vous pouvez l'ajouter au dictionnaire de données temporaires en utilisant la méthode d'extension mentionnée ci-dessus comme ceci:

TempData.Put("key", objectA);

Et pour le récupérer, vous pouvez le faire:

var value = TempData.Get<ClassA>("key")value récupéré sera de type ClassA

100
hem

Je ne peux pas commenter mais j'ai ajouté un PEEK également, ce qui est bien pour vérifier s'il y en a ou pour lire et ne pas retirer pour le prochain 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);
}

Exemple

var value = TempData.Peek<ClassA>("key") where value retrieved will be of type ClassA
6
Chris Go