42 votes

Post-Redirect-Get avec ASP.NET

Comment puis-je mettre en œuvre le Post-Redirect-Get avec ASP.NET ?

Un clic sur un bouton exécute un certain traitement :

<asp:Button id="bbLaunch" OnCommand="bbLaunch_Click" />

L'utilisateur clique sur le bouton, le vaisseau spatial est lancé, la page web s'affiche à nouveau. Si l'utilisateur appuie sur F5, il reçoit l'avertissement :

enter image description here

La solution à ce problème est la Post-Redirect-Get modèle.

Quelle est la méthode par laquelle PRG peut être mis en œuvre en ASP.NET ?


La question tourne autour des problèmes suivants :

  • comment le <asp:Button> effectuer un POST à un endroit qui n'est pas sa forme originale ?
  • ce qu'il advient de la ViewState lorsque vous publiez dans un formulaire qui ne lit pas l'état de la vue ?
  • ce qu'il advient de la ViewState lorsque vous redirigez vers le "vrai" formulaire web aspx ?
  • est ViewState fondamentalement incompatible avec ASP.net Post-Redirect-Get ?
  • ASP.net est-il fondamentalement incompatible avec Post-Redirect--Get ?
  • comment (c'est-à-dire quel code) redirigez-vous vers le "vrai" formulaire web aspx ?
  • comment (c'est-à-dire quelle url) redirigez-vous vers le "vrai" formulaire web aspx ? Une question de relation mentionne Response.Redirect(Request.RawUrl);
  • quand (c'est-à-dire dans quel gestionnaire d'événement) redirigez-vous vers le "vrai" formulaire web aspx ?
  • les questions connexes soulèvent des problèmes de comment vous affichez les données du formulaire. Il y a l'implication que le HTML formulaires ne peut être utilisé - et toutes les données du formulaire doivent être ajoutées à la chaîne de requête. Cela est-il vrai ? Si oui, pourquoi ? Dans le cas contraire, pourquoi ? Can un navigateur met les données d'un formulaire dans une chaîne de requête ?
  • une question connexe mentionne Server.Transfer . Utilisation de Server.Transfer est complètement erronée, et ne résout en aucun cas le problème de Post-Redirect-Get (parce qu'il n'y a pas de Rediriger ). Est-ce exact ?
  • quel changement de code doit avoir lieu dans le aspx o aspx.cs fichier pour soutenir le PRG ? On peut supposer qu'il faut au moins modifier le code comme suit post à part MyPage.aspx .

En d'autres termes : Comment faire un Post-Redirect-Get en ASP.net ?

Note : ASP.net (c'est-à-dire pas ASP.net MVC)

Voir aussi

40voto

user1429080 Points 4251

Pour ce faire, il faut généralement créer un formulaire web aspx qui utilise la chaîne de recherche pour indiquer quel enregistrement charger/traiter.

Disons que vous avez une page qui vous permet de mettre à jour certaines informations sur les clients :

http://www.mysite.com/customer.aspx

Vous devez charger le formulaire en utilisant un identifiant dans la chaîne de requête :

http://www.mysite.com/customer.aspx?CustomerId=42

Dans le code de base, vous auriez quelque chose comme ceci :

protected void Page_Load(object sender, EventArgs e)
{
    if (!IsPostBack)
    {
        int customerId = 0;
        if (!string.IsNullOrEmpty(Request.QueryString["CustomerId"]))
        {
            int.TryParse(Request.QueryString["CustomerId"], out customerId );
        }
        if (customerId == 0) 
        {
            //handle case when no valid customer id was passed in the qs here
        }
        else 
        {
            //load customer details, bind controls etc
            //make sure to handle the case when no customer was found using the id in the qs
        }
    }
}

Ensuite, quelque part dans votre page, vous devez avoir un bouton qui enregistre les modifications. Ce bouton aurait un gestionnaire OnClick dans le code sous-jacent :

protected void SaveClicked(object sender, EventArgs e)
{
    //save changes to database here

    //Redirect if all went well
    Response.Redirect("http://www.mysite.com/customer.aspx?CustomerId=" 
        + idOfSavedCustomer.ToString());
}

Ça devrait être tout. La redirection fera en sorte que le navigateur émette une nouvelle requête GET pour l'url dans la Redirect(...). Il chargera la page, le if (!IsPostBack) va s'exécuter et initialiser la page avec les nouvelles valeurs que vous venez de sauvegarder dans le post précédent.

Pour l'ensemble de ce processus, le trafic entre le navigateur et le serveur ressemblerait à ceci :

Browser: GET http://www.mysite.com/customer.aspx?CustomerId=42
Server: 200 (send back some html)

Browser: POST http://www.mysite.com/customer.aspx?CustomerId=42 (post data sent in request)
Server: 302 (point to http://www.mysite.com/customer.aspx?CustomerId=42)

Browser: GET http://www.mysite.com/customer.aspx?CustomerId=42
Server: 200 (send html)

Dans l'étape intermédiaire, le serveur dit en gros :

"Cette demande de poste que vous m'avez envoyée, j'en ai fini avec ça. Maintenant, s'il vous plaît obtenu à cette autre page ici ... "

Le fait que l'url renvoie en fait à la même page n'est pas important.


Quelques réflexions en réponse à votre liste de questions :

  • comment peut-on effectuer un POST à un endroit qui n'est pas sa forme originale ?

Vous pouvez le faire en définissant l'option action sur le formulaire, ou vous pouvez définir l'attribut PostBackUrl sur le bouton.

  • Que devient le ViewState lorsque vous publiez sur un formulaire qui ne lit pas l'état de la vue ? l'état de la vue ?

Cela dépend. Si vous postez simplement le formulaire sur une autre page, vous pouvez utiliser la directive <%@ PreviousPageType .../> pour indiquer à la "nouvelle" page d'où provient le post. Cela simplifiera le travail avec les données postées sur la nouvelle page. Voir ce lien pour plus de détails .

  • que devient le ViewState lorsque l'on redirige vers le "vrai" formulaire aspx ?

L'état de la vue est envoyé dans la demande de poste. Lors de la redirection, le navigateur chargera une nouvelle page et créera son propre état d'affichage.

  • ViewState est-il fondamentalement incompatible avec ASP.net ? Post-Redirect-Get ?

Ça dépend de la façon dont on voit les choses. Après la redirection, la nouvelle page n'aura pas accès à l'état d'affichage de la page précédente.

  • ASP.net est-il fondamentalement incompatible avec Post-Redirect--Get ?

Non. Voir l'exemple ci-dessus.

  • comment (i.e. quel code) redirigez-vous vers le "vrai" formulaire web aspx ?

Response.Redirect(url). Cela enverra une réponse au navigateur, lui indiquant d'effectuer une nouvelle demande d'accès.

  • quand (c'est-à-dire dans quel gestionnaire d'événement) redirigez-vous vers le "vrai" formulaire web aspx ?

Lorsque vous avez effectué tout le travail nécessaire pour traiter la demande de poste.

  • les questions connexes soulèvent le problème de l'affichage des données du formulaire. Le site l'implication que les formulaires HTML ne peuvent pas être utilisés - et toutes les données de formulaire doivent être ajoutées à la chaîne d'interrogation. Cela est-il vrai ? Si oui, pourquoi ? Si non, pourquoi ? pourquoi pas ? Un navigateur peut-il mettre des données de formulaire dans une chaîne d'interrogation ?

La redirection d'une requête post n'est pas bien supportée et devrait probablement être évitée. Cela peut être fait (avec certains navigateurs) en utilisant la réponse http 307. En faisant cela, le serveur indique effectivement au navigateur que " Je ne traiterai pas votre demande de poste, veuillez la poster sur cette autre page à la place. ".

  • une question connexe mentionne Server.Transfer. L'utilisation de Server.Transfer est complètement erronée, et ne résout en aucun cas le problème de Post-Redirect-Get (car il n'y a pas de redirection). Est-ce exact ?

Server.Transfer(...) est un processus qui se déroule du côté du serveur. Le navigateur n'en est pas conscient. En fait, une page peut utiliser Server.Transfer pour demander à une autre page d'effectuer un traitement, et cette page sera chargée de renvoyer une réponse au navigateur. Mais le navigateur pensera que c'est la page originale qui a répondu.

  • quel changement de code doit être effectué dans le fichier aspx ou aspx.cs pour prendre en charge PRG ? On peut supposer qu'il faut au moins modifier le code pour qu'il s'affiche ailleurs que dans MyPage.aspx. ailleurs que dans MyPage.aspx.

Non, un post back normal peut être utilisé. L'astuce consiste à avoir un (ou plusieurs) gestionnaire(s) d'événement spécifique(s) sur la page qui effectue un Repsonse.Redirect après avoir traité les données postées.

7voto

Keith Ballinger Points 96

Q) comment peut-on effectuer un TPV dans un lieu qui n'est pas sa forme originale ?

A) Avec PRG, vous ne POSTEZ pas vers une page différente, vous renvoyez vers la même page (voir le diagramme sur la page wikipedia dont vous avez fait le lien). Mais la réponse de cette page DOIT ÊTRE une réponse 30X (généralement un 302).

Q) Que devient le ViewState lorsque vous envoyez un message à un formulaire qui ne lit pas le ViewState ?

A) L'état de la vue est présent lorsque vous POST, mais il ne sera pas présent pour la nouvelle page sur laquelle vous effectuez un GET.

Q) que devient le ViewState lorsque l'on redirige vers le "vrai" formulaire web aspx ?

A) Per ci-dessus, il n'y a plus d'état de vue sont rediriger vers la page.

Q) ViewState est-il fondamentalement incompatible avec ASP.net ?

A) ViewState n'est pas incompatible avec ASP.NET. Il est (en grande partie) inutile pour P/R/G pour le rendu de la page vers laquelle vous êtes redirigé.

Q) ASP.net est-il fondamentalement incompatible avec Post-Redirect--Get ?

R) Non, mais vous ne pouvez pas trop compter sur l'utilisation d'une seule page et sur le maintien de tous vos états dans le viewstate, comme indiqué ci-dessus. Cela dit, ASP.MVC est une carte bien meilleure que P/R/G.

Q) comment (i.e. quel code) redirigez-vous vers le "vrai" formulaire web aspx ?

A) Response.Redirect("new_page_you_are_redirecting_to.aspx") dans la méthode bbLaunch_Click de old_page_you_are_posting_from.aspx

Q) comment (i.e. quelle url) redirigez-vous vers le "vrai" formulaire web aspx ? Une question de relation mentionne Response.Redirect(Request.RawUrl) ;

A) Voir ci-dessus

Q) Quand (c'est-à-dire dans quel gestionnaire d'événement) redirigez-vous vers le "vrai" formulaire web aspx ?

A) Après avoir traité l'appui sur le bouton, enregistré les données dans la base de données (ou la session, etc.), et avant d'avoir écrit quoi que ce soit d'autre dans le flux de réponse.

Q) les questions connexes soulèvent le problème de l'affichage des données de formulaire. Il semblerait que les formulaires HTML ne puissent pas être utilisés et que toutes les données de formulaire doivent être ajoutées à la chaîne de requête. Cela est-il vrai ?

R) Non - l'appui sur le bouton dans ASP.NET WebForms renverra à la page.

Q) Si oui, pourquoi ? Si non, pourquoi ?

A) C'est plus simple que ça, c'est pourquoi pas. Imaginez deux pages : first_page.asp et second_page.aspx. First_page.aspx contient le bouton (ainsi que d'autres contrôles web ASP.NET, comme des zones de texte, etc. que l'utilisateur a remplis). Lorsqu'il appuie sur le bouton, un POST est envoyé à first_page.aspx. Après avoir traité les données (qui se trouvent probablement dans le viewstate, bien que ce soit abstrait), vous redirigez l'utilisateur vers second_page.aspx en utilisant Response.redirect. Second_page.aspx peut afficher ce que vous voulez. Si vous voulez (ou avez besoin) d'afficher une interface utilisateur similaire à celle de first_page.aspx, y compris les contrôles et ce qu'ils ont saisi, vous voudrez stocker cela dans la session, un cookie, l'URL comme paramètres de la chaîne de requête, pour définir ces contrôles sur second_page.aspx. (Mais vous n'aurez peut-être pas besoin d'afficher quoi que ce soit sur second_page.aspx qui soit similaire à first_page.aspx - il n'y a donc pas de règle générale ici).

Q) Un navigateur peut-il placer des données de formulaire dans une chaîne d'interrogation ?

R) Oui, si vous réglez la méthode sur GET au lieu de POST. Vous ne pouvez pas modifier WebForms pour faire cela, et ce n'est pas nécessaire pour PRG.

Q) une question connexe mentionne Server.Transfer. L'utilisation de Server.Transfer est totalement erronée et ne résout en aucun cas le problème de Post-Redirect-Get (car il n'y a pas de Redirect). Est-ce exact ?

A) Essentiellement

Q) Quel changement de code doit être effectué dans le fichier aspx ou aspx.cs pour prendre en charge PRG ? Je suppose qu'il faut au moins modifier le code pour qu'il soit affiché ailleurs que dans MyPage.aspx.

A) Le code devrait toujours renvoyer l'information (comme indiqué ci-dessus), mais Mypage.aspx devrait être redirigé vers une nouvelle page dans le gestionnaire de bouton.

5voto

Aristos Points 40367

Les étapes exactes du Post Redirect Get sont celles-ci :

Vous avez le formulaire que vous remplissez avec des données, et après votre soumission valide (POST) vous les insérez dans votre base de données, et leur donnez un id de confirmation, puis vous redirigez l'utilisateur vers la page avec cet id de confirmation comme paramètre URL qui est utilisé comme le (GET) Après la redirection chaque F5-refresh est seulement lire les données et ne pas les insérer à nouveau.

Le code pour l'insertion est différent de celui qui affiche la confirmation, vous pouvez même en faire des pages différentes - vous pouvez faire la même page avec des zones de texte en lecture seule.

La redirection est simple : le Responce.Redirect fonction d'asp.net

Après le POST et la réalisation de la redirection, le seul élément qui vous relie à l'action précédente est le code de confirmation (pas le viewstate).

L'inconvénient de cette méthode est qu'en fait elle ne reconnaît pas le rafraîchissement, elle fait juste une étape supplémentaire qui fait que le rafraîchissement n'insère pas à nouveau les mêmes données - mais nécessite du code supplémentaire pour le Get data.

L'alternative est de reconnaître le rafraîchissement et de ne pas faire de redirection. En reconnaissant le rafraîchissement sur le post back vous pouvez éviter d'insérer les mêmes données avec un seul message à l'utilisateur. Il y a quelques exemples sur l'internet pour cela, et j'en ai implémenté un avec succès.

Un exemple : http://www.codeproject.com/Tips/319955/How-to-prevent-Re-Post-action-caused-by-pressing-b

5voto

graham mendick Points 1047

Le modèle Post-Redirect-Get peut être utilisé dans les formulaires Web. J'ai montré comment cela peut être fait en convertissant l'application MVC NerdDinner en formulaires Web, http://navigationnerddinner.codeplex.com/ . J'ai gardé les détails de navigation exactement les mêmes, de sorte qu'il y a beaucoup d'exemples du modèle PRG.

Cependant, il existe un autre moyen d'éviter le problème F5/Refresh. Si vous intégrez votre page dans un UpdatePanel (qui fait partie d'ASP.NET Ajax), tous les retours de courrier seront convertis en demandes de pages partielles. Cela signifie que lorsque vous appuyez sur la touche F5, la demande GET initiale sera uniquement rafraîchie (puisqu'il n'y a pas eu de POST ultérieur), et vous n'obtiendrez donc pas d'avertissement. (Remarque : si JavaScript est désactivé, l'avertissement apparaîtra quand même).

0 votes

Merci pour ce super conseil ! Je travaille avec WebForms depuis si longtemps, mais lorsque j'étais en train de réfléchir à PRG, j'ai complètement oublié d'utiliser un UpdatePanel à la place ! Cela résout le problème du rafraîchissement de la page très facilement !

4voto

Bas Brekelmans Points 13799

Vous pouvez invoquer le Réponse.Redirection pour aller à un autre endroit.

0 votes

Comment puis-je accéder à la page où se trouve la Response.Redirect ?

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