SelamünAleyküm, geçtiğimiz yazıda Route giriş yapmıştık ve Varsayılan Route, Custom Route ve Route Data konularını incelemiştik, bu yazımızda ise Route Data Kısıtlamaları'ndan devam edeceğiz ve devamında Custom Constraint, Attribute Routing, Regex Kullanarak Route Oluşturma ve RouteUrl İle Sayfaların Url'lerini Alma konularını inceleyeceğiz.
Url'den aldığımız parametrelerekısıtlamaları ekleyip bu kısıtlamaların dışında bir değer gönderimi yapılırsa; isterseniz, yazdığınız Route yapısına girmeyip geriye 404 durum kodunun dönmesini sağlayabilirsiniz.
Misalen; İlk örneğimizde yapacağımız kısıtlamayı inline olarak Url'mize ekleyelim.
cityId parametresini int tipinde göndermesini isteyelim. int tipinden farklı olarak bir değer gönderilirse 404 durum kodunu dönecektir.
app.MapControllerRoute(
name: "havadurumu",
pattern: "hava-durumu/{cityId:int}",
defaults: new { controller = "Weather", action = "Index" });
uygulamamıza https:localhost:44327/hava-durumu/Sivas gibi bir url Url ile istekte bulunduğumuzda cityId'ye karşılık gelen değer int tipinde olmadığından dolayı 404 durum kodunu dönecektir. Bu kısıtlamaları kodumuzda inline olarak yazdık. Kısıtlamaları inline olarak değil de constraints ile ayrı bir nesne olarak da Route'mize dâhil edebiliriz.
Misalen; önceki örnekte olduğu gibi cityId parametresine int değer kısıtlaması yapalım.
app.MapControllerRoute(
name: "havadurumu",
pattern: "hava-durumu/{cityId?}",
defaults: new { controller = "Weather", action = "Index" },
constraints: new { cityId = new IntRouteConstraint() });
Bu şekilde uygulamayı çalıştırdığımızda WeatherController altındaki Index metoduna gidebilmemiz için cityId parametresini hiç göndermemeniz (Bu durumda null değerini alır.) ya da cityId parametresini int tipinde bir değer göndermeniz gerekmektedir.
Şimdi bir örnek daha yapalım. Misalen, cityId parametremiz max.81 değerini alsın ve aldığı değer int tipinde bir değer olacak şekilde Route tanımlamasını yapalım.
app.MapControllerRoute(
name: "havadurumu",
pattern: "hava-durumu/{cityId?}",
defaults: new { controller = "Weather", action = "Index" },
constraints: new {
cityId = new CompositeRouteConstraint(
new IRouteConstraint[]
{
new IntRouteConstraint();
new MaxRouteConstraint(81)
});
});
Kısıtlamalarımıza hem int değerini hem de maksimum 81 değerini alacak şekilde eklemiş olduk. cityId parametresine bunun dışında bir değer gönderilirse 404 durum kodunu dönecektir.
Uygulamamıza CustomConstraint'ler tanımlayabiliriz. Bu şekilde kendimize özel kısıtlama kodları yazabiliriz.
Misalen; Bir önceki örneği şimdi IRouteConstraint'ten türeyen CustomConstraint sınıfıyla yapmayı deneyelim.
CustomConstraint isminde bir sınıf oluşturalım ve bu sınıf IRouteConstraint'ten türesin.
public class CustomConstraint : IRouteConstraint
{
private static IEnumerable<int> cityIds = Enumerable.Range(1, 81);
public bool Match(HttpContext httpContext, IRouter route, string routeKey,
RouteValueDictionary values, RouteDirection routeDirection)
{
return cityIds.Contains(Convert.ToInt32(values[routeKey]));
}
}
cityIds değişkenine 1'den 81'e kadar değerler atadık. Match metodunda da values[routeKey] ile bu değerler arasında Url'den gelen değer var mı diye bakmasını sağladık. Geriye bool değer döndürdük. Eğer sonuç True olacaksa uyuşan Controller ile Action metoduna düşüp sayfayı getirecektir Ama geriye dönen değer False olursa 404 durum kodunu dönecektir.
Route yapımızda Constarint'te oluşturduğumuz CustomConstraint'i kullanalım.
app.MapControllerRoute(
name: "havadurumu",
pattern: "hava-durumu/{cityId?}",
defaults: new { controller = "Weather", action = "Index" },
constraints: new {
cityId = new CustomConstraint()
});
Önceki örnekte olduğu gibi cityId'si 1'den 81'e kadar olan Route değerlerinde WeatherController altındaki Index Action metoudumuz çalışacaktır.
Oluşturduğumuz CustomConstraint sınıfını inline olarak da kullanmamız mümkündür.
Misalen; Startup sınıfımızın altına, ConfigureServices metoduna oluşturduğumuz CustomConstraint sınıfını tanıtırız. Bu sınıfa Route yapılarında kullanmamız için bir isim veririz.
public void ConfigureServices(IServiceCollection services)
{
services.Configure<RouteOptions>(options => options. ConstraintMap.Add("cityidconstraint",
typeof(CustomConstraint)));
services.AddMvc();
}
Route yapımıza da ConfigureServices metoduna eklediğimiz "cityidconstarint" isimli kısıtlamayı inline olarak ekleriz.
app.MapControllerRoute(
name: "havadurumu",
pattern: "hava-durumu/{cityId:cityidconstraint?}",
defaults: new { controller = "Weather", action = "Index" });
Uygulamayı çalıştırdığımızda bir önceki örnek ile aynı sonuçları verecektir.
Controller'imizde veya Action metotlarımızda Routelerimizi Attribute olarak tanımlayabiliriz. Yukarıda gösterdiğimiz Route tanımlamalarında yaptığımız işlemleri aynı şeklide Attribute Route ile yapabiliriz.
Misalen, Startup sınıfındaki Configure metodunun altında varsayılan Route'mizi tanımlayalım.
public void Configure(IApplicationBuilder app)
{
//Bir hata durumunda ekrana hatayı göstermesi için yazılmış Middleware
app.UseDeveloperExceptionPage();
#region route
app.MapDefaultControllerRoute();
#endregion
}
CategoryController ve GalleryController isimli iki Controller'imiz olsun.
CategoryController'in içinde CategoryList ve Index adında iki Action metodumuz olsun. Önceki örneklerde olduğu gibi Controller ismini ve Action ismini Json olarak döndürsün.
GalleryController'in altında Index metodu olsun. Bu Index metodu, categoryId isminde bin int parametresi alsın. Aynı şekilde Controller ile Action ismini Json olarak sayfaya geri döndürsün.
CategoryController'in üstüne, CategoryController'e ait özel Route'mizi Attribute olarak yazalım.
[Route("kategori/{action}")]
public class CategoryController : Controller
{
public IActionResult Index()
{
return Json(new { ControllerName = "Category", ActionName = "Index" });
}
public IActionResult CategoryList()
{
return Json(new { ControllerName = "Category", ActionName = "CategoryList" });
}
}
GalleryController'in Index metodunun üstüne özel Route'mizi Attribute olarak yazalım.
[Route("galeri/{categoryId:int?}")]
public IActionResult Index(int? categoryId)
{
return Json(new { ControllerName = "Gallery", ActionName = "Index", RouteParameter =
new List<string>() { categoryId?.ToString() }});
}
Uygulamamızı çalıştıralım.
https:localhost:44327/kategori/index Url'si üzerinden istekte bulunalım.
{
controllerName: "Category",
actionName: "Index"
}
https:localhost:44327/kategori/categorylist Url'si üzerinden istekte bulunalım.
{
controllerName: "Category",
actionName: "CategoryList"
}
https:localhost:44327/galeri/365 Url'si üzerinden istekte bulunalım.
{
controllerName: "Gallery",
actionName: "Index",
- routeParameter: [
"365"
]
}
Route'lerimizde Regex kodlarını kullanabiliriz. Eğer Route yapısında Regex varsa yapılan istek bu Regex koduna uyduğunda Route yapısandaki sayfaya düşecektir.
Misalen, MailController isimli bir Controller'imiz olsun ve bu Controller'in Index isminde bir Action metodu olsun. Index metodu e-mail parametresi alsın. Önceki örneklerimizde olduğu gibi ekrana Json formatında aktif olan Controller'i, aktif olan Index metodunu ve Url'den aldığı veriyi ekrana yazalım.
public IActionResult Index(string email)
{
return Json(new { ControllerName = "Mail", ActionName = "Index",
RouteParameter = new List<string>() { email } });
}
Route'mizde de Url'den alacağımız email parametresine kısıtlama eklemesi yapalım. Bu kısıtlama ile gelen veri e-posta formatına uygun mu diye bakalım. Bu işlemi Regex kodları kullanarak yapalım.
app.MapControllerRoute(
name: "email",
pattern: "mail/{email}",
defaults: new { controller = "Mail", action = "Index" },
constraints: new {
email = new RegexRouteConstraint(@"^([\w\.\-]+)@([\w\-]+)((\.(\w){2,3})+)$")
});
email değişkenine, gelen istekteki ilgili bölüm, e-posta standartlarına uyuyor mu diye Regex kodlarıyla kısıtlama ekledik.
https:localhost:44327/mail/deneme@outlook.com adresi üzerinden istekte bulunalım.
{
controllerName = "Mail",
actionName = "Index",
- routeParameter: [
"deneme@outlook.com"
]
}
Görüldüğü üzere Url'den aldığı e-posta verisini ekrana yazdık. Eğer e-posta standartlarına uymayan bir istekte bulunsaydık ilgili Route çalışmayacaktı ve bize 404 durum kodunu dönerek uygulamamıza böyle bir sayfanın bulunmadığını söyleyecekti.
Yazdığımız Route'ler yardımıyla istediğimiz sayfaların Url'lerini alabiliriz. Url.RouteUrl() ifadesi ile Url'isin almak istediğimiz sayfanın Route Name'sini parametre olarak verebiliriz. Route Name'sini parametre olarak verdikten sonra kullanıcıdan aldığımız değerleri yazabiliriz. Bu sayede sayfalarımızda linkler oluşturup tıklandığında bu linklere gitmesini sağlayabiliriz.
Misalen; Customers, Customer ve Default isimli Route'lerimiz olsun ve bu Route'leri Startup sınıfı içerisindeki Configure metoduna yazalım.
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "Customers",
template: "musteriler",
pattern: new { controller = "Customer", action = "List" });
endpoints.MapControllerRoute(
name: "Customer",
template: "musteri/{id}",
pattern: new { controller = "Customer", action = "Get" });
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}\{id?}");
});
Customer isimli Controller oluşturalım ve içine Index, Get, List ve CustomerOrder isimli Action metotları oluşturalım.
public IActionResult Index()
{
retrun View();
}
public IActionResult List()
{
retrun View();
}
public IActionResult Get(int id)
{
retrun View();
}
public IActionResult CustomerOrder(int id)
{
retrun View();
}
Şimdi ise CustomerController altındaki Index View'ini oluşturalım ve bu View'de <a> etiketleri içerisinde oluşturduğumuz Route isimlerine göre bazı Url'leri ekrana yazmasını sağlayan korları yazalım.
@{
Layout = null;
}
<a href="@Url.RoutUrl("Default", new { Controller = "Home",
Action = "Index" })">@Url.RoutUrl("Default", new { Controller = "Home", Action = "Index" })</a>
<br />
<a href="@Url.RoutUrl("Default")">@Url.RoutUrl("Default")</a>
<br />
<a href="@Url.RoutUrl("Customers")">@Url.RoutUrl("Customers")</a>
<br />
<a href="@Url.RoutUrl("Customer", new { id = 5 })">@Url.RoutUrl("Default", new { id = 5 })</a>
<br />
<a href="@Url.RoutUrl("Default", new { Controller = "Customer",
Action = "CustomerOrder", id = 7 })">@Url.RoutUrl("Default", new { Controller = "Customer",
Action = "CustomerOrder", id = 7 })</a>
Uygulamamızı F5 tuşuyla çalıştıralım ve /Customer Url'si üzerinden CustomerController altındaki Index sayfasına gidelim.
foto ekle
@Url.RouteUrl("Default", new { Controller = "Home", Aciton = "Index" }) → Default olarak isimlendirilen Route'ye gider. Controller ismini Home, Action ismini Index olarak verdiğimizden dolayı Anasayfa Url'sini bize verir.
@Url.RouteUrl("Default") → Default olarak isimlendirilen Route'ye gider. CustomerController altındaki Index altındaki Index sayfasında olduğumuzdan ve Controller, Action ismi vermediğimizden dolayı bulunduğumuz sayfanın Url'sini bize verir.
@Url.RouteUrl("Customers") → Customers isimli Route'ye gider.
@Url.RouteUrl("Customer", new { id = 5 }) → Customer isimli Route'ye gider. Id'ye 5 değerini verdiğimizden Route'de kullanıcıdan istediğimiz Id değeri yerine 5 ifadesini yazar.
@Url.RouteUrl("Default", new { Controller = "Customer", Action = "CustomerOrder", id = 7 }) → Default isimli Route'ye gider. Contorller, Action isimlerini ve Id parametresini yerine yazıp bize Controller, Action ve Id'den oluşan bir Url verir.
Bu yazımızın sonuna geldik, bu yazıda Routing yapılanması hakkında detaylı incelemelerde bulunduk. İlgilenenlerin faydalanması ümidiyle. Bu yazıya ilişkin projenin kodları geçtiğimiz yazıda bıraktığım github deposundan bulabilirsiniz.
Blog Listesi