Die ASP.NET Web Forms-Technologie gehört langsam aber sicher der Vergangenheit an. Es wird durch eine Web-API mit Angular 6 und ähnlichen Stacks ersetzt. Aber ich habe ein Projekt auf Web Forms mit großem Erbe geerbt. Ich habe einige Freunde, die eine ähnliche oder negative Situation haben. Lang geschriebene Anwendungen auf alten Technologien, die entwickelt und gewartet werden müssen. Web Forms bietet in PostBack die Möglichkeit, nicht die gesamte Seite, sondern nur einen Teil davon zu aktualisieren. Was ist in UpdatePanel verpackt. Dies fügt Interaktivität hinzu, arbeitet aber immer noch ziemlich langsam und verbraucht viel Verkehr, weil Jedes Mal, wenn das Rendern auf dem Server stattfindet und das fertige Markup an den Client übergeben wird, muss dieser anstelle des aktuellen Divs eingefügt werden. UpdatePanel wird übrigens nur in einem div gerendert, in dem dann das Markup ersetzt wird.
Was kann getan werden, um den Verkehr zu minimieren?
- Schreiben Sie WebMethod auf die Seite und rufen Sie es mit AJAX-Tools vom Client aus auf. Wenn Sie eine Antwort erhalten, ändern Sie das DOM über JS.
Der Nachteil dieser Lösung ist, dass Sie WebMethod nicht in der Steuerung definieren können. Ich möchte nicht alle Funktionen auf die Seite schreiben, insbesondere wenn sie mehrmals auf verschiedenen Seiten verwendet werden. - Schreiben Sie einen asmx-Dienst und rufen Sie ihn vom Client aus auf. Dies ist besser, aber in diesem Fall besteht keine explizite Verbindung zwischen dem Steuerelement und dem Dienst. Die Anzahl der Dienste wird mit zunehmender Anzahl der Kontrollen zunehmen. Darüber hinaus steht uns ViewState nicht zur Verfügung. Dies bedeutet, dass wir beim Zugriff auf den Dienst Parameter explizit übergeben. Daher führen wir eine Serverüberprüfung durch und prüfen, ob der Benutzer das Recht hat, das zu tun, was er angefordert hat.
- Verwenden Sie die ICallbackEventHandler-Schnittstelle. Dies ist meiner Meinung nach eine ziemlich gute Option.
Ich werde näher darauf eingehen.
Als erstes erben Sie unser UserControl von ICallbackEventHandler und schreiben die Methoden RaiseCallbackEvent und GetCallbackResult. Es ist etwas seltsam, dass es zwei davon gibt. Der erste ist für den Empfang von Parametern vom Client verantwortlich, der zweite für die Rückgabe des Ergebnisses.
Es wird ungefähr so aussehen
public partial class SomeControl : UserControl, ICallbackEventHandler { #region /// <summary> /// /// </summary> private Guid _someFileId; #endregion #region ICallbackEventHandler /// <inheritdoc /> public void RaiseCallbackEvent(string eventArgument) { // try { dynamic args = JsonConvert.DeserializeObject<dynamic>(eventArgument); _someFileId = (Guid) args.SomeFileId; string type = (string) args.Type; } catch (Exception exc) { // throw; } } /// <inheritdoc /> public string GetCallbackResult() { // try { // - return JsonConvert.SerializeObject(new { Action = actionName, FileId = _someFileId, }); } catch (Exception exc) { // throw; } } #endregion }
Es war die Serverseite. Jetzt Kunde
var SomeControl = { _successCallbackHandler: function (responseData) { let data = JSON.parse(responseData); switch (data.Action) { case "continue":
Das ist noch nicht alles. Wir müssen noch JS generieren, um alle unsere Funktionen zu verbinden.
protected override void OnLoad(EventArgs e) { base.OnLoad(e);
Dies ist offensichtlich Code hinter der Steuerung.
Das Interessanteste ist die Generierung von JS-Funktionen mit der GetCallbackEventReference-Methode.
Wir gehen hinein
- Link zu unserer Kontrolle
- Der Name der JS-Variablen, deren Wert in der RaiseCallbackEvent-Methode über eventArgument an den Server übergeben wird (in der obigen Zeile wird das Objekt in JSON für die Übertragung serialisiert und der Wert dieser args-Variablen selbst festgelegt.)
- Rückrufname der JS-Funktion für Erfolg
- Ausführungskontext (ich benutze ihn nicht)
- Der Name der JS-Rückruffunktion für den Fall, dass etwas schief geht
- Wir werden die Anforderung, die an den Server gesendet wurde, mithilfe von ASP.NET-Tools überprüfen
Wie wird das alles zusammenarbeiten?
Von JS aus können wir SomeControl.CallServer aufrufen. Diese Funktion erstellt eine lokale Variable args und übergibt die Steuerung an eine Funktion, die über AJAX eine Anforderung an den Server sendet.
Als nächstes wird die Steuerung an die RaiseCallbackEvent-Servermethode übergeben. Alles, was in der args-Clientvariablen enthalten war, fiel jetzt in den Servereingabeparameter eventArgument.
Nachdem das RaiseCallbackEvent ausgeführt wurde, wird die Steuerung an GetCallbackResult übergeben.
Die Zeichenfolge, die wir über return zurückgeben, wird an den Client gesendet und fällt in den Eingabeparameter der Funktion SomeControl._successCallbackHandler, dh in responseData.
Wenn der Servercode irgendwann eine Ausnahme auslöst, wird die Steuerung an den Client SomeControl._failCallbackHandler übertragen
Ich muss noch etwas über ViewState sagen. ViewState wird vom Client auf den Server übertragen und kann verwendet werden, jedoch nur im ReadOnly-Modus als ViewState wird nicht an den Client zurückgesendet.
Das Design ist auf den ersten Blick verwirrend, aber wenn Sie es sich ansehen, stellt es sich als ziemlich praktisch heraus und der Verkehr wurde gespeichert.
Die zweite Frage, die ich in diesem Artikel hervorheben möchte, sind anklickbare Divs oder wie Sie veranlassen können, dass das UpdatePanel vom Client aufgerufen wird.
Warum klickbare Divs benötigt werden, können Sie einfach <asp: Button> verwenden?
Ich mag es, dass das div nach Belieben zusammengestellt werden kann, ich bin nicht durch den Eingabetyp = "button" beschränkt.
Für die Implementierung muss es von der IPostBackEventHandler-Schnittstelle geerbt werden
Er hat nur 1 Methode
public void RaisePostBackEvent(string eventArgument)
Jetzt müssen wir wie im vorherigen Fall JS generieren, um diese Methode aufzurufen
Es sieht so aus
Page.ClientScript.GetPostBackEventReference(this, callbackArgument)
callbackArgument ist auf dem Server festgelegt und das Ändern auf dem Client funktioniert nicht. Aber Sie können immer etwas in ein HiddenField einfügen. Wir haben ein volles PostBack
Jetzt kann das Ergebnis der GetPostBackEventReference an den Klick eines Divs oder Span oder was auch immer gehängt werden.
Oder rufen Sie einfach von JS per Timer an.
Stellen Sie sicher, dass Sie das Steuerelement als asynchron registrieren (bei OnLoad rufen wir auf
ScriptManager.GetCurrent(Page)?.RegisterAsyncPostBackControl(this);
) Andernfalls wird auch im UpdatePanel das synchrone PostBack aufgerufen und die gesamte Seite und nicht nur der Inhalt des UpdatePanel aktualisiert
Mit den beiden oben beschriebenen Methoden habe ich beispielsweise ein solches Szenario implementiert.
Der Benutzer klickte auf die Schaltfläche, eine kleine Anfrage für einen langen Vorgang (10-15 Sekunden) wurde an den Server gesendet, der Benutzer erhielt eine kurze Antwort, während deren Analyse das Client-Skript setTimeout aufruft. In setTimeout wird eine Funktion für einen Rückruf an den Server übergeben, um die Ergebnisse einer zuvor angeforderten Operation zu ermitteln. Wenn das Ergebnis fertig ist, rufen Sie PostBack in UpdatePanel auf - das angegebene UpdatePanel wird aktualisiert. Wenn das Ergebnis noch nicht fertig ist, rufen Sie setTimeout erneut auf.
Ich wünsche allen, die noch mit Web Forms arbeiten, viel Glück. Ich hoffe, dass der Artikel Ihre Systeme schneller und schöner macht, und die Benutzer werden es Ihnen danken.