تلقيت بريدًا إلكترونيًا اليوم وسُئلت عن سبب تسبب UpdatePanel في حدوث مشكلات إذا تم دمجه مع UrlRewrite. لم آخذ الأمر على محمل الجد في البداية، لأنني استخدمت UpdatePanel أيضًا في UrlRewrite من قبل، ولم تكن هناك مشكلة. ومع ذلك، بعد تلقي الكود المعبأ من الطرف الآخر، وجدت أن المشكلة قد تكررت بالفعل. إذا قمت بالوصول إلى الصفحة المستهدفة مباشرة، فلن تكون هناك مشكلة. لأنني كنت في الشركة في ذلك الوقت ولم أدرس سبب الخطأ بعناية. في طريق عودتي إلى المنزل، قمت بمحاكاة عملية تنفيذ UpdatePanel مرارًا وتكرارًا في ذهني، لكنني لم ألاحظ أي خطأ. في النهاية، لم أستطع مساعدة نفسي، فتحت جهاز الكمبيوتر المحمول الخاص بي أثناء جلوسي في الحافلة وبحثت بعناية عن المشكلة. كانت الحافلة تهتز بشدة، ولكن لحسن الحظ وجدت المشكلة أخيرًا قبل أن أتقيأ، وكان تفكيري الآن لا يزال خاطئًا.
إعادة إنتاج المشكلة:
الآن سأقوم بإعادة إنتاج المشكلة. تم استخدام UrlRewriteModule الخاص بـ NBear في الكود الأصلي، ومن أجل التبسيط، استخدمت طريقة UrlRewrite الأكثر شيوعًا للحصول على نفس التأثير، محاولًا تجنب بعض الأصدقاء (بما فيهم أنا) الذين ليسوا على دراية بـ NBear ويعيقون فهم المقالة. محتوى.
أولاً، قم بإنشاء موقع ويب جديد ممكّن لـ ASP.NET AJAX. قم بإنشاء ملف ~/SubFolder/Target.aspx بالمحتوى التالي:
~/SubFolder/Target.aspx
<html xmlns=" http://www.w3.org/1999/xhtml " >
<رئيس التشغيل = "الخادم">
<title>الصفحة المستهدفة</title>
</الرأس>
<الجسم>
<معرف النموذج = "form1" runat = "الخادم">
<asp:ScriptManager ID = "ScriptManager1" runat = "الخادم">
</asp:ScriptManager>
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<قالب المحتوى>
<%= DateTime.Now.ToString() %>
<asp:Button ID = "Button1" runat = "server" Text = "تحديث" />
</ContentTemplate>
</asp:UpdatePanel>
</النموذج>
</الجسم>
</html>
ثم قم بإنشاء Global.asax، وقم بتوفير أسلوب Application_BeginRequest، وقم بتنفيذ إعادة كتابة عنوان Url فيه، كما يلي:
أسلوب Application_BeginRequest في Global.asax
باطلة Application_BeginRequest (مرسل الكائن، EventArgs e)
{
HttpContext context = (المرسل كـ HttpApplication).Context;
إذا (context.Request.Path.Contains("Source.aspx"))
{
context.RewritePath("SubFolder/Target.aspx", false);
}
}
بهذه الطريقة، عندما نصل إلى الملف ~/Source.aspx، ستتم إعادة كتابته إلى ~/SubFolder/Target.aspx، افتح الصفحة، وسيكون كل شيء طبيعيًا:
بعد النقر على زر التحديث، يتم تحديث الوقت. ثم عندما نقرنا على الزر مرة أخرى، حدث الخطأ: "Sys.WebForms.PageRequestManagerServerErrorException: حدث خطأ غير معروف أثناء معالجة الطلب على الخادم. رمز الحالة الذي تم إرجاعه من الخادم هو: 12031".
تحليل المشكلة:
سبب هذه المشكلة هو أن Url Rewrite يقوم بتحديث العنوان المقدم بواسطة النموذج، ويعكس UpdatePanel التغيير في عنوان الصفحة.
عندما نفتح الصفحة لأول مرة، يمكننا أن نرى أن إجراء عنصر <form /> في الملف المصدر للصفحة لم يعد هو Source.aspx الذي وصلنا إليه، بل هو الملف الهدف بعد إعادة كتابة عنوان Url:
الإجراء عنصر النموذج هو الصفحة المستهدفة
...
<اسم النموذج = "form1" طريقة = "نشر" الإجراء = "SubFolder/Target.aspx" معرف = "form1">
...
</النموذج>
...
لحسن الحظ، نحن نستخدم العرض الجزئي طالما أن "الهدف" صحيح، فلا يزال بإمكان UpdatePanel إرسال البيانات والحصول عليها بشكل صحيح، ثم تحديث الصفحة. لذلك، بعد النقر فوق الزر "تحديث"، يتم تحديث الصفحة بشكل صحيح. ومع ذلك، فقد تغير أيضًا إجراء عنصر النموذج الخاص بنا، والذي يمكن رؤيته في لمحة سريعة باستخدام Web Development Helper وIE Dev Toolbar:
نظرًا لأننا وصلنا مباشرة إلى ~/SubFolder/Target.aspx عند تنفيذ PostBack غير المتزامن، فإن قيمة الإجراء لكائن النموذج الذي تم إنشاؤه هي Target.aspx. ونتيجة لذلك، قام UpdatePanel بتعديل إجراء عنصر نموذج العميل بعناية. سيسمح لنا هذا بالوصول إلى صفحة غير موجودة عندما نرسلها مرة أخرى، وستكون الأخطاء أمرًا لا مفر منه.
حل المشكلة:
الآن بعد أن اكتشفت المشكلة، ستتمكن بطبيعة الحال من حلها بسهولة. نحتاج فقط إلى الرد على حدث التحميل الخاص بـ Sys.Application، وسيتم تشغيله عند تحميل الصفحة لأول مرة وبعد كل عرض جزئي. في هذا الوقت، يمكننا تعديل سمة الإجراء لعنصر النموذج في الصفحة ، كما يلي:
حدث تحميل Sys.Application المطابق
Sys.Application.add_load(function())
{
var form = Sys.WebForms.PageRequestManager.getInstance()._form;
form._initialAction =form.action = window.location.href;
});
أما لماذا يجب الحصول على عنصر النموذج في الصفحة بهذه الطريقة، وما هو _initialAction، ولماذا يجب تعيينه، فهو يتضمن تنفيذ UpdatePanel، لذلك لن أشرح ذلك هنا. وطالما تم وضع هذا الجزء الصغير من التعليمات البرمجية على الصفحة، فسيتم حل هذه المشكلة.
سؤال متعمق:
سبب هذه المشكلة هو في الواقع أنه بعد إعادة كتابة عنوان URL، فإن إجراء عنصر النموذج ليس هو العنوان الذي يطلبه العميل، بل هو العنوان المستهدف لإعادة كتابة عنوان URL. إذا لم نستخدم العرض الجزئي، لكننا استخدمنا PostBack الأكثر تقليدية، على الرغم من أن وظيفة الصفحة لن تتضرر، بعد PostBack، سيجد المستخدم أن محتوى شريط العناوين قد تغير وأصبح العنوان المستهدف مباشرة. هذه ليست النتيجة التي نريد رؤيتها. والآن بعد أن تمت إعادة كتابتها، فلنعيد كتابتها حتى النهاية. بالطبع، لا يزال بإمكاننا استخدام الطريقة المذكورة أعلاه واستخدام JavaScript لتعديل إجراء عنصر النموذج، ولكن هذه الطريقة ليست "جميلة" بدرجة كافية، ويمكن للمستخدم أيضًا رؤية العنوان المستهدف لإعادة كتابة عنوان URL الخاص بنا من مصدر HTML ملف، لا؟
سيكون أمرًا رائعًا لو تمكنا من ضبط إجراء النموذج على جانب الخادم، ولكن لسوء الحظ فإن فئة System.Web.UI.HtmlControls.HtmlForm لا تسمح لنا بالقيام بذلك. لكن لحسن الحظ، نحن نستخدم ASP.NET، ونستخدم نموذج البرمجة الشيئية. لذلك "نرث" System.Web.UI.HtmlControls.HtmlForm وننفذ عنصر التحكم في النموذج الخاص بنا:
نرث فئة HtmlForm لتنفيذ عنصر التحكم الخاص بنا من
مساحة الاسم ActionlessForm {
نموذج الفئة العامة: System.Web.UI.HtmlControls.HtmlForm
{
تجاوز محمي لRenderAttributes (كاتب HtmlTextWriter)
{
WriteAttribute("name", this.Name);
base.Attributes.Remove("name");
WriteAttribute("method", this.Method);
base.Attributes.Remove("method");
this.Attributes.Render(writer);
base.Attributes.Remove("action");
إذا (base.ID! = فارغ)
الكاتب.WriteAttribute("id"، base.ClientID);
}
}
}
ثم يمكننا استخدامه في الصفحة. بالطبع، قبل ذلك، نحتاج إلى تسجيله في الصفحة (أو Web.config):
استخدم النموذج المطبق الخاص بنا
<%@ سجل TagPrefix="skm" Namespace="ActionlessForm"
التجميع = "ActionlessForm" %>
...
<skm:Form id="Form1"method="post" runat="server">
...
</skm:نموذج>
...
في هذه المرحلة، لم نعد بحاجة إلى كتابة جافا سكريبت "ذكي" في الصفحة، حيث تم حل مشكلة الإجراء الخاصة بعنصر النموذج بعد إعادة كتابة عنوان URL.
("أسئلة متعمقة" تشير إلى جزء من المقالة السابقة على 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