ملخص:
تعتمد هذه المقالة على الكود المصدري لـ ASP.NET 2.0 وتجري تحليلًا موجزًا لوقت تشغيل ASP.NET 2.0 وآمل أن تساعدك على فهم عملية معالجة الطلب ونموذج تجميع الصفحات في ASP.NET 2.0.
الكلمات الرئيسية:
وقت تشغيل ASP.NET 2.0، المبادئ، معالجة الطلب، تجميع الصفحات، فئات ASP.NET 2.0 HTTP Runtime
الرئيسية:
System.Web.HttpRuntime
System.Web.HttpApplicationFactory
System.Web.HttpApplication
System.Web.Compilation.BuildManager
System.Web.Compilation.ApplicationBuildProvider
System.Web.Compilation.BuildProvidersCompiler
System.Web.UI.PageHandlerFactory
مخطط تدفق موجز لمعالجة الطلب:
اقتراحات القراءة:
استخدم أداة العاكس لعرض التعليمات البرمجية المصدر لـ ASP.NET 2.0 أثناء القراءة.
تحليل:
عندما نبدأ طلبًا لصفحة asp.net على موقع ASP.NET 2.0 من خلال المتصفح، يتلقى IIS الطلب أولاً من جانب الخادم. عندما يرى IIS أنها صفحة asp.net، أشعر بسعادة غامرة بسبب هذا لا يحتاج الطلب إلى معالجته، فقط اتركه لـ ASP.NET ISAPI. يعد عمل ASP.NET ISAPI أيضًا سهلًا نسبيًا. وتتمثل مهمته الرئيسية في ترتيب aspnet_wp.exe لمعالجة الطلبات ومراقبة تنفيذ عملية aspnet_wp.exe إذا كانت عملية aspnet_wp.exe متعبة جدًا ولا يمكنها إكمال المهمة حسنًا، سيقوم ASP.NET ISAPI بتسريحه واستبداله بملف aspnet_wp.exe جديد للتعامل مع العمل.
تتمثل المهمة الرئيسية لـ aspnet_wp.exe في تسليم الطلبات إلى سلسلة من الكائنات المُدارة تسمى خطوط أنابيب HTTP. إذا تمت مقارنة ASP.NET ISAPI بمدير المبيعات، فإن aspnet_wp.exe هو مدير الإنتاج، وخط أنابيب HTTP هو خط أنابيب الإنتاج. الفريق المسؤول عن خط التجميع هو HttpRuntime. سيقوم مدير الإنتاج aspnet_wp.exe بتسليم الطلب (طلب HTTP) إلى ProcessRequest (HttpWorkerRequest wr) عضو فريق HttpRuntime. ) وفقًا للتقسيم الداخلي للعمل، لذا فإن ProcessRequestInternal(HttpWorkerRequest wr) هو محور تحليلنا.
العمل الرئيسي لـ ProcessRequestInternal هو:
1. قم بإنشاء مثيل HttpContext.
2. تهيئة الطلب الأول (EnsureFirstRequestInit).
أ) تنفيذ بعض أعمال التهيئة في EnsureFirstRequestInit عن طريق استدعاء System.Web.HttpRuntime.FirstRequestInit، مثل قراءة تكوين Web.Config في RuntimeConfig وتحميل كافة ملفات dll من دليل bin.
3. قم بإنشاء مثيل HttpWriter.
4. قم بإنشاء مثيل HttpApplication عن طريق استدعاء HttpApplicationFactory.GetApplicationInstance.
هناك ثلاث طرق رئيسية في HttpApplicationFactory.GetApplicationInstance:
HttpApplicationFactory._theApplicationFactory.EnsureInited();
HttpApplicationFactory._theApplicationFactory.EnsureAppStartCalled(context);
HttpApplicationFactory._theApplicationFactory.GetNormalApplicationInstance(context);
دعنا نحلل هذه الطرق الثلاث واحدة تلو الأخرى:
1) HttpApplicationFactory._theApplicationFactory.EnsureInited();
تتحقق هذه الطريقة مما إذا كان قد تم تهيئة HttpApplicationFactory، وإذا لم يكن الأمر كذلك، فستتم تهيئته من خلال HttpApplicationFactory.Init().
في Init()، احصل أولاً على المسار الكامل لملف global.asax، ثم قم باستدعاء CompileApplication() لتجميع global.asax.
كيف يتم تنفيذ التجميع؟
تم إكمال أعمال التجميع بواسطة BuildManager. يحصل BuildManager أولاً على GlobalAsaxType (أي HttpApplication)، ثم يستدعي BuildManager.GetGlobalAsaxBuildResult() =》GetGlobalAsaxBuildResultInternal() =》EnsureTopLevelFilesCompiled() للتجميع.
في EnsureTopLevelFilesCompiled، يتم تجميع CompilationStage.TopLevelFiles أولاً، ويتم تجميع الملفات الموجودة في الدلائل الثلاثة التالية:
أ.CompileResourcesDirectory();
ترجمة الدليل App_GlobalResources.
ب.CompileWebRefDirectory();
ترجمة الدليل App_WebReferences.
ج.
ترجمة الدليل App_Code.
ثم قم بتجميع CompilationStage.GlobalAsax، وتجميع global.asax، واستدعاء الأسلوب: CompileGlobalAsax()=》ApplicationBuildProvider.GetGlobalAsaxBuildResult(BuildManager.IsPrecompiledApp).
يتم إكمال التجميع المحدد في GetGlobalAsaxBuildResult بواسطة ApplicationBuildProvider وBuildProvidersCompiler.
BuildProvidersCompiler.PerformBuild(); ينفذ أعمال التجميع.
يحصل ApplicationBuildProvider.GetBuildResult على النتيجة المجمعة.
بعد التحويل البرمجي الناجح، سيتم إنشاء ملف dll مشابه لـ App_global.asax.mlgx7n2v.dll في الدليل المقابل لـ C:WINDOWSMicrosoft.NETFrameworkv2.0.50727Temporary ASP.NET Files.
تسمى الفئة المترجمة ASP.global_asax وترث من HttpApplication.
ملاحظة: إذا لم يكن هناك ملف Global.asax في دليل الويب، فلن يتم تجميع وإنشاء ملفات مثل App_global.asax.mlgx7n2v.dll.
2) HttpApplicationFactory._theApplicationFactory.EnsureAppStartCalled(context);
قم بإنشاء مثيل HttpApplication محدد، وقم بتشغيل الحدث ApplicationOnStart، وقم بتنفيذ أسلوب Application_Start(object sender, EventArgs e) في ASP.global_asax. تتم إعادة تدوير مثيل HttpApplication الذي تم إنشاؤه هنا بعد معالجة الحدث.
3) HttpApplicationFactory._theApplicationFactory.GetNormalApplicationInstance(context);
يقوم هذا الأسلوب بإنشاء مثيل HttpApplication وتهيئته (استدعاء الأسلوب System.Web.HttpApplication.InitInternal()).
يعتمد إنشاء مثيل HttpApplication على _theApplicationType الفعلي. إذا لم يكن هناك ملف global.asa في دليل الويب، فهذا يعني أنه لا يوجد تجميع ديناميكي لإنشاء نوع ASP.global_asax، ثم قم بإنشاء مثيل HttpApplication مباشرة. إذا تم إنشاء نوع ASP.global_asax، فقم بإنشاء مثيل ASP.global_asa.
بعد إنشاء مثيل HttpApplication، قم باستدعاء أسلوب InitInternal الخاص بالمثيل.
طريقة InitInternal هي أيضًا الطريقة التي نركز عليها، والوظائف الرئيسية لهذه الطريقة هي كما يلي:
1. InitModules (): قم بإنشاء HttpModules المقابلة وفقًا لإعدادات Web.Config.
2. HookupEventHandlersForAppplicationAndModules: بناءً على الحدث الذي يحدث، قم باستدعاء وظيفة معالجة الحدث المقابلة في مثيل HttpApplication.
3. قم بإنشاء العديد من مثيلات الفئات التي تطبق واجهة IExecutionStep وأضفها إلى _execSteps لمثيل HttpApplication الحالي، وانتظر تنفيذ رد الاتصال. من هنا يمكننا أن نرى أن HttpApplication يعالج الطلبات بطريقة غير متزامنة، ويتم وضع العديد من مهام معالجة الطلبات في _execStep لانتظار تنفيذ رد الاتصال.
عمل المعالجة الرئيسي في _execStep هو كما يلي:
1) إجراء فحص أمني على المسار المطلوب وحظر الوصول غير القانوني إلى المسار (ValidatePathExecutionStep).
2) إذا تم تعيين UrlMappings، فقم بإجراء RewritePath(UrlMappingsExecutionStep).
3) تنفيذ وظائف معالجة الأحداث، مثل: BeginRequest، وAuthenticateRequest، وما إلى ذلك.
4) احصل على HttpHandler الذي يعالج الطلب الحالي ويتم هنا أيضًا تجميع وقت التشغيل لصفحة ASP.NET. (مابهاندلريكسيكوتيونستيب)
تتم هذه المعالجة عن طريق استدعاء الأسلوب System.Web.HttpApplication.MapHttpHandler.
في MapHttpHandler، احصل أولاً على النوع المقابل الذي يطبق IHttpHandlerFactory من web.config وفقًا للعنوان الذي تم الوصول إليه. بالنسبة لصفحات asp.net، يكون الإعداد الافتراضي هو PageHanlderFactory. ثم قم بإنشاء مثيل PageHanlderFactory، واستدعاء GetHandlerHelper، واستدعاء BuildManager.CreateInstanceFromVirtualPath في GetHandlerHelper لتجميع وإنشاء مثيل لصفحة ASP.NET المطلوبة حاليًا (إذا تم تجميعها، فقم بتحميلها مباشرة من ذاكرة التخزين المؤقت).
يقوم CreateInstanceFromVirtualPath بتمرير مهمة الترجمة إلى BuildManager () بعد عدة استدعاءات للأسلوب. يحصل CompileWebFile على BuildProvider المطابق من web.config بالنسبة لملفات .aspx، فإن BuildProvider المطابق هو PageBuildProvider. لن يتم هنا إجراء مزيد من التحليل حول كيفية قيام PageBuildProvider بتجميع الصفحات. إذا كنت مهتمًا، فيمكنك دراسة الكود المصدري لـ ASP.NET 2.0 بشكل أكبر.
5) اتصل بأسلوب .ProcessRequest الخاص بـ HttpHandler المقابل لمعالجة الطلب (إذا كان غير متزامن، فاتصل بـ BeginProcessReques). (كالهاندليركسيكوتيونستيب)
6) اكتب محتوى الرد في الفلتر. (CallFilterExecutionStep)
5. قم باستدعاء BeginProcessRequest لمثيل HttpApplication لمعالجة الطلب بشكل غير متزامن.
يتم تنفيذ العديد من الأشياء التي تحدث في _execSteps المذكورة أعلاه بعد أن يستدعي HttpRuntime HttpApplication BeginProcessRequest ثم يستدعي ResumeSteps في BeginProcessRequest.
يعد وقت تشغيل ASP.NET 2.0 جزءًا معقدًا للغاية ويصعب فهمه ومهمًا من ASP.NET 2.0. ستساعدنا دراسة الكود المصدري لوقت تشغيل ASP.NET 2.0 على تعميق فهمنا لمبادئ ASP.NET 2.0. يقدم لنا تطوير تطبيقات ASP.NET 2.0 الكثير من المساعدة. هذه المقالة هي المرة الأولى التي أتعلم فيها وقت تشغيل ASP.NET 2.0، وقد تمت كتابتها لمساعدتي في فهم وقت تشغيل ASP.NET 2.0 بشكل أفضل. مرحباً بك في انتقاد محتوى المقالة وتقديم اقتراحات بشأنها.
أشعر أن كتابة المقالات لا يمكنها فقط تحسين مهارات الكتابة وتسهيل التواصل، ولكن أيضًا من خلال كتابة المقالات، يمكن للمرء توضيح أفكاره الخاصة وتعزيز التفكير المتعمق وتعميق فهمه للتكنولوجيا لا تزال كتابة بعض المقالات التقنية مفيدة جدًا لتحسين نفسك.