Ich habe heute eine E-Mail erhalten und wurde gefragt, warum UpdatePanel in Kombination mit UrlRewrite Probleme verursachen würde. Ich habe es zunächst nicht ernst genommen, da ich UpdatePanel bereits zuvor in UrlRewrite verwendet habe und es kein Problem gab. Nachdem ich jedoch den gepackten Code von der anderen Partei erhalten hatte, stellte ich fest, dass das Problem tatsächlich erneut aufgetreten war, wenn ich direkt auf die Zielseite zugegriffen hätte. Weil ich zu diesem Zeitpunkt im Unternehmen war und die Fehlerursache nicht sorgfältig untersucht habe. Auf dem Heimweg habe ich in Gedanken immer wieder den Implementierungsprozess von UpdatePanel simuliert, aber mir ist nichts Ungewöhnliches aufgefallen. Am Ende konnte ich nicht anders, als ich im Bus saß, öffnete ich meinen Laptop und suchte sorgfältig nach dem Problem. Der Bus zitterte sehr stark, aber zum Glück fand ich das Problem endlich, bevor ich mich übergeben musste. Meine Überlegungen waren gerade noch falsch.
Reproduzieren des Problems:
Jetzt werde ich das Problem reproduzieren. Das UrlRewriteModule von NBear wurde im Originalcode verwendet. Der Einfachheit halber habe ich die gängigste UrlRewrite-Methode verwendet, um den gleichen Effekt zu erzielen, und versucht, einige Freunde (einschließlich mir) zu vermeiden, die mit NBear nicht vertraut sind und das Verständnis des Artikels behindern Inhalt.
Erstellen Sie zunächst eine neue ASP.NET AJAX-fähige Website. Erstellen Sie eine Datei ~/SubFolder/Target.aspx mit folgendem Inhalt:
~/SubFolder/Target.aspx
<html xmlns=" http://www.w3.org/1999/xhtml " >
<head runat="server">
<title>Zielseite</title>
</head>
<Körper>
<form id="form1" runat="server">
<asp:ScriptManager ID="ScriptManager1" runat="server">
</asp:ScriptManager>
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<%= DateTime.Now.ToString() %>
<asp:Button ID="Button1" runat="server" Text="Refresh" />
</ContentTemplate>
</asp:UpdatePanel>
</form>
</body>
</html>
Erstellen Sie dann eine Global.asax, stellen Sie die Methode Application_BeginRequest bereit und implementieren Sie darin URL Rewrite wie folgt:
Methode Application_BeginRequest in Global.asax
void Application_BeginRequest(object sender, EventArgs e)
{
HttpContext context = (sender as HttpApplication).Context;
if (context.Request.Path.Contains("Source.aspx"))
{
context.RewritePath("SubFolder/Target.aspx", false);
}
}
Wenn wir auf diese Weise auf die Datei ~/Source.aspx zugreifen, wird sie in ~/SubFolder/Target.aspx umgeschrieben, die Seite geöffnet und alles ist normal:
Nach dem Klicken auf die Schaltfläche „Aktualisieren“ wird die Uhrzeit aktualisiert. Als wir dann erneut auf die Schaltfläche klickten, trat der Fehler auf: „Sys.WebForms.PageRequestManagerServerErrorException: Bei der Verarbeitung der Anfrage auf dem Server ist ein unbekannter Fehler aufgetreten. Der vom Server zurückgegebene Statuscode war: 12031“.
Analyse des Problems:
Der Grund für dieses Problem liegt darin, dass Url Rewrite die vom Formular übermittelte Adresse aktualisiert und UpdatePanel die Änderung der Adresse auf der Seite widerspiegelt.
Wenn wir die Seite zum ersten Mal öffnen, können wir sehen, dass die Aktion des <form />-Elements in der Quelldatei der Seite nicht mehr die Source.aspx ist, auf die wir zugegriffen haben, sondern die Zieldatei nach Url Rewrite:
Die Aktion des Formularelements ist die Zielseite
...
<form name="form1" method="post" action="SubFolder/Target.aspx" id="form1">
...
</form>
...
Glücklicherweise verwenden wir Partial Rendering, solange das „Ziel“ korrekt ist, kann UpdatePanel weiterhin Daten korrekt senden und empfangen und dann die Seite aktualisieren. Daher wird die Seite nach dem Klicken auf die Schaltfläche „Aktualisieren“ korrekt aktualisiert. Allerdings hat sich auch die Aktion unseres Formularelements geändert, was mit Web Development Helper und IE Dev Toolbar auf einen Blick erkennbar ist:
Da wir beim Durchführen des asynchronen PostBacks direkt auf ~/SubFolder/Target.aspx zugegriffen haben, ist der Aktionswert des generierten Formularobjekts Target.aspx. Infolgedessen hat UpdatePanel die Aktion des Client-Formularelements sorgfältig geändert. Dadurch können wir beim erneuten Absenden auf eine nicht vorhandene Seite zugreifen, und Fehler sind unvermeidlich.
Lösen Sie das Problem:
Nachdem Sie das Problem entdeckt haben, können Sie es natürlich problemlos lösen. Wir müssen nur auf das Ladeereignis von Sys.Application reagieren. Es wird ausgelöst, wenn die Seite zum ersten Mal geladen wird und nach jedem Teilrendering. Zu diesem Zeitpunkt können wir das Aktionsattribut des Formularelements auf der Seite ändern , wie folgt:
Entsprechendes Sys.Application-Ladeereignis
Sys.Application.add_load(function()
{
var form = Sys.WebForms.PageRequestManager.getInstance()._form;
form._initialAction = form.action = window.location.href;
});
Warum das Formularelement auf der Seite auf diese Weise abgerufen werden sollte, was _initialAction ist und warum es festgelegt werden sollte, erfordert die Implementierung von UpdatePanel, daher werde ich es hier nicht erklären. Solange ein so kleiner Codeabschnitt auf der Seite platziert wird, ist dieses Problem gelöst.
Eingehende Frage:
Der Grund für dieses Problem liegt tatsächlich darin, dass die Aktion des Formularelements nach dem Url Rewrite nicht die vom Client angeforderte Adresse ist, sondern die Zieladresse des Url Rewrite. Wenn wir kein partielles Rendering verwenden, sondern das traditionellste PostBack verwenden, wird der Benutzer nach PostBack feststellen, dass sich der Inhalt der Adressleiste geändert hat und direkt zur Zieladresse wird, obwohl die Seitenfunktion nicht beschädigt wird. Dies ist nicht das Ergebnis, das wir sehen möchten. Nachdem es nun umgeschrieben wurde, schreiben wir es bis zum Ende um. Natürlich können wir weiterhin die oben erwähnte Methode verwenden und JavaScript verwenden, um die Aktion des Formularelements zu ändern, aber diese Methode ist nicht „schön“ genug und der Benutzer kann die Zieladresse unseres URL-Rewrites auch aus der HTML-Quelle sehen Datei, nicht ?
Es wäre toll, wenn wir die Aktion des Formulars auf der Serverseite festlegen könnten, aber leider erlaubt uns die Klasse System.Web.UI.HtmlControls.HtmlForm dies nicht. Aber glücklicherweise verwenden wir ASP.NET und das objektorientierte Programmiermodell. Also „erben“ wir System.Web.UI.HtmlControls.HtmlForm und implementieren unser eigenes Form-Steuerelement:
Erben Sie die HtmlForm-Klasse, um unser eigenes From zu implementieren
Namespace ActionlessForm {
öffentliches Klassenformular: System.Web.UI.HtmlControls.HtmlForm
{
protected override void RenderAttributes(HtmlTextWriter-Writer)
{
write.WriteAttribute("name", this.Name);
base.Attributes.Remove("name");
write.WriteAttribute("method", this.Method);
base.Attributes.Remove("method");
this.Attributes.Render(writer);
base.Attributes.Remove("action");
if (base.ID != null)
write.WriteAttribute("id", base.ClientID);
}
}
}
Dann können wir es auf der Seite verwenden. Zuvor müssen wir es natürlich auf der Seite (oder Web.config) registrieren:
Verwenden Sie unser eigenes implementiertes Formular
<%@ Register TagPrefix="skm" Namespace="ActionlessForm"
Assembly="ActionlessForm" %>
...
<skm:Form id="Form1" method="post" runat="server">
...
</skm:Form>
...
An diesem Punkt müssen wir kein „cleveres“ JavaScript mehr in die Seite schreiben. Das Aktionsproblem des Formularelements nach dem URL-Rewrite ist gelöst.
(„Ausführliche Fragen“ siehe Teil des vorherigen Artikels zu 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