تكنولوجيا نماذج ويب ASP.NET ببطء ولكن بالتأكيد شيء من الماضي. يتم استبداله بواجهة برمجة تطبيقات ويب مع Angular 6 ومكدسات مماثلة. لكنني ورثت مشروعًا في نماذج الويب بإرث ضخم. لدي بعض الأصدقاء الذين لديهم موقف مماثل زائد أو ناقص. تطبيقات طويلة مكتوبة على التكنولوجيا القديمة التي تحتاج إلى تطوير وصيانة. نماذج الويب لديها القدرة على PostBack ليس لتحديث الصفحة بأكملها ، ولكن فقط جزء منها. ما هو ملفوف في UpdatePanel. هذا يضيف التفاعل ، لكنه لا يزال يعمل ببطء شديد ويستهلك الكثير من حركة المرور ، لأنه يحدث العرض في كل مرة على الخادم ، ويتم منح العميل ترميزًا جاهزًا يجب إدراجه بدلاً من div الحالي بالداخل. بالمناسبة ، يتم عرض UpdatePanel فقط في div ، ثم يتم استبدال الترميز.
ما الذي يمكن فعله لتقليل حركة المرور؟
- اكتب WebMethod على الصفحة واتصل بها من العميل باستخدام أدوات AJAX ، عندما تتلقى استجابة ، قم بتغيير DOM عبر JS.
الجانب السلبي لهذا الحل هو أنه لا يمكنك تحديد WebMethod في التحكم. لا أرغب في كتابة جميع الوظائف على الصفحة ، خاصة إذا تم استخدامها عدة مرات على صفحات مختلفة. - اكتب خدمة asmx ، واتصل بها من العميل. هذا أفضل ، ولكن في هذه الحالة لا يوجد اتصال صريح بين عنصر التحكم والخدمة. سيزداد عدد الخدمات مع زيادة عدد الضوابط. بالإضافة إلى ذلك ، لن تكون ViewState متاحة لنا ، مما يعني أننا سنمر المعلمات بشكل صريح عند الوصول إلى الخدمة ، لذلك سنقوم بالتحقق من الخادم والتحقق مما إذا كان للمستخدم الحق في القيام بما طلبه.
- استخدم واجهة ICallbackEventHandler. هذا ، في رأيي ، خيار جيد.
سوف أتطرق إلى مزيد من التفاصيل.
أول شيء يجب فعله هو توريث UserControl من ICallbackEventHandler وكتابة أساليب RaiseCallbackEvent و GetCallbackResult. من الغريب أن هناك اثنان منها ، الأول مسؤول عن تلقي المعلمات من العميل ، والثاني مسؤول عن إرجاع النتيجة.
سيبدو شيء من هذا القبيل
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 }
كان جانب الخادم. العميل الآن
var SomeControl = { _successCallbackHandler: function (responseData) { let data = JSON.parse(responseData); switch (data.Action) { case "continue":
هذا ليس كل شيء. ما زلنا بحاجة إلى إنشاء JS لربط جميع وظائفنا.
protected override void OnLoad(EventArgs e) { base.OnLoad(e);
من الواضح أن هذا رمز وراء عنصر التحكم.
الشيء الأكثر إثارة للاهتمام هو إنشاء وظائف JS باستخدام طريقة GetCallbackEventReference.
نمر فيه
- رابط إلى سيطرتنا
- اسم متغير JS الذي سيتم تمرير قيمته إلى الخادم في طريقة RaiseCallbackEvent عبر eventArgument (السطر أعلاه يقوم بتسلسل الكائن في JSON لإرساله ويقوم بالفعل بتعيين قيمة متغير args)
- اسم رد وظيفة JS للنجاح
- سياق التنفيذ (أنا لا أستخدمه)
- اسم وظيفة رد اتصال JS في حالة حدوث خطأ ما
- سنقوم بالتحقق من صحة الطلب الذي جاء إلى الخادم باستخدام أدوات ASP.NET
كيف سيعمل كل هذا معًا؟
من JS يمكننا استدعاء SomeControl.CallServer ، ستقوم هذه الوظيفة بإنشاء متغيرات محلية وتمرير التحكم إلى وظيفة ستقوم بتقديم طلب إلى الخادم من خلال AJAX.
بعد ذلك ، يتم تمرير التحكم إلى طريقة خادم RaiseCallbackEvent. كل ما كان في متغير عميل args سقط الآن في eventArgument معلمة إدخال الخادم.
بعد تنفيذ RaiseCallbackEvent ، سيتم تمرير التحكم إلى GetCallbackResult.
سيتم إرسال السلسلة التي سنرجعها عبر الإرجاع إلى العميل والدخول إلى معلمة الإدخال الخاصة بدالة SomeControl._successCallbackHandler ، أي في responseData.
إذا طرح رمز الخادم في مرحلة ما استثناءً ، فسيتم نقل التحكم إلى العميل SomeControl._failCallbackHandler
ما زلت بحاجة للقول عن ViewState. يتم نقل ViewState من العميل إلى الخادم ، ويمكن استخدامه ، ولكن فقط في وضع ReadOnly ، مثل لا يتم إرسال ViewState إلى العميل.
التصميم مربك للوهلة الأولى ، ولكن إذا نظرت ، اتضح أنه مريح للغاية ، وتم حفظ حركة المرور.
السؤال الثاني الذي أريد تسليط الضوء عليه في هذه المقالة هو divs القابلة للنقر أو كيف يمكنك التسبب في استدعاء UpdatePanel من العميل.
لماذا يلزم استخدام divs قابل للنقر ، فهل يمكنك استخدام <asp: Button>؟
يعجبني أن div يمكن تكوينه كما أريد ، لست مقيدًا بنوع الإدخال = "button"
من أجل التنفيذ ، من الضروري أن تكون موروثة من واجهة IPostBackEventHandler
لديه طريقة واحدة فقط
public void RaisePostBackEvent(string eventArgument)
الآن ، كما في الحالة السابقة ، نحتاج إلى إنشاء JS لاستدعاء هذه الطريقة
يبدو هذا
Page.ClientScript.GetPostBackEventReference(this, callbackArgument)
تم تعيين callbackArgument على الخادم ولن يعمل تغييره على العميل. ولكن يمكنك دائمًا وضع شيء ما في HiddenField. لدينا PostBack الكامل
يمكن الآن تعليق نتيجة GetPostBackEventReference بمجرد النقر على أي div أو امتداد أو أيا كان.
أو فقط اتصل من JS بواسطة جهاز ضبط الوقت.
تأكد من تسجيل عنصر التحكم على أنه غير متزامن (على OnLoad نسميه
ScriptManager.GetCurrent(Page)?.RegisterAsyncPostBackControl(this);
) ، وإلا ، حتى في داخل UpdatePanel ، سيتم استدعاء PostBack المتزامن وسيتم تحديث الصفحة بأكملها ، وليس فقط محتويات UpdatePanel
باستخدام الطريقتين الموصوفتين أعلاه ، قمت بتطبيق مثل هذا السيناريو.
نقر المستخدم على الزر ، وتم إرسال طلب صغير لعملية طويلة (10-15 ثانية) إلى الخادم ، وتلقى المستخدم استجابة قصيرة ، وأثناء التحليل تم تعيين مكالمات البرنامج النصي للعميل. في setTimeout ، يتم تمرير وظيفة لاستدعاء للخادم من أجل معرفة نتائج العملية المطلوبة مسبقًا. إذا كانت النتيجة جاهزة ، فاتصل بـ PostBack في UpdatePanel - يتم تحديث UpdatePanel المحدد. إذا لم تكن النتيجة جاهزة بعد ، فاتصل setTimeout مرة أخرى.
حظاً طيباً لكل من لا يزال يعمل مع نماذج الويب ، آمل أن تجعل المقالة أنظمتكم أسرع وأجمل ، وسيشكرك المستخدمون.