Perkecil lalu lintas di Formulir Web ASP.NET, div yang dapat diklik, dan polling server berkala

Teknologi ASP.NET Web Forms lambat tapi pasti merupakan sesuatu dari masa lalu. Itu sedang digantikan oleh API Web dengan Angular 6 dan tumpukan serupa. Tapi saya mewarisi proyek di Formulir Web dengan warisan besar. Saya punya beberapa teman yang memiliki plus atau minus situasi serupa. Aplikasi lama yang ditulis tentang teknologi lama yang perlu dikembangkan dan dipelihara. Formulir Web memiliki kemampuan pada PostBack untuk tidak me-refresh seluruh halaman, tetapi hanya sebagian saja. Apa yang dibungkus dengan UpdatePanel. Ini menambah interaktivitas, tetapi masih berfungsi cukup lambat dan menghabiskan banyak lalu lintas, karena Setiap kali rendering berlangsung di server, dan markup yang sudah selesai diteruskan ke klien, yang perlu dimasukkan bukan div saat ini di dalam. Omong-omong, UpdatePanel baru saja dirender dalam div, di mana kemudian markup diganti.

Apa yang dapat dilakukan untuk meminimalkan lalu lintas?

  1. Tulis WebMetode pada halaman dan panggil dari klien menggunakan alat AJAX, ketika Anda menerima respons, ubah DOM melalui JS.

    Kelemahan dari solusi ini adalah Anda tidak dapat menentukan metode Web dalam kontrol. Saya tidak ingin menulis semua fungsi pada halaman, terutama jika digunakan beberapa kali pada halaman yang berbeda.
  2. Tulis layanan asmx, dan panggil dari klien. Ini lebih baik, tetapi dalam hal ini tidak ada koneksi eksplisit antara kontrol dan layanan. Jumlah layanan akan tumbuh dengan peningkatan jumlah kontrol. Selain itu, kondisi tampilan tidak akan tersedia bagi kami, yang berarti kami akan melewati parameter secara eksplisit ketika mengakses layanan, jadi kami akan melakukan validasi server dan memeriksa apakah pengguna memiliki hak untuk melakukan apa yang ia minta.
  3. Gunakan antarmuka ICallbackEventHandler. Menurut saya ini adalah opsi yang cukup bagus.

    Saya akan membahasnya lebih terinci.

Hal pertama yang harus dilakukan adalah mewarisi UserControl kami dari ICallbackEventHandler dan menulis metode RaiseCallbackEvent dan GetCallbackResult. Agak aneh bahwa ada 2 di antaranya. Yang pertama bertanggung jawab untuk menerima parameter dari klien, yang kedua bertanggung jawab untuk mengembalikan hasilnya.
Akan terlihat seperti ini

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 } 

Itu adalah sisi server. Sekarang klien

 var SomeControl = { _successCallbackHandler: function (responseData) { let data = JSON.parse(responseData); switch (data.Action) { case "continue": // -   break; case "success": //  -  break; case "fail": //   break; default: //   alert,     alert("      "); break; } }, _failCallbackHandler: function() { alert("      "); }, } 

Bukan itu saja. Kita masih perlu membuat JS untuk menghubungkan semua fungsi kita.

  protected override void OnLoad(EventArgs e) { base.OnLoad(e); //   SomeControl.js,     Page.ClientScript.RegisterClientScriptInclude(Page.GetType(), "SomeControl", "/Scripts/controls/SomeControl.js?v=2.24.0"); string callbackArgument = //   //***  .***   JS   SomeControl  CallServer.       ,     ScriptManager.RegisterStartupScript(Page, Page.GetType(), "SomeControl.Initialize", $@"SomeControl.CallServer = function(someFileId) {{ let args = JSON.stringify({{ SomeFileId : someFileId, Type: '{callbackArgument}' }}); {Page.ClientScript.GetCallbackEventReference(this, "args", "SomeControl._successCallbackHandler", string.Empty, "SomeControl._failCallbackHandler", true)}; }};", true); //    ScriptManager.GetCurrent(Page)?.RegisterAsyncPostBackControl(this); } 

Ini jelas kode di belakang kendali.

Yang paling menarik adalah pembuatan fungsi JS menggunakan metode GetCallbackEventReference.

Kami melewati itu

  • tautan ke kendali kami
  • nama variabel JS yang nilainya akan diteruskan ke server dalam metode RaiseCallbackEvent melalui eventArgument (baris di atas membuat serialisasi objek dalam JSON untuk transmisi dan benar-benar menetapkan nilai variabel args ini)
  • Nama panggilan balik fungsi JS untuk sukses
  • konteks eksekusi (saya tidak menggunakannya)
  • nama fungsi JS callback jika terjadi kesalahan
  • kami akan memvalidasi permintaan yang datang ke server menggunakan alat ASP.NET

Bagaimana semua ini akan bekerja bersama?

Dari JS kita dapat memanggil SomeControl.CallServer, fungsi ini akan membuat argumen variabel lokal dan meneruskan kontrol ke fungsi yang akan membuat permintaan ke server melalui AJAX.
Selanjutnya, kontrol diteruskan ke metode server RaiseCallbackEvent. Semua yang ada di variabel klien args sekarang jatuh ke parameter input server eventArgument.
Setelah RaiseCallbackEvent dijalankan, kontrol akan diteruskan ke GetCallbackResult.

String yang akan kami kembalikan melalui pengembalian akan dikirim ke klien dan masuk ke parameter input dari fungsi SomeControl._successCallbackHandler, yaitu di responseData.
Jika pada tahap tertentu kode server mengeluarkan Exception, maka kontrol akan ditransfer ke klien SomeControl._failCallbackHandler

Masih perlu dikatakan tentang ViewState. ViewState ditransfer dari klien ke server, dan itu dapat digunakan, tetapi hanya dalam mode ReadOnly, sebagai ViewState tidak dikirim kembali ke klien.

Desainnya membingungkan pada pandangan pertama, tetapi jika Anda melihatnya, ternyata cukup nyaman, dan lalu lintas dihemat.

Pertanyaan kedua yang ingin saya bahas dalam artikel ini adalah div yang dapat diklik atau bagaimana Anda dapat memanggil pembaruan UpdatePanel dari sisi klien.

Mengapa div yang dapat diklik diperlukan, bisakah Anda menggunakan <asp: Button>?
Saya suka bahwa div dapat dibuat seperti yang saya inginkan, saya tidak dibatasi oleh tipe input = "tombol"

Untuk implementasi perlu diwariskan dari antarmuka IPostBackEventHandler

Dia hanya memiliki 1 metode

 public void RaisePostBackEvent(string eventArgument) 

Sekarang, seperti pada kasus sebelumnya, kita perlu membuat JS untuk memanggil metode ini

Ini terlihat seperti ini

 Page.ClientScript.GetPostBackEventReference(this, callbackArgument) 

callbackArgument diatur pada server dan mengubahnya pada klien tidak akan berfungsi. Tetapi Anda selalu dapat memasukkan sesuatu ke dalam HiddenField. Kami memiliki PostBack penuh

Sekarang hasil dari GetPostBackEventReference dapat digantung pada onclick dari setiap div atau rentang, atau apa pun.

Atau telepon dari JS dengan timer.

Pastikan untuk mendaftarkan kontrol sebagai tidak sinkron (pada OnLoad kami memanggil

 ScriptManager.GetCurrent(Page)?.RegisterAsyncPostBackControl(this); 
), jika tidak, bahkan ketika di dalam UpdatePanel, PostBack yang sinkron akan dipanggil dan seluruh halaman akan diperbarui, dan bukan hanya konten dari UpdatePanel

Menggunakan 2 metode yang dijelaskan di atas, saya menerapkan, misalnya, skenario seperti itu.

Pengguna mengklik tombol, permintaan kecil untuk operasi panjang (10-15 detik) dikirim ke server, pengguna menerima respons singkat, selama analisis yang skrip klien memanggil setTimeout. Di setTimeout, fungsi dilewatkan untuk panggilan balik ke server untuk mengetahui tentang hasil operasi yang diminta sebelumnya. Jika hasilnya siap, panggil PostBack di UpdatePanel - UpdatePanel yang ditentukan diperbarui. Jika hasilnya belum siap, panggil setTimeout lagi.

Semoga sukses bagi semua orang yang masih bekerja dengan Formulir Web, saya harap artikel ini akan membuat sistem Anda lebih cepat dan lebih indah, dan pengguna akan berterima kasih.

Source: https://habr.com/ru/post/id427291/


All Articles