PDA

View Full Version : مقاله: اصلاح مسيرهاي نسبي در ASP.NET هنگام استفاده از بازنويسي URLها



s.mostafa.rahmani
چهارشنبه 21 مرداد 1388, 20:49 عصر
اين روش معمولاً در مواقعي استفاده مي‌شود كه از مسيرهاي نسبي در پروژه استفاده مي‌كنيم كه در اين حالت لينكها (تصاوير، CSSها و ...) در محيط توسعه درست كار مي‌كنند (چون VS مسيرهاي مجازي را در وب سرور خود مورد استفاده قرار مي‌دهد)، در حالي كه در محل نهايي سايت ممكن است اين مسيرها و لينكها از همان مسيرهاي مجازي استفاده نكنند. ساده‌ترين راه براي حل مشكل در چنين موقعيتي اين است كه تمام مسيرهاي مجازي را در محيط توسعه تغيير دهيم. براي اين كار، صفحه مشخصات (Properties) پروژه سايت خود را ببينيد. يك تنظيم مسيرهاي مجازي (Virtual Path) وجود دارد. اين تنظيم را به '/' تغيير دهيد، ديگر در محيط توسعه مسيرهاي مجازي نخواهيد داشت. البته اين تنظيم فقط در VS 2005 SP1 به بالا عمل مي‌كند. اگر اين تنظيم را در پروژه انجام دهيد، براحتي مي توانيد در هر جاي پروژه از مسيرهاي مطلق استفاده نماييد.
با بازنويسي URLها مي‌توان آدرسهاي زيباتري در سايت داشت. مثلاً ما آدرسي مانند http://devtoolshed.com/product.aspx?id=1234 را به http://devtoolshed.com/product/1234. تغيير مي‌دهيم. اين كا را مي‌توانيد براحتي با استفاده از ماژول بازنويسي URL در IIS7 كه ابزار بسيار جالبي است، انجام دهيد.
لينكهاي مشكل‌دار
همه چيز درست كار مي‌كند تا اين كه لينكهايي را پيدا مي‌كنيم كه به جاي مسير مطلق از مسيرهاي نسبي استفاده كرده‌اند. به عنوان مثال، تصويري را در نظر بگيريد كه از آدرس "images/logo.gif" استفاده مي‌كند. بعد از بازنويسي URL وقتي URL اصلي تغيير كرد، مرورگر به دنبال http://devtoolshed.com/product/images/logo.gif مي‌گردد، كه وجود ندارد (مسير درست http://devtoolshed.com/images/logo.gif است).
راه‌هاي مختلفي براي حل اين مسأله وجود دارد كه خيلي‌هايش در چنين موقعيتي به درد نمي‌خورند.
انتخاب 1: تمام مسيرهاي پروژه را به مسيرهاي مطلق تغيير دهيد.
يك انتخاب اين است كه تمام URLها را به مسيرهاي مطلق مانند "/images/logo.gif" تغيير دهيم. مشكل اين راه حل اين است كه وقتي داريد سايت را محيط توسعه VS مي‌بينيد درست كار نمي‌كند چون وب سرور محيط توسعه، سايت را به جاي مسير ريشه وب سرور از زير پوشه اجرا مي‌كند. اين، كار توسعه و تست را سخت مي‌كند.
انتخاب 2: استفاده از ~/
كنترلهاي .NET اجازه استفاده از "~/page.aspx" يا "~/images/image.png" را مي‌دهند و خودشان ~/ را به مسير درست تغيير مي‌دهند. سحرآميز است! اين روش هم در محيط توسعه و هم در محيط اجراي نهايي در مواقع عادي درست كار مي‌كند، اما اگر از بازنويسي URLها استفاده كنيد ديگر كار نمي‌كند چون هنگام بازنويسي به مسيرهاي نسبي ترجمه مي‌شوند.
انتخاب 3: از قوانين بازنويسي بيشتري هنگام بازنويسي URL استفاده كنيد.
مي‌توانيد به موتور بازنويسي URL بگوييد كه آدرسهاي مشكل‌دار را قبول كرده و آنها را به آدرسهايي كه درست كار مي‌كنند تبديل كند. متأسفانه اگر مسير كمي طولاني شود، اين كار تبديل به يك كابوس مي‌گردد. من اين روش را توصيه نمي‌كنم.
انتخاب 4: استفاده از Request.ApplicationPath (راه درست)
پيشوند Rquest.ApplicationPath را به ابتداي تمام لينكهاي خود اضافه كنيد، در اكثر مواقع درست عمل مي‌كند. اين كار مسير مطلق به ريشه آدرس وب سايت را به شما مي‌دهد. اين خوب است چون به ما امكان كار با مسيرهاي مطلق را مي‌دهد، و خوب است چون بر اساس محيط اجرا (چه محيط توسعه و چه محيط اجراي نهايي) تغيير مي‌كند. يك مشكل آن اين است كه با / آخر آدرس كنار نمي‌آيد. بدون اين كه به جزئيات و دليل اين موضوع اشاره كنم، مي‌گويم كه راه درست براي آدرس دهي اين است كه هميشه از Request.ApplicationPath.TrimEnd('/') استفاده كنيم.
وقتي از اين راه استفاده مي‌كنيد كدهاي شما در فايل كد شبيه به اين مي‌شوند:

Response.Redirect(Request.ApplicationPath.TrimEnd( '/') + "/url.aspx");
sb.Append("<a href=\"" + Request.ApplicationPath.TrimEnd('/') + "search.aspx?q=" + ...);

و فايل aspx شبيه به اين:

<a href=<%= Request.ApplicationPath.TrimEnd('/') + "/Rss.aspx" %> >RSS Feed</a>
<link href=<%= Request.ApplicationPath.TrimEnd('/') + "/css/style.css" %> rel="stylesheet" type="text/css" />
و البته بعد از اين كار لينكهاي شما هميشه درست كار خواهند كرد.

اما در مورد CSS
ليكنهاي CSS كمي پيچيده‌تر هستند چون شما به طور پيوش فرض نمي‌توانيد از Request.ApplicationPath در آنها استفاده كنيد. راه حل اين است كه فايلهاي CSS را مانند كد C# تجزيه (Parse) كنيد. وقتي من اولين بار اين تكنيك را ديدم چندشم شد، اما بعد از اين كه كمي بيشتر در مورد آن فكر كردم و بعد از اين كه واقعاً از آن استفاده كردم، به شدت به اين تكنيك علاقمند شدم. علاوه بر اين كه مي‌توانيد لينكهايي در فايلهاي CSS ايجاد كنيد كه هميشه كار كنند، مي‌توانيد فايلهاي CSSي ايجاد كنيد كه انعطاف بيشتري هم داشته باشند - تصور كنيد بلوكهاي if/else و ... در فايل CSS. حال به چگونگي انجام اين كار مي‌پردازيم. در فايل web.config اين دو قسمت را اضافه كنيد:

<compilation debug="true">
<buildProviders>
<!-- So we can map paths correctly in css files -->
<add extension=".css" type="System.Web.Compilation.PageBuildProvider" />
</buildProviders>
</compilation>

و
براي IIS 6

<httpHandlers>
<add path="*.css" verb="GET" type="System.Web.UI.PageHandlerFactory" validate="True" />
</httpHandlers>
براي IIS 7

<system.webServer>
<handlers>
<add name="Parse CSS Files" preCondition="integratedMode" verb="GET" path="*.css" type="System.Web.UI.PageHandlerFactory" />
</handlers>
</system.webServer>
و در فايل CSS:

<!-- اين خط را در ابتداي فايل قرار دهيد. با اين كار همه مرورگرها اين فايل را به عنوان يك سي‌اس‌اس خواهند شناخت. -->
<%@ ContentType="text/css" %>

.home_background
{
background-image:url(<%= Request.ApplicationPath.TrimEnd("/") %>/images/bg_home_search.png);
}

منبع: DevToolShed.com (http://www.devtoolshed.com/content/fixing-relative-paths-c-aspnet-when-using-url-rewriting)

پ.ن: در پوشه‌هاي خاص ASP.NET مانند App_Theme نمي‌توان از اين روش استفاده كرد. يعني فايل CSSي كه از اين كد استفاده مي‌كند نبايد در اين پوشه باشد (وگرنه با خطا مواجه خواهيد شد). مشكل خود من اين است كه معمولاً از تم‌ها استفاده مي‌كنم و حال اگر بخواهم از اين روش استفاده كنم بايد با تغيير تم با كد نويسي فايل‌هاي CSS جديد را معرفي كنم. البته مي‌توان از فايلهاي .Skin استفاده كرد، اما هميشه جوابگو نيست. اگر از دوستان كسي راه حلي براي اين موضوع داشت در همين پست ما را هم آگاه كند.

با تشكر

s.mostafa.rahmani
یک شنبه 25 مرداد 1388, 10:57 صبح
يك مشكل ديگر كه در ادامه مسأله قبلي (كه در آخر متن قبلي گفتم يعني فايلهاي داخل پوشه App_Theme) اين است كه در CSSهاي داخل تگهاي HTML (يعني Style) هم امكان استفاده از اين روش وجود ندارد. گرچه اين مشكل خاصي نيست و براحتي مي‌توان آن را با يك فايل CSS جايگزين كرد. اما مشكل فايلهاي CSS داخل پوشه تم همچنان وجود دارد كه نمي‌توان از كد C# داخل آنها استفاده كرد.

hadi000333
یک شنبه 25 مرداد 1388, 14:52 عصر
(<%= Request.ApplicationPath.TrimEnd("/") %>/images/bg_home_search.png
دوست من تابع ResolveUrl رو برای همچین مواقعی گذاشتن .
هر موقع بخوایی آدرس مجازی رو به مطلق تبدیل کنی
می تونی ار تابع ResolveUrl استفاده کنی
و در مورد CSS ها من مشکلی نداشتم.

asp2.net
سه شنبه 15 شهریور 1390, 10:02 صبح
میشه یک مثال بزنید.ممنون میشم

Saber_Fatholahi
سه شنبه 15 شهریور 1390, 11:02 صبح
<link href='<%# ResolveUrl("~/App_Themes/Admin/admin.css") %>' rel="stylesheet" type="text/css" />
<link href='<%# ResolveUrl("~/App_Themes/Pages/grid.css")%>' rel="stylesheet" type="text/css" />
<script type="text/javascript" src='<%# ResolveUrl("~/Scripts/jquery-1.4.1.min.js") %>'></script>


اینک چند تا مثال

بعدش توی PageLoad بنویس



protected void Page_Load(object sender, EventArgs e)
{
Page.Header.DataBind();
}


موفق و موید باشید