web-dev-qa-db-fra.com

Redirigez vers l'action et devez transmettre des données

J'ai un contrôleur qui gère trois actions spécifiques à mon problème.

La première est l'action de modification qui renvoie une vue avec un formulaire HTML que l'utilisateur peut modifier les propriétés de l'élément donné.

La seconde est l'action de mise à jour qui accepte le post de retour du navigateur et met à jour la base de données. Lorsque la mise à jour réussit, nous redirigeons vers l'action.

Le troisième est l'action show qui montre les détails de l'élément donné. Cette action est l'endroit où nous sommes redirigés après une mise à jour réussie.

Le flux est:

Afficher -> Modifier -> Mettre à jour (Réussite: y -> rediriger vers Afficher, n -> retourner Modifier)

Ce que je veux réaliser, c'est de déclencher un indicateur lorsque la mise à jour a réussi, afin que dans la prochaine vue Afficher, je puisse afficher un message de confirmation pour l'utilisateur. Le problème est que je ne suis pas sûr à 100% de la meilleure façon de transporter ces données via l'appel RedirectToAction (). Une pensée que j'avais était d'utiliser une chaîne de requête? Nous transportons déjà des variables avec la chaîne de requête dans un autre but, mais une partie de mon est sceptique d'en abuser. L'appel à la redirection est ci-dessous.

RouteValueDictionary dict = Foo.GetRouteValues(bar);

RedirectToAction("Show", dict);

J'ai également lu cette question, mais j'apprends à utiliser la propriété TempData si je n'ai pas à le faire.

Question

Merci pour quelques suggestions!

28
user172632

EDIT: Désolé, je n'ai pas vu à l'origine votre note sur le fait de ne pas vouloir utiliser TempData.

En un mot - voulez-vous que votre message réapparaisse si le client rafraîchit/recharge la page vers laquelle il a été redirigé?

Si vous le faites, utilisez la chaîne de requête, quelque chose comme:

return(RedirectToAction("Index", new { message = "hi there!" }));

puis définir

public ActionResult Index(string message) { }

ou retirez explicitement Request.QueryString ["message"] et passez-le à View via ViewData de la manière habituelle. Cela fonctionnera également sur les navigateurs qui n'acceptent pas les cookies de votre site.

Si vous ne souhaitez PAS que le message s'affiche à nouveau, ASP.NET MVC 1.0 fournit la collection TempData à cette fin précise.

Les valeurs des propriétés TempData sont stockées dans l'état de session jusqu'à la prochaine demande du même navigateur , après quoi elles sont effacées - donc si vous mettez quelque chose dans TempData juste avant en retournant RedirectToAction, il sera disponible sur le résultat de la redirection mais sera effacé immédiatement après.

Voici une modification simple du HomeController dans le projet de démarrage ASP.NET MVC:

public ActionResult Index() {
    ViewData["Message"] = "Welcome to ASP.NET MVC!";
    return View();
}

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Index(string submitButton) {
    TempData["message"] = "You clicked " + submitButton;
return(RedirectToAction("Index"));
}

public ActionResult About() {
    return View();
}

et la vue correspondante /Views/Home/Index.aspx devrait contenir quelque chose comme ceci:

<asp:Content ID="indexContent" ContentPlaceHolderID="MainContent" runat="server">
  <% if (TempData["message"] != null) { %>
    <p><%= Html.Encode(TempData["message"]) %></p>
  <% } %>
  <% using (Html.BeginForm()) { %>
    <input type="submit" name="submitButton" value="Button One" />
    <input type="submit" name="submitButton" value="Button Two" />
  <% } %>
</asp:Content>

Vous remarquerez que le message TempData s'affiche immédiatement après une séquence POST-REDIRECT-GET, mais si vous actualisez la page, il ne s'affichera plus.

Notez que ce comportement a changé dans ASP.NET MVC 2 - voir "Passage d'état entre les méthodes d'action" dans cet article pour plus d'informations.

41
Dylan Beattie

Je n'ai jamais été fan de TempData non plus et je ne voulais pas non plus passer l'indicateur de réussite dans l'URL comme je ne voulais pas voir

Application/Paramètres? SaveSuccess = true

dans la barre d'URL du navigateur.

Ma solution utilise un cookie temporaire:

[HttpPost]
public ActionResult Settings(SettingsViewModel view)
{
    if (ModelState.IsValid)
    {
        //save
        Response.SetCookie(new HttpCookie("SettingsSaveSuccess", ""));
        return RedirectToAction("Settings");
    }
    else
    {
        return View(view);
    }     
}

et dans l'action correspondante, vérifiez la présence de ce cookie et supprimez-le:

[HttpGet]
public ActionResult Settings()
{
    var view = new SettingsViewModel();
    //fetch from db and do your mapping
    bool saveSuccess = false;
    if (Request.Cookies["SettingsSaveSuccess"] != null)
    {
        Response.SetCookie(new HttpCookie("SettingsSaveSuccess", "") { Expires = DateTime.Now.AddDays(-1) });
        saveSuccess = true;
    }
    view.SaveSuccess = saveSuccess;
    return View(view);
}

nb cela peut être une pente assez glissante si vous commencez à passer quelque chose de plus complexe qu'un drapeau booléen

4
wal