J'ai reçu un e-mail aujourd'hui et on m'a demandé pourquoi UpdatePanel poserait des problèmes s'il était combiné avec UrlRewrite. Je ne l'ai pas pris au sérieux au début, car j'ai également utilisé UpdatePanel dans UrlRewrite auparavant, et il n'y a eu aucun problème. Cependant, après avoir reçu le code packagé de l'autre partie, j'ai constaté que le problème était effectivement réapparu. Si j'accédais directement à la page cible, il n'y aurait aucun problème. Parce que j'étais dans l'entreprise à ce moment-là et que je n'ai pas étudié attentivement la cause de l'erreur. Sur le chemin du retour, j'ai simulé encore et encore dans mon esprit le processus de mise en œuvre de UpdatePanel, mais je n'ai rien remarqué d'anormal. En fin de compte, je n'ai pas pu m'en empêcher. J'ai ouvert mon ordinateur portable alors que j'étais assis dans le bus et j'ai soigneusement recherché le problème. Le bus tremblait très fort, mais heureusement, j'ai finalement trouvé le problème avant de vomir. Ma pensée à l'instant était toujours fausse.
Reproduire le problème :
Je vais maintenant reproduire le problème. Le UrlRewriteModule de NBear a été utilisé dans le code original. Par souci de simplicité, j'ai utilisé la méthode UrlRewrite la plus courante pour obtenir le même effet, en essayant d'éviter certains amis (dont moi) qui ne sont pas familiers avec NBear et qui gênent la compréhension de l'article. contenu.
Tout d’abord, créez un nouveau site Web compatible ASP.NET AJAX. Créez un fichier ~/SubFolder/Target.aspx avec le contenu suivant :
~/SubFolder/Target.aspx
<html xmlns=" http://www.w3.org/1999/xhtml " >
<head runat="serveur">
<title>Page cible</title>
</tête>
<corps>
<form id="form1" runat="serveur">
<asp:ScriptManager ID="ScriptManager1" runat="server">
</asp:ScriptManager>
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<Modèle de contenu>
<%= DateTime.Now.ToString() %>
<asp:Button ID="Button1" runat="server" Text="Refresh" />
</ContentTemplate>
</asp:UpdatePanel>
</form>
</corps>
</html>
Créez ensuite un Global.asax, fournissez la méthode Application_BeginRequest et implémentez-y Url Rewrite, comme suit :
Méthode Application_BeginRequest dans Global.asax
void Application_BeginRequest (expéditeur d'objet, EventArgs e)
{
HttpContext context = (expéditeur en tant que HttpApplication).Context ;
if (context.Request.Path.Contains("Source.aspx"))
{
context.RewritePath("SubFolder/Target.aspx", false);
}
}
De cette façon, lorsque nous accédons au fichier ~/Source.aspx, il sera réécrit dans ~/SubFolder/Target.aspx, ouvrez la page et tout est normal :
Après avoir cliqué sur le bouton Actualiser, l'heure est mise à jour. Ensuite, lorsque nous avons cliqué à nouveau sur le bouton, l'erreur s'est produite : « Sys.WebForms.PageRequestManagerServerErrorException : Une erreur inconnue s'est produite lors du traitement de la demande sur le serveur. Le code d'état renvoyé par le serveur était : 12031 ».
Analyse du problème :
la raison de ce problème est que Url Rewrite met à jour l'adresse soumise par le formulaire et UpdatePanel reflète le changement d'adresse de la page.
Lorsque l'on ouvre la page pour la première fois, on constate que l'action de l'élément <form /> dans le fichier source de la page n'est plus le Source.aspx auquel nous avons accédé, mais le fichier cible après Url Rewrite :
L'action de l'élément de formulaire est la page cible
...
<form name="form1" method="post" action="SubFolder/Target.aspx" id="form1">
...
</form>
...
Heureusement, nous utilisons le rendu partiel. Tant que la "cible" est correcte, UpdatePanel peut toujours envoyer et obtenir des données correctement, puis mettre à jour la page. Par conséquent, après avoir cliqué sur le bouton Actualiser, la page est mise à jour correctement. Cependant, l'action de notre élément de formulaire a également changé, ce qui peut être vu en un coup d'œil à l'aide de Web Development Helper et de la barre d'outils de développement IE :
Puisque nous avons directement accédé à ~/SubFolder/Target.aspx lors de l'exécution d'une publication asynchrone, la valeur d'action de l'objet Form généré est Target.aspx. En conséquence, UpdatePanel a modifié avec diligence l'action de l'élément de formulaire client. Cela nous permettra d'accéder à une page inexistante lors de notre nouvelle soumission, et les erreurs sont inévitables.
Résoudre le problème :
Maintenant que vous avez découvert le problème, vous pourrez naturellement le résoudre facilement. Il suffit de répondre à l'événement de chargement de Sys.Application. Il sera déclenché lors du premier chargement de la page et après chaque rendu partiel. À ce moment, nous pouvons modifier l'attribut d'action de l'élément de formulaire dans la page. , comme suit :
événement de chargement Sys.Application correspondant
Sys.Application.add_load(fonction()
{
var form = Sys.WebForms.PageRequestManager.getInstance()._form;
form._initialAction = form.action = window.location.href;
});
Quant à savoir pourquoi l'élément de formulaire dans la page doit être obtenu de cette manière, ce qu'est _initialAction et pourquoi il doit être défini, cela implique l'implémentation de UpdatePanel, je ne l'expliquerai donc pas ici. Tant qu'un si petit morceau de code est placé sur la page, ce problème est résolu.
Question approfondie :
La raison de ce problème est en fait qu'après Url Rewrite, l'action de l'élément de formulaire n'est pas l'adresse demandée par le client, mais l'adresse cible de Url Rewrite. Si nous n'utilisons pas le rendu partiel, mais utilisons le PostBack le plus traditionnel, même si la fonction de la page ne sera pas endommagée, après PostBack, l'utilisateur constatera que le contenu de la barre d'adresse a changé et devient directement l'adresse cible. Ce n’est pas le résultat que nous souhaitons voir. Maintenant qu’il a été réécrit, réécrivons-le jusqu’au bout. Bien sûr, nous pouvons toujours utiliser la méthode mentionnée ci-dessus et utiliser JavaScript pour modifier l'action de l'élément de formulaire, mais cette méthode n'est pas assez "belle", et l'utilisateur peut également voir l'adresse cible de notre Url Rewrite à partir de la source HTML. fichier, non ?
Ce serait formidable si nous pouvions définir l'action du formulaire côté serveur, mais malheureusement la classe System.Web.UI.HtmlControls.HtmlForm ne nous permet pas de le faire. Mais heureusement, nous utilisons ASP.NET et le modèle de programmation orienté objet. Nous "héritons" donc de System.Web.UI.HtmlControls.HtmlForm et implémentons notre propre contrôle Form :
héritons de la classe HtmlForm pour implémenter notre propre From
espace de noms ActionlessForm {
Formulaire de classe publique : System.Web.UI.HtmlControls.HtmlForm
{
remplacement protégé void RenderAttributes (écrivain HtmlTextWriter)
{
écrivain.WriteAttribute("nom", this.Name);
base.Attributes.Remove("nom");
écrivain.WriteAttribute("méthode", this.Method);
base.Attributes.Remove("méthode");
this.Attributes.Render(écrivain);
base.Attributes.Remove("action");
si (base.ID != null)
écrivain.WriteAttribute("id", base.ClientID);
}
}
}
Ensuite, nous pouvons l'utiliser dans la page. Bien sûr, avant cela, nous devons l'enregistrer dans la page (ou Web.config) :
utilisez notre propre formulaire implémenté
<%@ Register TagPrefix="skm" Namespace="ActionlessForm"
Assembly="Formulaire sans action" %>
...
<skm:Form id="Form1" method="post" runat="server">
...
</skm:Formulaire>
...
À ce stade, nous n'avons plus besoin d'écrire un JavaScript « intelligent » dans la page. Le problème d'action de l'élément de formulaire après la réécriture de l'URL est résolu.
("Questions approfondies" font référence à une partie de l'article précédent sur MSDN : http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnaspp/html/urlrewriting.asp )
http://www.cnblogs.com/JeffreyZhao/archive/2006/12/27/updatepanel_with_url_rewrite.html