در برنامههای ASP.NET Web Forms، هر درخواست (URL)، به یک فایل با پسوند aspx منطبق میشود. بطور مثال آدرس http://domain/studentsinfo.aspx بایستی با یک فایل فیزیکی به نام studentsinfo.aspx مطابقت داشته باشد. این فایل حاوی code و markup برای پاسخگویی به درخواست ارسالی و نمایش اطلاعات در مرورگر میباشد.
Asp.net
با معرفی سیستم مسیریابی (Routing)، عملیات نگاشت آدرسها به فایلهای فیزیکی را حذف کرد. مسیریابی امکانی را فراهم میکند تا با طراحی الگوی URL، درخواستها را به مدیریت کنندهی درخواستها نگاشت کنیم. این مدیریت کنندهی URLها میتواند یک فایل و یا یک کلاس باشد. در برنامههای وب فرم این مدیریت کننده URL یک فایل فیزیکی است و
در برنامههای MVC یک کلاس (کنترلر) و متد(اکشن) است. بطور مثال درخواست http://domain/students میتواند به آدرس http:domain/studentsinfo.aspx در یک برنامه وب فرم نگاشت شود و یا در یک برنامه MVC به کنترلر Student و اکشن Index .
نکته : مسیریابی مربوط به فریم ورک MVC نمیباشد ، از مسیر یابی هم در WebForm application و هم در MVC Application استفاده میشود.
مسیر (Route) :
Route، الگوی URL و اطلاعات مدیریت کنندهی URL را تعریف میکند. تمامی Routeهای تعریف شدهی در یک برنامه، در جدولی به نام
RouteTable ذخیره میشوند. اطلاعات این جدول توسط موتور مسیریابی (Routing Engine) برای پیدا کردن مدیریت کنندههای URLها مورد استفاده قرار میگیرد.
تصویر زیر فرآیند مسیریابی را نشان میدهد:
پیکربندی مسیر(Route Configuration) :
در برنامههای MVC میبایست حداقل یک Route، پیکربندی و تعریف شده باشد. شما میتوانید یک Route دلخواه را در کلاس RouteConfig که در پوشه App_Start پروژه قرار گرفته است، تعریف کنید. شکل زیر طریقه پیکربندی یک Route را در کلاس RouteConfig، نشان میدهد:
همانطور که در شکل بالا مشاهده میکنید برای پیکره بندی Route از متد الحاقی MapRoute از مجموعه RouteCollection استفاده شده است.
ساختار Route تعریف شده :
• نام: "Default"
• الگوی درخواست: {Id}/{Action}/{Controller}.
• پارامترهای پیش فرض: این بخش در مواقعی که کنترلر، اکشن و یا مقدار Id، در آدرس ارسالی وجود نداشته باشد مورد استفاده قرار میگیرد.
نکته : RouteCollection خصوصیتی از کلاس RouteTable میباشد.
الگوی درخواست (URL Pattern) :
الگوی URL باید بعد از نام دامنه قرار بگیرد. بطور مثال الگوی "{controller}/{action}/{id}" شبیه چنین درخواستی میباشد:
localhost:123/{controller}/{action}/{id}
هر چیزی بعد از نام دامنه ("/localhost:1234") بعنوان کنترلر در نظر گرفته خواهد شد. به همین ترتیب هر چیزی بعد از نام کنترلر، بعنوان اکشن و پس از آن مقدار پارامتر id .
اگر درخواست ارسالی بعد از نام دامنه، فاقد اطلاعات کنترلر و اکشن باشد، کنترلر و اکشن پیش فرض تعریف شده، جایگزین خواهند شد. بطور مثال درخواست localhost:1234 توسط کنترلر پیش فرض Home و متد Index مدیریت خواهد شد (با توجه به الگوی تعریف شده بالا):
جدول زیر وضعیت بررسی URLها بر اساس Route تعریف شدهی فوق را نشان میدهد:
Id | Action | Controller | URL |
null | Index | HomeController |
http://localhost/home |
123 | Index | HomeController | http://localhost/home/index/123 |
null | About | HomeController |
http://localhost/home/about |
null | contact | HomeController |
http://localhost/home/contact |
null | Index | StudentController | http://localhost/student |
123 | Edit | StudentController |
http://localhost/student/edit/123 |
مسیرهای چندگانه (Multiple Route) :
شما براحتی و از طریق MapRoute میتوانید چندین Route سفارشی را تعریف کنید. برای تعریف یک Route، حداقل دو پارامتر Name و الگوی URL الزامی است. بخش پارامترهای پیش فرض در تعریف یک Route، اختیاری است.
مثال: قصد داریم یک Route سفارشی را تعریف کنیم تا هر درخواستی، با الگوی domainName/students از طریق آن مدیریت شود:
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Student",
url: "students/{id}",
defaults: new { controller = "Student", action = "Index" }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
با تعریف Route فوق، کلیه درخواستهایی که با domainName/students شروع میشوند، باید بوسیلهی StudentController مدیریت شوند. همانطور که مشاهده میکنید، در الگوی URL فوق هیچ {action} ای را معرفی نکردهایم. به این خاطر که قصد داریم هر درخواستی که با student شروع میشود از متد Index نوشته شده در کنترلر student استفاده کند.
فریم ورک MVC، کلیه Route های تعریف شده را به ترتیب مورد بررسی قرار خواهد داد. بدین معنی که با آمدن هر درخواست، اولین Route در جدول Routeها را بررسی کرده و اگر درخواست با Students/ شروع نشده بود، به سراغ مسیر تعریف شده بعدی میرود.
جدول زیر چگونگی نگاشت URLهای مختلف را از طریق Route تعریف شده Student، نشان میدهد:
Id | Action | Controller | URL |
123 | Index | StudentController |
http://localhost/students/123 |
123 | Index | StudentController |
http://localhost/students/index/123 |
123 | Index | StudentController |
http://localhost/students/index/123 |
محدود کردن مسیرها (Route Constraints) :
به Route تعریف شده زیر دقت کنید :
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Product",
url: "{Product}/{productid}",
defaults: new { controller = "Product", action = "Details" }
);
اکشن مورد استفاده نهایی هم به شکل زیر میباشد :
public class ProductController : Controller
{
// GET: Product
public ActionResult Details(int prodcutId)
{
return View();
}
}
درخواستهای ارسالی با فرمت زیر، بدون مشکل و توسط Route تعریف شدهی فوق مدیریت خواهند شد:
اما ارسال درخواستهایی با فرمت زیر، سبب بروز خطا خواهد شد:
/Product/apple
/Product/kish
بررسی علت بروز خطا:
انتظار اکشن Details، دریافت یک پارامتر از نوع عددی میباشد. ارسال هر مقداری به غیر از عدد، سبب بروز خطا خواهد شد:
برای حل مشکل فوق باید بر روی الگوی تعریف شده،
محدودیت ایجاد کنیم.
نحوه ایجاد محدودیت بر روی پارامتر id : routes.MapRoute(
name: "Product",
url: "{Product}/{productid}",
defaults: new { controller = "Product", action = "Details" },
constraints: new { productid = @"\d+" }
);
در صورتیکه مقداری غیر عددی، به عنوان پارامتر id ارسال شود، درخواست توسط Route فوق پردازش نخواهد شد و سیستم مسیریابی مجددا به دنبال یک Route که شرایط درخواست را تامین کند، میگردد. در صورت پیدا نشدن یک Route برای پاسخدهی به این درخواست، خطای "The resource could not be found" نمایش داده خواهد شد.
ثبت مسیر (Register Route) :
بعد از پیکربندی کلیه Routeها در کلاس RouteConfig، باید Routeها از طریق رویداد Application_Start موجود در فایل Global.asx ثبت گردند.
بعد از این مرحله کلیه Routeهای تعریف شده به RouteTable اضافه خواهند شد.
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
RouteConfig.RegisterRoutes(RouteTable.Routes);
}
}
شکل زیر، فرآیند ثبت یک Route را نشان میدهد: