précédent : <rewriter>
< réécrire url = " ^/Utilisateur/(d+)$ " à = " ~/User.aspx?id=$1 " traitement = " arrêter " />
< réécrire url = " ^/Utilisateur/(w+)$ " à = " ~/User.aspx?name=$1 " traitement = " arrêter " />
</ rewriter >
Lorsque l'utilisateur demande "/User/jeffz", le code qui apparaît sur la page sera <form action="/User.aspx?name=jeffz" /> En effet, lorsque le code est généré, la page La valeur actuelle de Request.Url.PathAndQuery sera utilisée pour obtenir l'action de l'élément de formulaire. Cela fait apparaître "User.aspx?name=jeffz" dans la barre d'adresse une fois PostBack, et cette adresse peut ne pas être en mesure de demander la bonne ressource (car elle peut être réécrite ailleurs, ou en raison de relations au niveau du répertoire). telle ressource). Dans l'article précédent « UpdatePanel et UrlRewrite », je disais que ce problème pouvait être résolu en ajoutant une ligne de code JavaScript en fin de page :
< script language ="javascript" type ="text/javascript">
document.getElementsByTagName( "form" )(0).action = window.location;
</script> Le but
de cette ligne de code est très évident. Changer l'action du formulaire en window.location (c'est-à-dire le chemin dans la barre d'adresse du navigateur), de sorte que lorsque la page effectue PostBack, l'adresse cible sera être l'adresse avant la réécriture de l'URL. Cette approche peut permettre au programme de fonctionner normalement, mais elle ne me satisfait vraiment pas. Pourquoi?
Parce que c'est trop moche.
Parce que nous exposons toujours l'adresse après la réécriture de l'URL au client. Tant que l'utilisateur installe un renifleur HTTP (comme le célèbre Fiddler) ou sélectionne directement d'afficher le fichier source dans IE, notre adresse cible sera affichée devant l'utilisateur sans aucune dissimulation. Comment pouvons-nous faire connaître aux utilisateurs nos règles de réécriture ? Nous devons résoudre ce problème. La solution est très simple et déjà très populaire, qui consiste à utiliser Control Adapter pour modifier le comportement de la génération de formulaire. Mais ce qui me rend étrange, c'est que toutes les recherches de cet adaptateur de contrôle sur Internet sont des versions VB.NET, mais le langage C# principalement promu par Microsoft est introuvable. Bien qu'il ne soit pas difficile de réécrire tant que vous comprenez un peu la syntaxe VB.NET, cela reste après tout un travail supplémentaire. Je vais donc publier maintenant le code de la version C# de cet adaptateur afin que mes amis puissent l'utiliser directement :
espace de noms Sample.Web.UI.Adapters
{
classe publique FormRewriterControlAdapter :
System.Web.UI.Adapters.ControlAdapter
{
remplacement protégé void Render (écrivain HtmlTextWriter )
{
base .Render ( new RewriteFormHtmlTextWriter (écrivain));
}
}
classe publique RewriteFormHtmlTextWriter : HtmlTextWriter
{
public RewriteFormHtmlTextWriter (écrivain HtmlTextWriter )
: base (écrivain)
{
ceci .InnerWriter = écrivain.InnerWriter;
}
public RewriteFormHtmlTextWriter (écrivain TextWriter )
: base (écrivain)
{
this .InnerWriter = écrivain ;
}
public override void WriteAttribute (nom de chaîne , valeur de chaîne , bool fEncode)
{
si (nom == "action" )
{
Contexte HttpContext = HttpContext .Current ;
if (context.Items[ "ActionAlreadyWritten" ] == null )
{
valeur = contexte.Request.RawUrl ;
context.Items[ "ActionAlreadyWritten" ] = true ;
}
}
base .WriteAttribute(nom, valeur, fEncode);
}
}
}
Pour faire simple, cet adaptateur de contrôle attend en fait le moment où l'attribut "action" est généré et modifie la valeur en l'attribut RawUrl de l'objet Request actuel. Cet attribut est déterminé lorsque ASP.NET reçoit pour la première fois la demande d'IIS. Il ne changera pas avec l'opération de réécriture ultérieure dans BeginRequest. Par conséquent, nous avons uniquement besoin de générer le RawUrl pour l'action Form afin de résoudre le problème de changement d'adresse PostBack.
Toutefois, pour que cet adaptateur de contrôle prenne effet, vous devez également créer un fichier de navigateur dans le projet Web, tel que « App_BrowsersForm.browser », et y écrire le code suivant :
< navigateurs >
< navigateur refID = " Par défaut " >
<adaptateursdecontrôle>
< adaptateur controlType = " System.Web.UI.HtmlControls.HtmlForm "
adapterType = " Sample.Web.UI.Adapters.FormRewriterControlAdapter " />
</ adaptateurs de contrôle >
</navigateur>
</ navigateurs >
À ce stade, le problème des changements d'adresse PostBack provoqués par la réécriture d'URL au niveau ASP.NET a été parfaitement résolu - attendez, pourquoi devrions-nous mettre l'accent sur le « niveau ASP.NET » ? C'est vrai, car si vous effectuez une réécriture d'URL au niveau IIS, ce problème existe toujours. Par exemple, si vous utilisez IIRF pour la réécriture d'URL et activez l'adaptateur de contrôle ci-dessus, vous constaterez toujours que l'adresse PostBack sur la page est différente de l'adresse demandée par le client. RawUrl est-il également devenu « déloyal » ? Cela n'est pas dû à RawUrl, mais est déterminé par le mécanisme ASP.NET. Afin d'expliquer ce problème, regardons à nouveau le schéma du premier article « IIS et ASP.NET » :
La réécriture d'URL au niveau IIS se produit avant l'étape 2 dans l'image ci-dessus. Parce qu'elle est réécrite, le sélecteur ISAPI d'IIS transmettra la requête à ASPNET ISAPI pour traitement. En d'autres termes, lorsque IIS transmet la requête au moteur ASP.NET pour traitement, les informations qu'ASP.NET obtient d'IIS sont déjà l'adresse après la réécriture de l'URL (par exemple, /User.aspx?name=jeffz), donc peu importe Quel que soit l'endroit où ASP.NET traite la demande, il ne peut pas connaître l'URL lorsque IIS a reçu la demande.
En d’autres termes, nous ne pouvons vraiment rien y faire.
Cependant, les quatre mots « il n'y a vraiment aucun moyen » sont conditionnels. Pour le dire complètement, cela devrait être : « s'appuyer sur ASP.NET lui-même » est en effet « il n'y a aucun moyen ». Mais que se passe-t-il si IIS nous aide lors de la réécriture d'URL ? En tant que composant open source mature, IIRF sait naturellement que le moteur ASP.NET et même tous les gestionnaires ISAPI ont besoin de son aide. Il connaît naturellement le principe de « apporter des modifications lorsque vous apportez des modifications », il a donc appris à stocker l'adresse d'origine. Capacités dans la variable serveur HTTP_X_REWRITE_URL. Cependant, IIRF ne le fera pas "consciemment" (comme c'est fatigant), nous devons donc le rappeler dans le fichier de configuration :
RewriteRule ^/User/(d+)$ /User.aspx?id=$1 [I, L , U ]
RewriteRule ^/User/(w+)$ /User.aspx?name=$1 [I, L, U]
Veuillez noter que nous utilisons un modificateur supplémentaire. L'ajout de U à la collection Modifier indique que nous avons besoin de l'IIRF pour stocker l'adresse d'origine avant la réécriture de l'URL dans la variable serveur HTTP_X_REWRITE_URL. Nous pouvons maintenant obtenir cette valeur dans ASP.NET, nous modifions donc la méthode WriteAttribute dans le code précédent de l'adaptateur de contrôle comme suit :
public override void WriteAttribute (nom de chaîne , valeur de chaîne , bool fEncode)
{
si (nom == "action" )
{
Contexte HttpContext = HttpContext .Current ;
if (context.Items[ "ActionAlreadyWritten" ] == null )
{
valeur = contexte.Request.ServerVariables[ "HTTP_X_REWRITE_URL" ]
?? contexte.Request.RawUrl;
context.Items[ "ActionAlreadyWritten" ] = true ;
}
}
base .WriteAttribute(nom, valeur, fEncode);
}
Désormais, la valeur de l'action n'est pas simplement obtenue à partir de l'attribut RawUrl, mais tente d'obtenir la valeur de la variable HTTP_X_REWRITE_URL de la collection ServerVariables, car l'adresse de la requête d'origine reçue par IIS y est stockée.
À ce stade, les principaux sujets concernant la réécriture d'URL ont été abordés. Dans le prochain article, qui est le dernier article de cette série, nous nous concentrerons sur les différences dans certains détails causées par l'utilisation de différents niveaux de réécriture d'URL et sur les points pertinents de cette série. note.