MVC Routing
Bu makalemizde MVC Routing kavramını ele alacağız. ASP.Net üzerinde route işlemi sunucuda fiziksel dosya (.aspx) üzerinden direkt olarak gerçekleştirilirdi, MVC’de ise bu işlem için Controller sınıfından Action metot çağrısı yapmaktadır. Peki MVC Routing aslında ne yapıyor ? Yaptığı iş istemci (client) üzerinden sunucu (server) tarafına gönderilen isteği ilgili Controller metoduna yönlendirmektir. Yapılan bu yönlendirme ile kullanıcının gözüne hoş gelecek bir URL oluşur ve çeşitli güvenlik açıklarından da kaçınmış oluruz.Bildiğiniz gibi MVC (Model View Controller) yapısında kullanıcının erişmek istediği sayfa, yapılan istek sonrası ilgili Controller’ın Action metodu üzerinden dönen View ile gerçekleşiyor. Bazı View’ların isimleri kullanıcı için uygun bir yapıda olmayabilir.Estetik konusunu bir kenara bıraksak bile direkt olarak Controller metot ismini adres çubuğunda görmek riskli bir durumdur. Neyse ki MVC Routing ile bu gibi durumlara önlem alabiliyoruz.
Örneklerimize geçmeden önce Mvc Routing makalemizde göz atacağımız başlıkları listeleyelim.
- App_Start ve RouteConfig.cs
- Route Ekleme
- Parametreli Route Ekleme
- Route Filter
- Http Filter
- Regex Filter
- RouteConstraint Filter
Örneklerimiz için bilisimIOMVCRouting adında bir proje oluşturalım. Ben projeyi oluştururken ekranda gelen şablonlardan Empty olanı seçtim. Proje oluştururken farklı seçenekler üzerinden belli başlı özelliklerin bulunduğu projeleri otomatik olarak oluşturabilirsiniz.
Şimdi Controller klasörü üzerinden Add > New ile HomeController adında bir sınıf ekliyoruz. Daha sonra View klasörü içine Controller ismimiz ile bir klasör ekleyip içine Index adında bir View ekliyoruz.
AppStart ve RouteConfig sınıfı
App_Start klasörü programımızla ilgili genel ayarlara yönelik sınıfların bulunduğu klasördür. App_Start içinde RouteConfig.cs sınıfı otomatik olarak oluşturulur. Sınıf controller sınıflarını dinleyerek herhangi bir controller metot çağrısı olduğunda devreye girer ve ilgili yönlendirmeyi yapar.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
using System.Web.Mvc; using System.Web.Routing; namespace bilisimIOMVCRouting { public class RouteConfig { public static void RegisterRoutes(RouteCollection routes) { routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); routes.MapRoute( name: "Default", url: "{controller}/{action}/{id}", defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } ); } } } |
yukarıda RouteConfig sınıfının ilk halini görüyoruz. Hali hazırda eklenen dosya üzerinde herhangi bir değişiklik yapmazsak site içerisindeki tüm adres(URL)ler eklenen MapRoute kurallarına göre işletilir.
Projemizi çalıştırıp oluşran URL bilgisine baktığımızda http://localhost:22067/Home/Index veya http://localhost:22067/ şeklinde bir adres göreceğiz.
Config sınıfımız içinde herhangi bir değişiklik yapmadığımız için istemciden gelen isteği default olarak değerlendirdi ve belirlenen düzene göre ( url : “{controller}/{action}/{id}”) bir URL oluşturdu.
Not : Konuyu daha rahat örneklemek için projeye View – Controller ve Model eklemeleri yapıyorum. Routing kapsamından çok fazla uzaklaşmamak için bu değişiklikleri burada anlatmadım.
Route Ekleme
Yeni Route eklemeden önce projemizdeki Article view URL’i görelim.
Yeni sayfa üzerine yönlendirme işleminde standart dışına çıkıp kullanıcı dostu
(User-Friendly) bir URL göstermek istiyorsak RouteConfig sınıfımızı aşağıdaki gibi değiştiriyoruz. Burada dikkat etmemiz gereken ilk şey default mapRoute tanımının her zaman en altta olmasıdır.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
using System.Web.Mvc; using System.Web.Routing; namespace bilisimIOMVCRouting { public class RouteConfig { public static void RegisterRoutes(RouteCollection routes) { routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); routes.MapRoute( name: "Articles", url: "Makale/bilsimIO-Makaleler", defaults: new { controller = "Article", action = "Articles" } ); routes.MapRoute( name: "Default", url: "{controller}/{action}/{id}", defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } ); } } } |
Parametreli Route Tanımı
Parametreli Route tanımına geçmeden önce ArticleController ‘a yeni bir View ve Controller metodu eklemeliyiz. Bu Action ile beklediğimiz gönderdiğimiz parametreye göre .Net kategori makalelerinin ekranda görünmesi.
Yukarıda göründüğü gibi .Net makaleleri ekranda görüntülendi fakat adres çubuğunda metot adımız parametre adı parametre değeri gibi tüm değerler dışarıya açılmış oldu. şimdi yeni bir Route ekleyelim.
1 2 3 4 5 6 7 8 9 |
routes.MapRoute( name: "GetArticlesByCategory", url: "Makale/bilsimIO-Makaleler/{categoryId}", defaults: new { controller = "Article", action = "GetArticlesByCategory", categoryId= "" } ); |
Action Method
1 2 3 4 5 6 7 8 9 |
public ActionResult GetArticlesByCategory(int categoryId) { var articlesByCategories = _articles.Where(p => p.ArticleCategoryId.Equals(categoryId)); return View(articlesByCategories); } |
Route Filter – RouteConstraint Filter
Routing yaparken bazı senaryolarda çeşitli kısıtlamalar kullanmamız gerekebilir. Örneğin GetArticlesByCategory ile listelediğimiz kategoriler için bir parametre kullanmıştık. Ardes çubugunda parametremizi 1 ,2 ,3 şeklinde Int değerlerden oluşturduk. Fakat bununla ilgili bir kısıtlama yapmadık. Adres çubuğundaki parametreye /bilisimIO ‘ da yazabiliriz. Bu istenmeyen durumu engellemek için regex’den faydalanacağız. Dikkat ettiyseniz şu ana kadar istek yaptığımız her sayfa için bir ActionResult metot tanımlamıştık.Yani her ActionResult ‘ın bir View cshtml dosyası vardı. Şimdi tanımlayacağımız metot için ayrı bir View sayfası olmayacak. ActionResult’ı GetArticleByCategory sayfasına yönlendireceğiz.
1 2 3 4 5 6 7 8 9 10 |
routes.MapRoute( name: "GetArticleByCategoryPosted", url: "Makale/bilsimIO-Makaleler-Posted/{categoryId}", defaults: new { controller = "Article", action = "GetArticleByCategoryPosted", categoryId = "" } , constraints: new { categoryId = @"^[0-9]*$" } ); |
ActionResult
1 2 3 4 5 6 7 8 9 |
public ActionResult GetArticleByCategoryPosted(int categoryId) { var articlesByCategories = _articles.Where(p => p.ArticleCategoryId.Equals(categoryId)); return View("GetArticlesByCategory", articlesByCategories); } |
GetArcitleByCategoryPosted metodu ile GetArticleByCategory.cshtml içine istediğimiz veriyi gönderdik.
HttpPost HttpGet Filter
HttpPost ve HttpGet attribute’leri metotlar için kullanılır. Gelen isteğin Post veya Get durumuna göre filtre uygulamış olur.
ActionResult
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
[HttpPost] public ActionResult SaveArticle() { ..... } routes.MapRoute( name: "Name", url: "Makale/Ekle", defaults: new { controller = "Article", action = "SaveArticle"} , constraints: new { method = new HttpMethodConstraint("POST") } ); |
H.Burak Karadağ
Referans
msdn Routing