3. Denetleyiciler, Eylemler, Yönlendirme
Bir ASP.NET MVC uygulamasının mimarisini ele alalım:
![]() |
Bu bölümde, [1] isteğinin, onu işleyecek denetleyiciye ve eyleme ([2a]) ulaşmasını sağlayan süreci inceleyeceğiz; bu mekanizmaya yönlendirme denir. Ayrıca, bir eylemin tarayıcıya verebileceği çeşitli yanıtları ([3]) da ele alacağız. Bu yanıtlar, bir V görünümü ([4b]) dışında başka şeyler de olabilir.
3.1. Bir projenin yapısı ASP.NET MVC
Visual Studio Express 2012 ile ilk ASP.NET MVC projemizi oluşturalım. Bunu, önceki bölümde kullanılan çözüme [1] ekleyeceğiz:
![]() |
![]() |
- [2] olarak yeni projenin adını belirleyeceğiz;
- [3, 4] olarak, temel bir proje olan ASP.NET MVC'i seçiyoruz. Bu şablon bize, çalışmak için gerekli tüm kaynakları (DLL, javascript kütüphaneleri, ...) içeren boş bir web uygulaması sağlar.
Ortaya çıkan proje [5] olarak gösterilmektedir. Bunu, çözümün başlangıç projesi olarak [6] adresine taşıyacağız:
![]() |
[5] dosyasında aşağıdaki hususlara dikkat edilmelidir:
- Projenin mimarisi, MVC modelini yansıtmaktadır:
- C denetleyicileri [Controllers] klasörüne yerleştirilecektir,
- M veri modelleri [Models] klasörüne yerleştirilecektir,
- V görünümleri [Views] klasörüne yerleştirilecektir,
![]() |
- [1] klasöründe, [Site.css] dosyası uygulamanın varsayılan dosyası olarak CSS olacaktır;
- [2]'te ise bir dizi JavaScript kütüphanesi kullanıma sunulur;
- [3] dosyasında üç özel görünüm bulunur: _ViewStart, _Layout ve Error.
[_ViewStart] dosyası şu şekildedir:
@{
Layout = "~/Views/Shared/_Layout.cshtml";
}
- 1. satır: @ karakteri, görünümde bir C# dizisini belirtir. Nitekim, bir görünüme C# kodu eklenebilir;
- 2. satır: Tüm görünümlerin üst görünümünü tanımlayan Layout değişkenini tanımlar. Bu, klasik ASP.NET çerçevesinin ana sayfasına karşılık gelir.
'daki [_Layout] dosyası şu şekildedir:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<title>@ViewBag.Title</title>
@Styles.Render("~/Content/css")
@Scripts.Render("~/bundles/modernizr")
</head>
<body>
@RenderBody()
@Scripts.Render("~/bundles/jquery")
@RenderSection("scripts", required: false)
</body>
</html>
[Views] klasöründeki bir görünüm görüntülenirken, gövdesi yukarıdaki 11. satır tarafından oluşturulur. Bu, görünümün <html>, <head>, <body> etiketlerini içermesi gerekmediği anlamına gelir. Bunlar yukarıdaki dosya tarafından sağlanır. Bu dosya şimdilik oldukça karmaşıktır. Basitleştirelim:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<title>Tutoriel ASP.NET MVC</title>
</head>
<body>
<h2>Tutoriel ASP.NET MVC</h2>
@RenderBody()
</body>
</html>
- 6. satır: tüm görünümlerde ortak olan başlık;
- 9. satır: tüm görünümlerde ortak olan üstbilgi;
- 10. satır: görüntülenen görünüme özgü içerik.
![]() |
- [Web.config], web uygulamasının yapılandırma dosyasıdır. Bu dosya karmaşıktır. Çok katmanlı bir mimaride [Spring.net] çerçevesini kullanırken bu dosyayı değiştirmek gerekecektir.
- [Global.asax], uygulamanın başlatılması sırasında yürütülen kodu içerir. Genellikle bu kod, [Web.config] dahil olmak üzere uygulamanın çeşitli yapılandırma dosyalarını kullanır.
3.2. URL'in varsayılan yönlendirmesi
[Global.asax] kodunun şu anki hali şöyledir:
using System.Web.Http;
using System.Web.Mvc;
using System.Web.Optimization;
using System.Web.Routing;
namespace Exemple_01
{
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
...
}
}
}
- 6. satır, sınıfın namespace'i. Bu, doğrudan proje adından gelir ve proje özelliklerinde bulunur:

![]() |
[1]'i varsayılan ad alanı olarak belirleriz. Böylece, projede oluşturulacak tüm sınıflar için varsayılan olarak kullanılır.
[Global.asax] koduna geri dönelim:
using System.Web.Http;
using System.Web.Mvc;
using System.Web.Optimization;
using System.Web.Routing;
namespace Exemple_01
{
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
...
}
}
}
- 9. satır: [MvcApplication] sınıfı, [HttpApplication] sınıfından türetilmiştir. [MvcApplication] adı değiştirilebilir;
- 11. satır: [Application_Start] yöntemi, web uygulamasının başlatılması sırasında yürütülen yöntemdir. Yalnızca bir kez yürütülür. Uygulamanın başlatılması bu yöntemde gerçekleştirilir.
[Application_Start] kodunun şu anki hali şöyledir:
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
WebApiConfig.Register(GlobalConfiguration.Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
Şu an için bu kodun tamamını anlamamıza gerek yok. 5-8. satırlar, web uygulaması tarafından kabul edilen rotaları tanımlar. ASP.NET MVC uygulamasının mimarisine geri dönelim:
![]() |
[Front Controller]'in bir URL'i onu işlemekle görevli eyleme yönlendirmesi gerektiğini açıklamıştık. Bir rota, bir URL şablonu ile bir eylem arasında bağlantı kurmak için kullanılır. Bu rotalar, projenin [App_Start] klasöründe [WebApiConfig, FilterConfig, RouteConfig, BundleConfig] sınıfları tarafından tanımlanır:
![]() |
Şu an için sadece [RouteConfig] sınıfı bizi ilgilendiriyor:
using System.Web.Mvc;
using System.Web.Routing;
namespace Exemple_01
{
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 }
);
}
}
}
12-16. satırlar, uygulama tarafından kabul edilen URL formatını tanımlar. Buna rota denir. Birden fazla olası rota olabilir (= birden fazla olası URL şablonu). Bunlar, adlarına göre birbirinden ayrılır (13. satır). Rotadaki URL'lerin biçimi 14. satırda tanımlanmıştır. Burada, URL üç bileşene sahip olacaktır:
- {controller}: [Controller]'ten türetilmiş bir sınıfın adı. Bu sınıf, projenin [Controllers] klasöründe aranacaktır. Geleneksel olarak, URL /X/Y/Z ise, bu URL'i işlemekle görevli denetleyici XController sınıfı olacaktır. URL içinde bulunan denetleyicinin adına Controller son eki eklenir;
- {action}: yukarıda belirtilen denetleyicideki bir yöntemin adıdır. URL ile birlikte gelen parametreleri alacak ve işleyecek olan bu yöntemdir. Bu yöntem çeşitli sonuçlar verebilir:
- void: eylem, istemci tarayıcısına gönderilecek yanıtı kendisi oluşturur
- String: eylem, müşteriye bir karakter dizisi döndürür;
- ViewResult: müşteriye bir görünüm döndürür;
- PartialViewResult: Kısmi bir görünüm gönderir;
- EmptyResult: müşteriye boş bir yanıt gönderilir;
- RedirectResult: istemciden URL'e yönlendirilmesini ister
- RedirectToRouteResult: aynı, ancak URL, uygulamanın rotalarından oluşturulur;
- JsonResult: JSON yanıtını gönderir
- JavaScriptResult: İstemciye bir JavaScript kodu gönderir;
- ContentResult: bir HTML akışını, bir görünümden geçmeden istemciye geri gönderir;
- FileContentResult: müşteriye bir dosya gönderir;
- FileStreamResult: aynı işlem, ancak farklı bir yolla;
- FilePathResult: ...
- {id}: eyleme iletilecek bir parametre. Bunun için eylemin id adlı bir parametreye sahip olması gerekir.
15. satır, URL'in beklenen /{controller}/{action}/{id} biçiminde olmadığı durumlarda varsayılan değerleri tanımlar. Ayrıca, URL'teki {id} parametresinin isteğe bağlı olduğunu da belirtir. Aşağıda eksik URL örnekleri ve varsayılan değerlerle tamamlanmış URL örneği yer almaktadır:
Orijinal URL | Doldurulmuş URL |
/ | /Ana Sayfa/Dizin |
/Do | /Do/Index |
/Do/Something | /Yap/Bir Şey |
/Yap/Bir Şey/4 | /Yap/Bir Şey/4 |
/Bir Şey Yap/x/y/z | URL yönlendirilmemiş |
3.3. Bir denetleyici ve ilk eylem oluşturma
İlk denetleyiciyi oluşturalım:
![]() |
![]() |
- [1]'te denetleyicinin adını [Controller] sonekiyle birlikte girin;
- [2]'te, MVC adlı boş bir denetleyici oluşturun;
- [3]'te, denetleyici oluşturulmuştur.
[FirstController] kodunun içeriği şöyledir:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace Exemple_01.Controllers
{
public class FirstController : Controller
{
//
// GET: /First/
public ActionResult Index()
{
return View();
}
}
}
- 7. satır: Varsayılan bir namespace oluşturulmuştur;
- 9. satır: [FirstController] sınıfı, [System.Web.Mvc.Controller] sınıfından türetilmiştir;
- 14-17. satırlar: Varsayılan olarak bir [Index] eylemi oluşturulmuştur. Bu eylem herkese açıktır. Bu önemlidir, aksi takdirde eylem bulunamaz. Bu eylem, bir eylemin genellikle döndürdüğü sonuçların çoğunun türetildiği soyut bir sınıf olan [ActionResult] türünü döndürür. Bu, döndürülen türün gerçek adıyla değiştirilerek belirtilebilen bir "genel amaçlı" türdür;
- 16. satır: Yöntem hiçbir işlem yapmaz. Sadece bir görünüm döndürür, yani [ViewResult] türünü. Görünümün adı belirtilmemiştir. Bu durumda, çerçeve [Views / First] klasöründe eylemin adını taşıyan bir görünüm arar; yani burada: [Index.cshtml].
[Index.cshtml] görünümünü oluşturalım:
![]() |
- [1]'te, eylem koduna sağ tıklayıp [Ajouter une vue] seçeneğini seçin;
- [2]'te, sihirbaz eylemin adını taşıyan bir görünüm önerir. Burada istediğimiz budur;
- [3]'te, varsayılan olarak [_Layout.cshtml] ana sayfasının kullanılması önerilir;
- [4]'te, onaylandıktan sonra sihirbaz, [Views] klasörünün içinde denetleyicinin adını (First) taşıyan bir alt klasörde görünümü oluşturur.
[Index] görünümü için oluşturulan kod şöyledir:
@{
ViewBag.Title = "Index";
}
<h2>Index</h2>
- 1-3. satırlar: bir değişkeni tanımlayan C# kodu;
- 5. satır: bir HTML etiketi.
Yukarıdaki kodun tamamı şu kodla değiştirilir:
<strong>Vue [Index]...</strong>
Özetleyelim:
- [First] adlı bir C denetleyicimiz var;
- [Index] adlı bir eylemimiz var ve bu eylem, [Index] adlı bir görünümün görüntülenmesini istiyor;
- V [Index] adlı bir görünümümüz var.
[Index] adlı eylemi iki şekilde çağırabiliriz:
- /First/Index;
- /First, çünkü [Index] aynı zamanda rotalardaki varsayılan eylemdir.
Uygulamayı (CTRL-F5) çalıştıralım. Aşağıdaki sayfayı elde ederiz:
1

[1]'te, istenen URL, http://localhost:49302 idi. Yol yok. Yönlendiricimizin /{controller}/{action}/{id} biçiminde URL beklediği biliniyor. Bu öğeler bulunmadığından varsayılan değerler kullanılır. URL, http://localhost:49302/Home/Index olur. [Home] denetleyicisi mevcut değildir. Dolayısıyla URL reddedilir.
Şimdi URL http://localhost:49302/First/Index adresini tarayıcıya doğrudan yazarak deneyelim:
![]() |
Yukarıdaki sayfa, [First] denetleyicisinin [Index] eylemi tarafından oluşturulmuştur. Bu eylem tarafından oluşturulan sayfa, kodu aşağıdaki gibi olan [Index] görünümüdür:
<strong>Vue [Index]...</strong>
Bu eylem, [1] bölümünü oluşturur. [2] bölümü ise, biraz önce tanımladığımız [_Layout] ana sayfasından gelmektedir:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<title>Tutoriel ASP.NET MVC</title>
</head>
<body>
<h2>Tutoriel ASP.NET MVC</h2>
@RenderBody()
</body>
</html>
- satır, sayfanın [2] bölümünü oluşturmuştur. [Index] görünümü ise ancak 10. satırda devreye girer.
Alınan sayfanın kaynak kodunu görüntülediğimizde, [Index] sayfasının [Layout] sayfasına dahil edildiğini (aşağıdaki 10. satır) görebiliriz:
Şimdi de URL ve [/First]'i deneyelim:
![]() |
URL ve [/First] eksikti. Bu kodlar, rota için varsayılan değerlerle tamamlandı ve [/First/Index] haline geldi. Böylece, önceki ile aynı sonucu elde ediyoruz.
3.4. [ContentResult] - 1 türünde bir sonuca sahip eylem
[First] denetleyicisinde yeni bir eylem oluşturalım:
using System.Text;
using System.Web.Mvc;
namespace Exemple_01.Controllers
{
public class FirstController : Controller
{
// Index
public ViewResult Index()
{
return View();
}
// Eylem01
public ContentResult Action01()
{
return Content("<h1>Action [Action01]</h1>", "text/plain", Encoding.UTF8);
}
}
}
Yeni eylem 14-18. satırlarda tanımlanmıştır. Bu eylem, [Controller] sınıfının (6. satır) [Content] yöntemini (16. satır) kullanarak bir karakter dizisi döndürmekten ibarettir. Yöntemin parametreleri şunlardır:
- yanıtın karakter dizesi;
- gönderilen metnin türünü belirten bir gösterge: "text/plain", "text/html", "text/xml", ... Bu göstergeye MIME türü (http://fr.wikipedia.org/wiki/Type_MIME) denir;
- üçüncü parametre, metin için kullanılan kodlama türünü belirtmeye yarar.
Soyut [ActionResult] türünü kullanmak yerine, yöntemlerimiz gerçek olarak döndürülen türü belirtir (9. ve 14. satırlar).
URL [/First/Action01]'i isteyelim. Aşağıdaki sayfa elde edilir:
![]() |
Alınan sayfanın kaynak koduna bakalım:
Tarayıcı, eylem tarafından gönderilen metni aldı, başka hiçbir şey almadı. Bu mod, HTML biçimlendirmesi olmadan web sunucusundan saf veriler istemek istediğimizde kullanışlıdır. Yukarıda, tarayıcının HTML <h1> etiketini yorumlamadığına dikkat edelim. Nedenini anlamak için Chrome'da HTTP iletişimlerini inceleyelim:
Tarayıcı şu başlıkları gönderdi:
Sunucu, tarayıcıya aşağıdaki başlıklarla yanıt verdi:
- 3. satır: belgenin türünü belirler. Burada, [Action01] yönteminde ayarlanan öznitelikleri görüyoruz. Tarayıcıya belgenin türünün "text/html" değil "text/plain" olduğu söylendiği için, alınan belgedeki <h1> etiketini yorumlamadı.
3.5. [ContentResult] - 2 türünde bir sonuca sahip eylem
Şu üçüncü eylemi ele alalım:
using System.Text;
using System.Web.Mvc;
namespace Exemple_01.Controllers
{
public class FirstController : Controller
{
...
// Eylem02
public ContentResult Action02()
{
string data = "<action><name>Action02</name><description>renvoie un texte XML</description></action>";
return Content(data, "text/xml", Encoding.UTF8);
}
}
}
- 12. satır: XML metni tanımlanır;
- 13. satır: metni, türü MIME "text/xml" olan XML olarak belirtilerek tarayıcıya gönderilir.
Tarayıcıda şu sayfa görüntülenir:
![]() |
Chrome'da sunucudan gelen HTTP yanıtına bakalım:
- 3. satır: belgenin türünü belirler. Burada, [Action02] yönteminde ayarlanan öznitelikler bulunur;
- 12. satır: sunucu tarafından gönderilen belgenin bayt cinsinden boyutu.
Sunucu tarafından gönderilen belge şudur (Chrome'dan kopyalanmıştır):
![]() |
3.6. [JsonResult] türünde bir sonuca sahip eylem
[First] denetleyicisine aşağıdaki eylemi ekleyelim:
// Eylem03
public JsonResult Action03()
{
dynamic personne = new ExpandoObject();
personne.nom = "someone";
personne.age = 20;
return Json(personne,JsonRequestBehavior.AllowGet);
}
- 4. satır: dynamic türünde bir değişken. Çalışma sırasında, bu tür bir değişkene istediğimiz gibi özellikler ekleyebiliriz. Özellik, başlatıldığı anda oluşturulur;
- 5-6. satırlar: nom ve age adlı iki özellik başlatılır;
- 7. satır: Nesnenin JSON (JavaScript Nesne Notasyonu) temsilini döndürür. JSON, bir nesneyi karakter dizisine serileştirmeye ve tersine bir karakter dizisini nesneye deserileştirmeye olanak tanır. Bu, XML serileştirme/deserileştirme işleminin bir alternatifidir;
- 2. satır: İşlem, [JsonResult] türünde bir değer döndürür. Bu tür, yalnızca bir POST isteği için döndürülebilir. Bunu bir GET yöntemi için döndürmek istersek, Json sınıfının oluşturucusunun ikinci parametresine (7. satır) JsonRequestBehavior.AllowGet değerini vermeliyiz.
URL [/First/Action03] istendiğinde, tarayıcı şunu görüntüler:
![]() |
Sunucudan gelen HTTP yanıtı ise şöyledir:
- 3. satır: gönderilen belgenin JSON olduğunu belirtir;
- 10. satır: Gönderilen belgenin boyutu 58 bayttır. Şu şekildedir:
[personne] dinamik öğesi, JSON tarafından her bir sözlüğün:
- [personne] değişkenindeki bir alana karşılık gelir;
- "Key" ve "Value" adlı iki anahtara sahiptir. "Key" anahtarının ilişkili değeri alanın adıdır ve "Value" anahtarının değeri ise alanın değeridir.
3.7. [string] türünde bir sonuca sahip eylem
[First] denetleyicisine aşağıdaki eylemi ekleyelim:
// Eylem04
public string Action04()
{
return "<h3>Contrôleur=First, Action=Action04</h3>";
}
Chrome ile URL [/First/Action04] adresini çağırdığımızda, şu yanıtı alırız:
![]() |
<h3> etiketinin yorumlandığını görüyoruz. Sunucudan gelen HTTP yanıtına bakalım:
ve şu belgeyi inceleyelim:
- satırda, sunucunun HTML biçiminde metin gönderdiğini belirttiği görülüyor. Bu nedenle tarayıcı, <h3> etiketini yorumlamıştır. Dolayısıyla, düz metin göndermek istediğimizde, [string] yerine [ContentResult] formatını kullanmak daha uygundur. [ContentResult], "text/plain" türünü belirtmemize olanak tanır; böylece biçimlendirilmemiş, dolayısıyla tarayıcı tarafından yorumlanmayacak metin gönderildiğini gösterir.
3.8. [EmptyResult] türünde bir sonuca sahip eylem
Şu yeni eylem ele alınalım:
// Eylem05
public EmptyResult Action05()
{
return new EmptyResult();
}
Eylem, yalnızca [EmptyResult] türünü döndürür. Bu durumda, sunucu, HTTP yanıtında gösterildiği gibi istemciye boş bir yanıt gönderir:
- 9. satır: Sunucu, istemcisine boş bir belge gönderdiğini bildirir.
3.9. [RedirectResult] - 1 türünde bir sonuca sahip eylem
Şu yeni eylem ele alınsın:
// Eylem06
public RedirectResult Action06()
{
return new RedirectResult("/First/Action05");
}
Eylem, [RedirectResult] türünde bir sonuç döndürür. Bu tür, müşteriye, oluşturucunun URL parametresine (satır 4) yönlendirme emri gönderilmesini sağlar. Müşteri daha sonra GET adresine [/First/Action05] adresine yönelik yeni bir istek gönderir. Böylece müşteri toplamda iki istek göndermiş olur.
Tarayıcı, ikinci isteğin sonucunu görüntüler:
![]() |
Chrome'da sunucudan gelen HTTP yanıtını inceleyelim:
![]() |
Yukarıda tarayıcının iki isteğini görüyoruz. İlk istek olan [Action06]'i inceleyelim. Sunucudan gelen HTTP yanıtı şöyledir:
- 1. satır: Sunucu, 302 Found koduyla yanıt verdi. Şu ana kadar 200 OK koduydu; bu, istenen belgenin bulunduğunu ifade ediyordu. 302 kodu, bir yönlendirmenin istendiğini gösterir. Yönlendirme adresi 4. satırda verilmiştir. Burada, eylem kodunda verdiğimiz yönlendirme adresini görüyoruz;
- 11. satır: Sunucu, HTTP yanıtıyla, 132 baytlık (11. satır) bir text/html türü (3. satır) belge gönderdiğini belirtir. Chrome'da [Action06] isteğine verilen yanıt incelendiğinde, beklendiği gibi boştur. Muhtemelen bunun bir açıklaması vardır, ancak ben bilmiyorum.
Yönlendirme nedeniyle, tarayıcı, aşağıdaki Chrome ekranının 1. satırında da görülebileceği gibi, yukarıdaki 4. satırda belirtilen URL adresine GET adlı yeni bir istek gönderir:
3.10. [RedirectResult] - 2 türünde bir sonuç veren eylem
Şu yeni eylem:
// Eylem07
public RedirectResult Action07()
{
return new RedirectResult("/First/Action05",true);
}
- satırda, [RedirectResult] türündeki oluşturucuya ikinci bir parametre eklendi. Bu, varsayılan olarak false olan bir boole değeridir. Bu parametre true olarak ayarlandığında, istemciye gönderilen HTTP yanıtı değişir. Yanıt şu hale gelir:
Böylece, müşteriye gönderilen yanıt kodu artık 301 Moved Permanently olur. Yönlendirme daha önce olduğu gibi gerçekleşir, ancak bu yönlendirmenin kalıcı olduğu belirtilir. Bu, arama motorlarının sonuçlarında eski URL kodunu yenisiyle değiştirmesine olanak tanır.
3.11. [RedirectToRouteResult] türünde bir sonuca sahip eylem
Şu yeni eylem ele alınalım:
// Eylem08
public RedirectToRouteResult Action08()
{
return new RedirectToRouteResult("Default",new RouteValueDictionary(new {controller="First",action="Action05"}));
}
- 2. satır: Eylem, [RedirectToRouteResult] türünde bir sonuç döndürür. Bu tür, bir istemciyi, daha önce olduğu gibi bir karakter dizisiyle değil, bir rota ile belirtilen bir URL adresine yönlendirmeye olanak tanır.
Yollar, [App_Start/RouteConfig] içinde tanımlanmıştır. Şu anda sadece bir tane vardır:
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
- 4. satırda, istemciden controller=First ve action=Action05 değişkenleriyle [Default] adlı rotaya yönlendirilmesi istenir. Yönlendirme sistemi daha sonra /First/Action05 yönlendirme rotası olan URL'i oluşturacaktır. Sunucudan gelen HTTP yanıtı bunu göstermektedir:
- 1. satır: yönlendirme;
- 4. satır: URL yönlendirme sistemi tarafından oluşturulan yönlendirme adresi.
3.12. [void] türünde bir sonuca sahip eylem
Şu yeni eylem olsun:
// Eylem09
public void Action09()
{
string nom = Request.QueryString["nom"] ?? "inconnu";
Response.AddHeader("Content-Type", "text/plain");
Response.Write(string.Format("<h3>Action09</h3>nom={0}", nom));
}
- 2. satır: eylem hiçbir sonuç döndürmez. Müşteriye gönderilen yanıt akışına kendisi yazar;
- 4. satır: İstekte [nom] adlı olası bir parametre alınır. Bu parametreye, [First] denetleyicisinin miras aldığı [Controller] denetleyicisinin [Request] özelliği aracılığıyla erişilebilir. [nom] parametresi, [/First/Action09?nom=quelquechose] biçiminde aktarıldığında, Request.QueryString["nom"]'te kullanılabilir. 4. satırın sözdizimi şuna eşdeğerdir:
- 5. satır: İstemciye gönderilen yanıt, [First] denetleyicisinin miras aldığı [Controller] denetleyicisinin [Response] özelliği aracılığıyla erişilebilir;
- 5. satır: Sunucunun müşteriye göndereceği belgenin türünü belirten HTTP [Content-Type] başlığı belirlenir. Burada "text/plain", belgenin tarayıcı tarafından yorumlanmaması gereken düz metin olduğunu belirtir;
- 6. satır: Yanıt akışına bir karakter dizisi yazılır. Buraya, tarayıcı tarafından yorumlanmaması gereken HTML etiketleri eklenmiştir; zira tarayıcı daha önce HTTP [Content-Type : text/plain"] başlığını almış olacaktır. İşte bunu doğrulamak istiyoruz.
Projeyi derleyelim ve önce URL [/First/Action09?nom=someone ][1], ardından daURL [/First/Action09 ] [2]:
![]() |
Şimdi Chrome'da sunucudan gelen HTTP yanıtına bakalım:
- 3. satır: Eylem kodunda kendimiz belirlediğimiz HTTP başlığını görüyoruz.
3.13. İkinci bir denetleyici
Projede ikinci bir denetleyici oluşturalım. Sayfa 40, paragraf 3.1'de açıklanan yöntemi izleyeceğiz. Buna [Second] adını vereceğiz.
![]() |
Oluşturulan kodu şu şekildedir:
namespace Exemple_01.Controllers
{
public class SecondController : Controller
{
//
// GET: /İkinci/
public ActionResult Index()
{
return View();
}
}
}
Bunu şu şekilde değiştirelim:
using System.Text;
using System.Web.Mvc;
namespace Exemple_01.Controllers
{
public class SecondController : Controller
{
// /Saniye/Eylem01
public ContentResult Action01()
{
return Content("Contrôleur=Second, Action=Action01", "text/plain", Encoding.UTF8);
}
}
}
Ardından bir tarayıcıyla URL [/Second/Action01] adresini çağıralım. Şu yanıtı alıyoruz:
![]() |
Bu URL, Chrome'daki isteğin günlüklerinde de görüldüğü gibi, HTTP GET komutuyla istenmiştir:
URL, HTTP ve POST komutlarıyla da çağrılabilir. Bunu göstermek için yine [Advanced Rest Client] uygulamasını kullanalım:
![]() |
- [1]'te uygulamayı başlatıyoruz (yeni bir Chrome sekmesinin [Applications] sekmesinde);
- [2]'te, [Request] seçeneğini seçin;
- [3]'te, istenen URL'i belirtin;
- [4]'te, URL'in bir POST ile talep edilmesi gerektiğini belirtin;
Sunucudan HTTP yanıtını almak için (CTRL-I) komutuyla Chrome günlüklerini etkinleştirilir. [Send] komutunu çalıştırdığımızda, önceki istekle ilgili HTTP iletişimleri şu şekildedir:
Tarayıcı şu isteği gönderir:
- 1. satır: URL, bir POST ile doğru şekilde talep edilmiştir;
- 4. satır: Gönderilen öğelerin bayt cinsinden boyutu. Burada böyle bir şey yoktur.
Sunucudan gelen HTTP yanıtı şöyledir:
- 3. satır: sunucu biçimlendirilmemiş (düz) bir metin belgesi gönderir;
- 12. satır: 148 karakterden oluşur.
Gönderilen belge şöyledir:
![]() |
GET ile aynı belge elde edilir.
3.14. Özellik ile filtrelenen eylem
Şu yeni eylemi oluşturalım:
// /Saniye/Eylem02
[HttpPost]
public ContentResult Action02()
{
return Content("Contrôleur=Second, Action=Action02", "text/plain", Encoding.UTF8);
}
[Action02] eylemi, [Action01] eylemine benzer, ancak bu eyleme yalnızca HTTP POST komutuyla erişilebileceği belirtilir (2. satır). Kullanılabilecek diğer öznitelikler şunlardır:
HttpGet | komutu yalnızca GET komutuna hizmet eder |
HttpHead | sadece HEAD komutunda kullanılır |
HttpOptions | sadece OPTIONS komutuna hizmet eder |
HttpPut | sadece PUT komutuna hizmet eder |
HttpDelete | sadece DELETE komutuna hizmet eder |
URL [/Second/Action02] komutlarını doğrudan tarayıcıda isteyelim. Bunun üzerine GET komutu ile istek gönderilir. Tarayıcı da şu yanıtı görüntüler:
![]() |
Sunucudan gelen HTTP yanıtı şöyleydi:
- 1. satır: HTTP 404 Not Found kodu, sunucunun istenen belgeyi bulamadığını gösterir. Burada, [Action02] eylemi, GET isteğini karşılayamadı çünkü bu eylem yalnızca POST komutlarını işler;
- 3. satır: Geri gönderilen belgenin boyutu. Bu, tarayıcı tarafından görüntülenen sayfadır:
![]() |
3.15. Bir rotadaki öğeleri almak
Yukarıda açıklanan iki işlemde, şunun gibi bir kod yazıyorduk:
public ContentResult Action02()
{
return Content("Contrôleur=Second, Action=Action02", "text/plain", Encoding.UTF8);
}
Denetleyici ve eylemin adları koda sabit olarak yazılmıştı. Bu adları değiştirirsek, kod artık doğru çalışmaz. Denetleyiciye ve eyleme şu şekilde erişebiliriz:
// /Saniye/Eylem03
public ContentResult Action03()
{
string texte = string.Format("Contrôleur={0}, Action={1}", RouteData.Values["controller"], RouteData.Values["action"]);
return Content(texte, "text/plain", Encoding.UTF8);
}
[App_Start/RouteConfig] içinde tanımlanan rota şöyledir:
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
- satırda, rotanın üç öğesi RouteData.Values["élément"] ile elde edilebilir; öğe ise [controller, action, id]'te bulunur.
Şimdi URL ve [http://localhost:49302/Second/Action03] komutlarını verelim:
![]() |
Denetleyicinin adını ve eylemin adını başarıyla aldık.




























