كمثال : <rewriter>
< إعادة الكتابة URL = " ^/المستخدم/(d+)$ " إلى = " ~/User.aspx?id=$1 " المعالجة = " إيقاف " />
< إعادة الكتابة URL = " ^/المستخدم/(w+)$ " إلى = " ~/User.aspx?name=$1 " المعالجة = " إيقاف " />
</ rewriter >
عندما يطلب المستخدم "/User/jeffz"، فإن الكود الذي يظهر على الصفحة سيكون <form action="/User.aspx?name=jeffz" />، وذلك لأنه عندما يتم إنشاء الكود، الصفحة سيتم استخدام القيمة الحالية لـ Request.Url.PathAndQuery للحصول على الإجراء الخاص بعنصر النموذج. يؤدي هذا إلى ظهور "User.aspx?name=jeffz" في شريط العناوين مرة واحدة PostBack، وقد لا يتمكن هذا العنوان من طلب المورد الصحيح (لأنه قد تتم إعادة كتابته في مكان آخر، أو بسبب العلاقات على مستوى الدليل). مثل هذا المورد). في المقالة السابقة " UpdatePanel and UrlRewrite "، قلت أنه يمكن حل هذه المشكلة عن طريق إضافة سطر من كود JavaScript في نهاية الصفحة:
< script language ="javascript" type ="text/javascript">
document.getElementsByTagName( "form" )[0].action = window.location;
</script> الغرض من
هذا السطر من التعليمات البرمجية واضح جدًا. قم بتغيير إجراء النموذج إلى window.location (أي المسار في شريط عنوان المتصفح)، بحيث عندما تقوم الصفحة بإجراء PostBack، سيتم عرض العنوان الهدف. يكون العنوان قبل إعادة كتابة URL. هذا الأسلوب يمكن أن يجعل البرنامج يعمل بشكل طبيعي، لكنه في الحقيقة لا يرضيني. لماذا؟
لأنه قبيح جدا.
لأننا مازلنا نكشف العنوان بعد إعادة كتابة عنوان URL للعميل. طالما أن المستخدم قام بتثبيت برنامج HTTP sniffer (مثل Fiddler الشهير)، أو اختار مباشرة عرض الملف المصدر في IE، فسيتم عرض عنواننا المستهدف أمام المستخدم دون أي إخفاء. كيف يمكننا السماح للمستخدمين بمعرفة قواعد إعادة الكتابة لدينا؟ يجب علينا حل هذه المشكلة. الحل بسيط للغاية ويحظى بشعبية كبيرة بالفعل، وهو استخدام محول التحكم لتغيير سلوك إنشاء النموذج. ولكن ما يجعلني أشعر بالغرابة هو أن جميع عمليات البحث عن محول التحكم هذا على الإنترنت هي إصدارات VB.NET، ولكن لا يمكن العثور على لغة C# التي تروج لها Microsoft بشكل أساسي. على الرغم من أنه ليس من الصعب إعادة الكتابة طالما أنك تفهم القليل من بناء جملة VB.NET، إلا أنه لا يزال عملاً إضافيًا على كل حال. لذلك سأقوم بنشر رمز إصدار C# لهذا المحول الآن حتى يتمكن الأصدقاء من استخدامه مباشرة:
مساحة الاسم Sample.Web.UI.Adapters
{
الفئة العامة FormRewriterControlAdapter :
System.Web.UI.Adapters.ControlAdapter
{
تجاوز محمي عرض باطلة (كاتب HtmlTextWriter )
{
base .Render( new RewriteFormHtmlTextWriter (writer));
}
}
الفئة العامة RewriteFormHtmlTextWriter : HtmlTextWriter
{
RewriteFormHtmlTextWriter العام (كاتب HtmlTextWriter )
: قاعدة (كاتب)
{
this .InnerWriter =writer.InnerWriter;
}
RewriteFormHtmlTextWriter العام (كاتب النصوص )
: قاعدة (كاتب)
{
هذا .InnerWriter = الكاتب؛
}
التجاوز العام لـ WriteAttribute (اسم السلسلة ، قيمة السلسلة ، bool fEncode)
{
إذا (الاسم == "الإجراء" )
{
HttpContext context = HttpContext .Current;
إذا (context.Items[ "ActionAlreadyWritten" ] == null )
{
value = context.Request.RawUrl;
context.Items[ "ActionAlreadyWritten" ] = صحيح ؛
}
}
base .WriteAttribute(name, value, fEncode);
}
}
}
بكل بساطة، كان محول التحكم هذا ينتظر بالفعل اللحظة التي يتم فيها إخراج سمة "الإجراء"، ويقوم بتغيير القيمة إلى سمة RawUrl لكائن الطلب الحالي. يتم تحديد هذه السمة عندما يتلقى ASP.NET الطلب من IIS لأول مرة، ولن تتغير مع عملية إعادة الكتابة اللاحقة في BeginRequest. لذلك، نحتاج فقط إلى إخراج RawUrl لإجراء النموذج لحل مشكلة تغيير عنوان PostBack.
ومع ذلك، لكي يصبح محول التحكم ساري المفعول، يجب عليك أيضًا إنشاء ملف متصفح في مشروع الويب، مثل "App_BrowsersForm.browser"، وكتابة التعليمة البرمجية التالية فيه:
< browsers >
< المتصفح المرجع = " الافتراضي " >
<محولات التحكم>
< محول نوع التحكم = " System.Web.UI.HtmlControls.HtmlForm "
محول نوع = " Sample.Web.UI.Adapters.FormRewriterControlAdapter " />
</ التحكم في المحولات >
</ المتصفح >
</ browsers >
في هذه المرحلة، تم حل مشكلة تغييرات عنوان PostBack الناتجة عن إعادة كتابة عنوان URL على مستوى ASP.NET تمامًا - انتظر، لماذا يجب علينا التأكيد على "مستوى ASP.NET"؟ هذا صحيح، لأنه إذا قمت بإعادة كتابة عنوان URL على مستوى IIS، فستظل هذه المشكلة موجودة. على سبيل المثال، إذا كنت تستخدم IIRF لإعادة كتابة عنوان URL وقمت بتمكين محول التحكم أعلاه، فسوف تجد أن عنوان PostBack الموجود على الصفحة يختلف عن العنوان الذي طلبه العميل. هل أصبح RawUrl أيضًا "غير مخلص"؟ لا يرجع ذلك إلى RawUrl، ولكن يتم تحديده بواسطة آلية ASP.NET. من أجل شرح هذه المشكلة، دعونا نلقي نظرة مرة أخرى على الرسم التخطيطي في المقالة الأولى " IIS and ASP.NET ":
تتم إعادة كتابة عنوان URL على مستوى IIS قبل الخطوة 2 في الصورة أعلاه، نظرًا لأنه تمت إعادة كتابته، سيقوم محدد ISAPI الخاص بـ IIS بتسليم الطلب إلى ASPNET ISAPI للمعالجة. بمعنى آخر، عندما يقوم IIS بتسليم الطلب إلى محرك ASP.NET للمعالجة، فإن المعلومات التي يحصل عليها ASP.NET من IIS هي بالفعل العنوان بعد إعادة كتابة عنوان URL (على سبيل المثال، /User.aspx?name=jeffz)، لذلك لا يهم بغض النظر عن المكان الذي يعالج فيه ASP.NET الطلب، فإنه لا يمكنه معرفة عنوان URL عندما يتلقى IIS الطلب.
وبعبارة أخرى، لا يوجد شيء يمكننا القيام به حيال ذلك.
ومع ذلك، فإن الكلمات الأربع "لا توجد طريقة حقًا" مشروطة، وبعبارة كاملة، يجب أن تكون: "الاعتماد على ASP.NET نفسه" هو بالفعل "ليس هناك طريقة". ولكن ماذا لو ساعدنا IIS عند إجراء إعادة كتابة عنوان URL؟ باعتباره مكونًا ناضجًا مفتوح المصدر، يعرف IIRF بطبيعة الحال أن محرك ASP.NET وحتى جميع معالجات ISAPI بحاجة إلى مساعدته، ومن الطبيعي أن يعرف مبدأ "إجراء التغييرات عند إجراء التغييرات"، لذلك تعلم كيفية تخزين العنوان الأصلي. الإمكانيات الموجودة في متغير الخادم HTTP_X_REWRITE_URL. ومع ذلك، لن يقوم IIRF بذلك "بوعي" (كم هو متعب)، لذا نحتاج إلى تذكيره في ملف التكوين:
RewriteRule ^/User/(d+)$ /User.aspx?id=$1 [I, L , U ]
RewriteRule ^/User/(w+)$ /User.aspx?name=$1 [I, L, U]
يرجى ملاحظة أننا نستخدم معدلًا إضافيًا. تشير إضافة U إلى مجموعة Modifier إلى أننا بحاجة إلى IIRF لتخزين العنوان الأصلي قبل إعادة كتابة عنوان URL في متغير الخادم HTTP_X_REWRITE_URL. الآن يمكننا الحصول على هذه القيمة في ASP.NET، لذلك نقوم بتعديل طريقة WriteAttribute في كود Control Adaptor السابق على النحو التالي:
public override void WriteAttribute( string name, string value, bool fEncode)
{
إذا (الاسم == "الإجراء" )
{
HttpContext context = HttpContext .Current;
إذا (context.Items[ "ActionAlreadyWritten" ] == null )
{
القيمة = context.Request.ServerVariables[ "HTTP_X_REWRITE_URL" ]
؟؟ سياق.Request.RawUrl؛
context.Items[ "ActionAlreadyWritten" ] = صحيح ؛
}
}
base .WriteAttribute(name, value, fEncode);
}
الآن لا يتم الحصول على قيمة الإجراء ببساطة من سمة RawUrl، ولكن يحاول الحصول على قيمة متغير HTTP_X_REWRITE_URL من مجموعة ServerVariables، لأنه يتم تخزين عنوان الطلب الأصلي الذي تلقاه IIS هناك.
في هذه المرحلة، تمت تغطية المواضيع الرئيسية حول إعادة كتابة عنوان URL، وفي المقالة التالية، وهي المقالة الأخيرة في هذه السلسلة، سنركز على الاختلافات في بعض التفاصيل الناتجة عن استخدام مستويات مختلفة من إعادة كتابة عنوان URL، والنقاط ذات الصلة. ملحوظة.