59 votes

MVC - Transmission de données avec RedirectToAction()

J'aimerais prendre les données saisies dans un formulaire utilisateur MVC et les afficher dans une vue différente.

La classe possède la variable privée suivante :

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

L'action suivante accepte un objet FormCollection, le valide, et le transmet à la vue "Preview" sous forme de liste :

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

La vue Aperçu a la directive de page suivante pour passer une liste d'objets fortement typés :

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

Je m'attendrais à pouvoir utiliser l'objet Modèle pour obtenir mes données, mais hélas je ne peux pas. À la ligne suivante, j'obtiens un error index out of bounds exception, précisant que l'indice doit être non négatif et inférieur à la taille de la collection :

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

Et des paramètres étranges ont été ajoutés à l'URL, car elle se résout en http://localhost:1894/Admin/Preview?Capacity=4&Count=3

J'ai donc deux questions :

  1. Lorsque j'appelle RedirectToAction et lui passe ma liste, pourquoi est-elle inaccessible dans l'objet Model de la vue ?
  2. Quelle est la bonne façon de procéder pour faire ce que j'essaie de faire, à savoir passer une collection de chaînes à une vue pour qu'elle les affiche ?

56voto

MichaelGG Points 8202

Essayez d'utiliser TempData. C'est comme un objet de session unique. Vous mettez les valeurs que vous voulez dans TempData, vous les redirigez immédiatement et vous les récupérez. Il y a un bon article ici : http://blogs.teamb.com/craigstuntz/2009/01/23/37947/

11voto

João Miguel Points 81

Soyez prudent lorsque vous utilisez TempData. Elle fonctionne très bien dans un environnement à serveur unique, mais dans un environnement en nuage, elle peut ne pas fonctionner comme prévu, car vous ne pouvez pas garantir que la requête touchera la même machine. Cela se produit parce que TempData repose sur la session asp.net. Mais si vous utilisez un autre gestionnaire de session comme SQL ou AppFabric Cache, cela fonctionnera bien.

7voto

AndreasN Points 1703

Le deuxième paramètre de RedirectAction est routeValues, et non pas modèle.

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

Essayez d'utiliser TempData pour le modèle. Cela permet de conserver les données entre les redirections.

4voto

Chad Moran Points 8560

Le problème avec RedirectToAction, c'est qu'il renvoie un HTTP 302 et que le navigateur doit alors, de son propre chef, faire une toute nouvelle requête HTTP. Vous pouvez envisager d'utiliser un cookie et/ou un objet de session pour conserver les données entre les requêtes.

3voto

andrecarlucci Points 2435

Cela ne fonctionne pas car RedirectToAction renvoie en fait un Http 302 au navigateur. Lorsque le navigateur reçoit ce 302, il fait une nouvelle demande au serveur pour obtenir la nouvelle page. Nouvelle requête, nouvelles variables temporaires.

Vous serez également confronté à ce problème lorsque vous essayez d'enregistrer/modifier/supprimer quelque chose et que, pour une raison quelconque, vous le refusez et que vous devez à nouveau retourner l'ancien formulaire.

Donc, au lieu de :

return RedirectToAction("Preview", _pagecontent);

Mettez la logique de prévisualisation dans une méthode séparée et appelez-la simplement :

return PreviewLogic(_pagecontent);

Vous pouvez également utiliser le dic TempData[] pour faire persister les données pour la prochaine requête comme d'autres l'ont dit, mais alors vous n'éviterez pas l'aller-retour 302 supplémentaire vers le serveur.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X