
دو نوع routing وجود دارد:
- مرسوم یا قراردادی / Conventional
- صفتی / Attribute
همانطور که در آموزش های قبل گفته شد، زمانی که request ای از مرورگر به سمت اپلیکیشن می آید این controller است که آن را مدیریت می کند. کاربر همیشه آدرس کنترلر را وارد میکند. به عنوان مثال اگر کاربر آدرس https://localhost:44312/student/details/2 را وارد کند، واژه ی Student به نام کنترلر اشاره دارد، بعد از آن نام اکشن می آید که در اینجا نام اکشن درخواست شده، Details است. و بعد از آن هم مقدار پارامتر ورودی این اکشن قرار می گیرد.
1 2 3 4 5 6 7 8 9 10 11 |
public class StudentController : Controller { public IActionResult Index() { //Some code } public IActionResult Details(int id) { //Some code } } |
Conventional Routing
این مدل routing ، به مرسومی یا قراردادی معروف است. برای پیاده سازی باید در فایل Startup و در متد Configure کد زیر را نوشت.
1 2 |
//using routing app.UseRouting(); |
و به عنوان آخرین middleware ، باید کد های مربوط به EndPoint را به شکل زیر نوشت. اگر پروژه را به صورت Blank تعریف نکرده باشید، این کدها از قبل وجود دارند و میتوان آنها را با توجه به نیاز پروژه ویرایش کرد.
1 2 3 4 5 6 |
app.UseEndpoints(endpoints => { endpoints.MapControllerRoute( name: "default", pattern: "{controller=Home}/{action=Index}/{id?}"); }); |
این کد باعث می شود که بتوان مسیر سایت را طبق قرارداد پیش فرض پیمایش کرد، مانند زیر:
https://localhost:44312/student/details/2
Attribute Routing
این مدل routing بر پایه ی attribute است یعنی بالای هر اکشن به صورت attribute تعیین می کنیم که کاربر با وارد کردن چه آدرسی می تواند این اکشن را اجرا کند و نسبت به Conventional Routing انعطاف پذیرتر است. برای پیاده سازی این مدل routing باید در فایل Startup و در متد Configure به جای این کد زیر
1 |
app.UseRouting(); |
باید کد زیر را بنویسیم و کد مربوط به EndPoint را هم حذف کنیم.
1 |
app.UseMvc(); |
و در متد ConfigureService به جای کد زیر
1 |
services.AddMvc(); |
کد زیر را می نویسیم تا به سرویس ها اطلاع دهیم که از مدلی از MVC می خواهیم استفاده کنیم که نیازی به EndPoint نداشته باشد. اگر این کار را انجام ندهیم سرویس AddMVC به دنبال middleware مربوط به EndPoint خواهد گشت و خطا بروز پیدا می کند.
1 |
services.AddMvc((mvcOptions) => { mvcOptions.EnableEndpointRouting = false; }); |
با این کار برنامه از mvc استفاده می کند ولی از هیچ routing ای پشتیبانی نمی کند. در این حالت با هر آدرسی که در مرورگر وارد کنیم با خطای 404 مواجه می شویم.
برای حل این مشکل، در کنترلر مورد نظر به سراغ یکی از متد ها می رویم، مثلا متد Index در Controller ای به نام Student می تواند گزینه ی خوبی باشد. حال به آن متد یک Attribute اضافه میکنیم:
1 2 3 4 5 |
[Route("")] public IActionResult Index() { //Some Code } |
این کد باعث می شود که هنگامی که در مرورگر، فقط آدرس سایت را وارد کردیم این متد از این کنترلر اجرا شود و با خطای 404 مواجه نشویم. حتی می توانیم attribute های دیگری نیز اضافه کنیم:
1 2 3 4 5 6 7 |
[Route("")] [Route("Student")] [Route("Student/Index")] public IActionResult Index() { //Some Code } |
و با پیمایش به آدرس https://localhost:44312/student/index می توان به قسمت دلخواه از وبسایت رسید. برای افزودن attribute routing به متد هایی که ورودی می گیرند از روش زیر استفاده می کنیم تا احتمال بروز خطا را کاهش دهیم:
1 2 3 4 |
public IActionResult Details(int? id) { //Some Code } |
نکته: عبارت id??1 بیان می کند که اگر id برابر null بود مقدار یک و در غیر این صورت مقدار خودش را وارد متد کند.
نکته: می توان attribute ای را بالای کلاس کنترلر اضافه کرد تا نام کنترلر ابتدای هر attribute نوشته نشود.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
[Route("Student")] public class StudentController : Controller { [Route("")] [Route("Index")] [Route("~/")] public IActionResult Index() { //Some Code } [Route("Details/{id?}")] public IActionResult Details(int? id) { //Some Code } |
دقت کنید در این صورت باید به اکشن root یعنی همان index یک attribute خاص ( تیلدا فوروراد اسلش) هم اضافه کرد. یکی از مزایای استفاده از attribute routing، پشتیبانی از Token Replacement است.
Token Replacement
استفاده از attribute routing به این شکل یک عیب بزرگ دارد. اگر بعدا اسم متد، کنترلر و … تغییر پیدا کند، باید همه ی attribute ها را هم عوض کرد. برای حل این مشکل از Token Replacement استفاده می شود. به Token های داخل کروشه ها دقت کنید:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
[Route("[controller]")] public class StudentController : Controller { [Route("")] [Route("[action]")] [Route("~/")] public IActionResult Index() { //Some Code } [Route("[action]/{id?}")] public IActionResult Details(int? id) { //Some Code } } |