3. Контролери, дії, маршрутизація
Розглянемо архітектуру додатка ASP.NET MVC:
![]() |
У цьому розділі ми розглянемо процес, завдяки якому запит [1] надходить до контролера та дії [2a], які його оброблять — цей механізм називається маршрутизацією. Крім того, ми розглянемо різні відповіді [3], які дія може надати браузеру. Це може бути щось інше, ніж представлення V [4b].
3.1. Структура проєкту ASP.NET MVC
Створимо перший проект ASP.NET MVC за допомогою Visual Studio Express 2012. Ми додамо його [1] до рішення, яке використовувалося в попередньому розділі:
![]() |
![]() |
- в [2] — ім’я нового проєкту;
- [3, 4] — ми обираємо базовий проект ASP.NET MVC. Цей шаблон надає нам порожній веб-додаток, однак із усіма ресурсами (DLL, бібліотеки JavaScript тощо), необхідними для роботи.
Отриманий проект представлено у файлі [5]. Ми зробимо його [6] стартовим проектом рішення:
![]() |
У [5] слід звернути увагу на наступні моменти:
- архітектура проекту відображає його модель MVC:
- контролери C будуть розміщені в папці [Controllers],
- моделі даних M будуть розміщені в папці [Models],
- представлення V будуть розміщені в папці [Views],
![]() |
- у [1] файл [Site.css] стане файлом CSS за замовчуванням для додатка;
- у [2] нам надається певна кількість бібліотек JavaScript;
- у [3] містяться три особливі подання: _ViewStart, _Layout, Error.
Файл [_ViewStart] має такий вигляд:
@{
Layout = "~/Views/Shared/_Layout.cshtml";
}
- рядок 1: символ @ позначає послідовність C# у подання. Дійсно, у подання можна включати код C#;
- рядок 2: визначає змінну Layout, яка визначає батьківський вигляд для всіх інших виглядів. Вона відповідає головній сторінці класичного фреймворку ASP.NET.
Файл [_Layout] має такий вигляд:
<!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], його тіло буде відтворюватися за допомогою 11-го рядка вище. Це означає, що представлення не повинно містити теги <html>, <head>, <body>. Вони надаються вищезазначеним файлом. Наразі цей файл є досить незрозумілим. Спростимо його:
<!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: загальний заголовок для всіх подань;
- рядок 9: заголовок, спільний для всіх переглядів;
- рядок 10: вміст, характерний для відображуваного виду.
![]() |
- [Web.config] — це файл конфігурації веб-додатка. Він є складним. Його доведеться змінювати під час використання фреймворку [Spring.net] у багатошаровій архітектурі.
- [Global.asax] містить код, що виконується під час запуску додатка. Зазвичай цей код використовує різні конфігураційні файли додатка, зокрема [Web.config].
3.2. Маршрутизація за замовчуванням у URL
Наразі код [Global.asax] має такий вигляд:
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, namespace класу. Він походить безпосередньо від назви проєкту та міститься у властивостях проєкту:

![]() |
У [1] ми встановлюємо простір імен за замовчуванням. Він буде використовуватися за замовчуванням для всіх класів, які будуть створені в проєкті.
Повернемося до коду класу [Global.asax]:
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: клас [MvcApplication] походить від класу [HttpApplication]. Ім’я [MvcApplication] можна змінити;
- рядок 11: метод [Application_Start] — це метод, що виконується під час запуску веб-додатка. Він виконується лише один раз. Саме тут відбувається ініціалізація додатка.
Наразі код [Application_Start] виглядає так:
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
WebApiConfig.Register(GlobalConfiguration.Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
Наразі немає потреби розуміти цей код повністю. Рядки 5–8 визначають маршрути, які підтримує веб-додаток. Повернемося до архітектури додатка ASP.NET MVC:
![]() |
Ми вже пояснювали, що [Front Controller] має перенаправити URL до дії, яка відповідає за її обробку. Маршрут слугує для встановлення зв’язку між шаблоном URL та дією. Ці маршрути визначаються у папці [App_Start] проекту за допомогою класів [WebApiConfig, FilterConfig, RouteConfig, BundleConfig]:
![]() |
Наразі нас цікавить лише клас [RouteConfig]:
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 визначають формат URL, який підтримує програма. Це називається маршрутом. Може існувати кілька можливих маршрутів (= кілька можливих шаблонів URL). Вони відрізняються між собою за назвою (рядок 13). Формат URL для маршруту визначено у рядку 14. У цьому випадку URL матиме три складові:
- {controller}: ім’я класу, похідного від [Controller]. Його шукатимуть у папці [Controllers] проекту. За угодою, якщо URL — це /X/Y/Z, контролер, відповідальний за обробку цього URL, буде класом XController. До назви контролера, зазначеного в URL, додається суфікс Controller;
- {action} — ім’я методу у зазначеному вище контролері. Саме цей метод отримає параметри, що супроводжують URL, і обробить їх. Цей метод може повертати різні результати:
- void: дія самостійно сформує відповідь для браузера клієнта
- String: дія повертає клієнту рядок символів;
- ViewResult: повертає клієнту представлення;
- PartialViewResult: повертає клієнту частковий вигляд;
- EmptyResult: клієнту надсилається порожня відповідь;
- RedirectResult: запитує клієнта перенаправити на URL
- RedirectToRouteResult: те саме, але URL формується на основі маршрутів додатка;
- JsonResult: надсилає відповідь JSON
- JavaScriptResult: повертає код JavaScript клієнту;
- ContentResult: повертає потік HTML клієнту, оминаючи представлення;
- FileContentResult: повертає файл клієнту;
- FileStreamResult: те саме, але іншим шляхом;
- FilePathResult: ...
- {id}: параметр, який буде передано до дії. Для цього дія повинна мати параметр із назвою id.
У рядку 15 визначено значення за замовчуванням на випадок, якщо URL не має очікуваного формату /{controller}/{action}/{id}. Також зазначено, що параметр {id} у URL є необов’язковим. Ось список неповних URL та URL, доповнений значеннями за замовчуванням:
Оригінальний URL | Заповнений файл URL |
/ | /Home/Index |
/Do | /Do/Індекс |
/Do/Something | /Зробити/Щось |
/Зробити/Щось/4 | /Зробити/Щось/4 |
/Зробити/Щось/x/y/z | URL без маршруту |
3.3. Створення контролера та першої дії
Створимо перший контролер:
![]() |
![]() |
- у [1] вкажіть назву контролера з суфіксом [Controller];
- у [2] створіть порожній контролер MVC;
- у [3] він був створений.
Код для [FirstController] такий:
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: було згенеровано namespace за замовчуванням;
- рядок 9: клас [FirstController] походить від класу [System.Web.Mvc.Controller];
- рядки 14–17: за замовчуванням було згенеровано дію [Index]. Вона є публічною. Це важливо, інакше її не буде знайдено. Вона повертає тип [ActionResult], який є абстрактним класом, від якого походять більшість результатів, що зазвичай повертає дія. Це «універсальний» тип, який можна уточнити, замінивши його на реальну назву типу, що повертається;
- рядок 16: метод нічого не робить. Він просто повертає представлення, тобто тип [ViewResult]. Назва представлення не вказана. У цьому випадку фреймворк шукає в папці [Views / First] вигляд із назвою дії, тобто в даному випадку: [Index.cshtml].
Створимо вигляд [Index.cshtml]:
![]() |
- у [1] клацаємо правою кнопкою миші в коді дії та вибираємо опцію [Ajouter une vue];
- у [2] майстер пропонує подачу з назвою дії. Це саме те, що нам потрібно;
- у [3] за замовчуванням пропонується використання шаблону [_Layout.cshtml];
- у [4] після підтвердження майстер створює представлення у підпапці папки [Views], що має назву контролера (First).
Код, згенерований для подання [Index], має такий вигляд:
@{
ViewBag.Title = "Index";
}
<h2>Index</h2>
- рядки 1–3: код на C#, що визначає змінну;
- рядок 5: тег HTML.
Замінюємо весь попередній код на цей:
<strong>Vue [Index]...</strong>
Підсумуємо:
- у нас є контролер C під назвою [First];
- у нас є дія з назвою [Index], яка вимагає відображення подання з назвою [Index];
- у нас є вигляд V [Index].
Ми можемо викликати дію [Index] двома способами:
- /First/Index;
- /First, оскільки [Index] також є дією за замовчуванням у маршрутах.
Запустимо додаток (CTRL-F5). Ми отримаємо таку сторінку:
1

У [1] запитувана URL мала вигляд http://localhost:49302. Шляху немає. Ми знаємо, що наш маршрутизатор очікує URL у формі /{controller}/{action}/{id}. Оскільки ці елементи відсутні, використовуються значення за замовчуванням. Запит URL перетворюється на http://localhost:49302/Home/Index. Контролер [Home] не існує. Тому запит URL відхиляється.
Тепер спробуємо URL http://localhost:49302/First/Index, ввівши його безпосередньо в браузері:
![]() |
Наведена вище сторінка була згенерована дією [Index] контролера [First]. Сторінка, згенерована цією дією, є поданням [Index], код якого був таким:
<strong>Vue [Index]...</strong>
Вона генерує частину [1]. Частина [2], у свою чергу, походить із головної сторінки [_Layout], яку ми визначили трохи раніше:
<!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>
У рядку 9 було згенеровано частину [2] сторінки. Вигляд [Index] з’являється лише в рядку 10.
Якщо переглянути вихідний код отриманої сторінки, можна побачити, що сторінка [Index] дійсно включена (рядок 10 нижче) у сторінку [Layout]:
Тепер спробуємо URL та [/First]:
![]() |
URL [/First] був неповним. Його було доповнено значеннями за замовчуванням для маршруту, і він перетворився на [/First/Index]. Отже, ми отримуємо той самий результат, що й раніше.
3.4. Дія з результатом типу [ContentResult] - 1
Створимо нову дію в контролері [First]:
using System.Text;
using System.Web.Mvc;
namespace Exemple_01.Controllers
{
public class FirstController : Controller
{
// Індекс
public ViewResult Index()
{
return View();
}
// Action01
public ContentResult Action01()
{
return Content("<h1>Action [Action01]</h1>", "text/plain", Encoding.UTF8);
}
}
}
Нова дія визначена у рядках 14–18. Вона просто повертає рядок за допомогою методу [Content] (рядок 16) класу [Controller] (рядок 6). Параметри методу такі:
- рядок-відповідь;
- покажчик типу надісланого тексту: «text/plain», «text/html», «text/xml» тощо. Цей показник називається типом MIME (http://fr.wikipedia.org/wiki/Type_MIME);
- третій параметр дозволяє вказати тип кодування, що використовується для тексту.
Замість використання абстрактного типу [ActionResult] наші методи вказують фактичний тип, що відображається (рядки 9 та 14).
Запросімо URL [/First/Action01]. Отримаємо таку сторінку:
![]() |
Розглянемо вихідний код отриманої сторінки:
Браузер отримав лише текст, надісланий акцією, і нічого більше. Цей режим є цікавим, коли потрібно отримати від веб-сервера «чисті» дані без оточуючого коду HTML. Зверніть увагу, що браузер не проінтерпретував тег <h1>. Щоб зрозуміти, чому, давайте подивимося в Chrome на обмін даними:
Браузер надіслав такі заголовки:
Сервер відповів йому такими заголовками:
- рядок 3: визначає тип документа. Тут ми бачимо атрибути, задані в методі [Action01]. Саме тому, що браузеру було вказано, що документ має тип «text/plain», а не «text/html», він не проінтерпретував тег <h1>, який містився в отриманому документі.
3.5. Дія з результатом типу [ContentResult] - 2
Розглянемо наступну, третю дію:
using System.Text;
using System.Web.Mvc;
namespace Exemple_01.Controllers
{
public class FirstController : Controller
{
...
// Дія02
public ContentResult Action02()
{
string data = "<action><name>Action02</name><description>renvoie un texte XML</description></action>";
return Content(data, "text/xml", Encoding.UTF8);
}
}
}
- рядок 12: визначається текст XML;
- рядок 13: його надсилають до браузера, вказавши, що це XML з типом MIME «text/xml».
У браузері відображається така сторінка:
![]() |
Давайте подивимося в Chrome на відповідь HTTP від сервера:
- рядок 3: визначає тип документа. Тут містяться атрибути, задані в методі [Action02];
- рядок 12: розмір у байтах документа, надісланого сервером.
Документ, надісланий сервером, виглядає так (копія з Chrome):
![]() |
3.6. Дія з результатом типу [JsonResult]
Додамо наступну дію до контролера [First]:
// Дія03
public JsonResult Action03()
{
dynamic personne = new ExpandoObject();
personne.nom = "someone";
personne.age = 20;
return Json(personne,JsonRequestBehavior.AllowGet);
}
- рядок 4: змінна типу dynamic. Під час виконання до такої змінної можна вільно додавати властивості. Властивість створюється одночасно з її ініціалізацією;
- рядки 5–6: ініціалізуються дві властивості nom та age;
- рядок 7: повертається представлення об’єкта у форматі JSON (Javascript Object Notation). JSON дозволяє серіалізувати об’єкт у рядок символів і, навпаки, десеріалізувати рядок у об’єкт. Це альтернатива серіалізації/десеріалізації XML;
- рядок 2: дія повертає тип [JsonResult]. Цей тип може бути повернутий лише для запиту POST. Якщо потрібно повернути його для методу GET, необхідно вказати у другому параметрі конструктора класу Json (рядок 7) значення JsonRequestBehavior.AllowGet.
При запиті URL [/First/Action03] браузер відображає наступне:
![]() |
Відповідь сервера на запит HTTP виглядає так:
- рядок 3: вказує, що надісланий документ має формат JSON;
- рядок 10: розмір надісланого документа становить 58 байт. Він має такий вигляд:
Динамічний елемент [personne] сприймається JSON як масив словників, де кожен словник:
- відповідає полю змінної [personne];
- має два ключі: «Key» та «Value». Ключ «Key» має значення, пов’язане з назвою поля, а ключ «Value» — значення поля.
3.7. Дія з результатом типу [string]
Додамо таку дію до контролера [First]:
// Дія04
public string Action04()
{
return "<h3>Contrôleur=First, Action=Action04</h3>";
}
Коли ми запитуємо URL [/First/Action04] у браузері Chrome, отримуємо таку відповідь:
![]() |
Бачимо, що тег <h3> було інтерпретовано. Розглянемо відповідь HTTP від сервера:
та наступний документ:
У третьому рядку видно, що сервер вказав надіслати текст у форматі HTML. Саме тому браузер інтерпретував тег <h3>. Отже, якщо потрібно надіслати чистий текст, краще повернути [ContentResult], а не [string]. А [ContentResult] дозволяє нам вказати тип MIME «text/plain», щоб позначити, що ми надсилаємо неформатований текст, який, отже, не підлягає інтерпретації з боку браузера.
3.8. Дія з результатом типу [EmptyResult]
Розглянемо таку нову дію:
// Дія05
public EmptyResult Action05()
{
return new EmptyResult();
}
Ця дія просто повертає тип [EmptyResult]. У цьому випадку сервер надсилає клієнту порожню відповідь, як показано в його відповіді HTTP:
- рядок 9: сервер повідомляє клієнту, що надсилає йому порожній документ.
3.9. Дія з результатом типу [RedirectResult] — 1
Розглянемо таку нову дію:
// Дія06
public RedirectResult Action06()
{
return new RedirectResult("/First/Action05");
}
Ця дія повертає тип [RedirectResult]. Цей тип дозволяє надіслати клієнту команду перенаправлення до параметра конструктора URL (рядок 4). Після цього клієнт надішле новий запит GET до [/First/Action05]. Отже, клієнт надсилає загалом два запити.
Браузер відображає результат другого запиту:
![]() |
Розглянемо відповідь сервера HTTP у Chrome:
![]() |
Вище наведено обидва запити браузера. Розглянемо перший запит [Action06]. Відповідь сервера HTTP виглядає так:
- рядок 1: сервер відповів кодом 302 Found. До цього моменту код був 200 OK, що означає, що запитуваний документ було знайдено. Код 302 вказує на те, що вимагається перенаправлення. Адреса перенаправлення вказана у рядку 4. Тут ми бачимо адресу перенаправлення, яку ми вказали в коді дії;
- рядок 11: сервер вказує, що у своїй відповіді HTTP він надсилає документ типу text/html (рядок 3) розміром 132 байти (рядок 11). Якщо в Chrome переглянути відповідь на запит [Action06], вона, як і слід було очікувати, порожня. Ймовірно, цьому є пояснення, але я його не знаю.
Через перенаправлення браузер надсилає новий запит GET до URL, зазначеного у рядку 4 вище, як це видно в Chrome у рядку 1 нижче:
3.10. Дія з результатом типу [RedirectResult] - 2
Нехай нова дія виглядає так:
// Дія07
public RedirectResult Action07()
{
return new RedirectResult("/First/Action05",true);
}
У рядку 4 до конструктора типу [RedirectResult] додано другий параметр. Це логічне значення, яке за замовчуванням дорівнює false. Якщо його значення змінити на true, це змінить відповідь HTTP, що надсилається клієнту. Вона стане такою:
Таким чином, код відповіді, що надсилається клієнту, тепер дорівнює 301 Moved Permanently. Перенаправлення відбувається так само, як і раніше, але вказується, що це перенаправлення є постійним. Це дозволяє пошуковим системам замінити у своїх результатах старий код URL на новий.
3.11. Дія з результатом типу [RedirectToRouteResult]
Розглянемо таку нову дію:
// Дія08
public RedirectToRouteResult Action08()
{
return new RedirectToRouteResult("Default",new RouteValueDictionary(new {controller="First",action="Action05"}));
}
- рядок 2: дія повертає тип [RedirectToRouteResult]. Цей тип дозволяє перенаправити клієнта на URL, вказаний не за допомогою символьного рядка, як раніше, а за допомогою маршруту.
Маршрути визначені в [App_Start/RouteConfig]. Наразі існує лише один:
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
- у рядку 4 клієнту пропонується перенаправитися на маршрут із назвою [Default] із змінною controller=First та змінною action=Action05. Система маршрутизації згенерує маршрут перенаправлення URL до /First/Action05. Про це свідчить відповідь сервера HTTP:
- рядок 1: перенаправлення;
- рядок 4: адреса перенаправлення, згенерована системою маршрутизації URL.
3.12. Дія з результатом типу [void]
Нехай це буде така нова дія:
// Дія09
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: дія не повертає жодного результату. Вона сама записує дані у потік відповіді, що надсилається клієнту;
- рядок 4: отримуємо можливий параметр із назвою [nom] у запиті. Доступ до нього здійснюється через властивість [Request] контролера [Controller], від якого успадковує контролер [First]. Параметр [nom], переданий у формі [/First/Action09?nom=quelquechose], доступний у Request.QueryString["nom"]. Синтаксис рядка 4 еквівалентний такому:
- рядок 5: відповідь, надіслана клієнту, доступна через властивість [Response] контролера [Controller], від якого успадковує контролер [First];
- рядок 5: встановлюється заголовок HTTP [Content-Type], який вказує на тип документа, який сервер збирається надіслати клієнту. У даному випадку «text/plain» означає, що документ є простим текстом, який не повинен інтерпретуватися браузером;
- рядок 6: у потік відповіді записується рядок символів. До нього включено теги HTML, які не повинні інтерпретуватися браузером, оскільки той раніше отримав заголовок HTTP [Content-Type : text/plain"]. Саме це ми й хочемо перевірити.
Скомпілюємо проєкт і надішлемо запит на URL [/First/Action09?nom=someone ][1], а потім наURL [/First/Action09 ] [2]:
![]() |
Тепер подивимося в Chrome на відповідь HTTP від сервера:
- рядок 3: ми бачимо заголовок HTTP, який ми самі встановили в коді дії.
3.13. Другий контролер
Створимо в проєкті другий контролер. Дотримаємося методу, описаного в розділі 3.1, на сторінці 40. Назвемо його [Second].
![]() |
Його згенерований код такий:
namespace Exemple_01.Controllers
{
public class SecondController : Controller
{
//
// GET: /Second/
public ActionResult Index()
{
return View();
}
}
}
Змінимо його наступним чином:
using System.Text;
using System.Web.Mvc;
namespace Exemple_01.Controllers
{
public class SecondController : Controller
{
// /Second/Action01
public ContentResult Action01()
{
return Content("Contrôleur=Second, Action=Action01", "text/plain", Encoding.UTF8);
}
}
}
Потім завантажимо URL [/Second/Action01] у браузері. Отримаємо таку відповідь:
![]() |
Цей URL було запитано за допомогою команди HTTP GET, як показано в логах HTTP запиту в Chrome:
URL також може бути запрошений за допомогою команд HTTP та POST. Щоб це продемонструвати, знову скористаємося додатком [Advanced Rest Client]:
![]() |
- у [1] запускаємо додаток (у вкладці [Applications] нової вкладки Chrome);
- у [2] вибираємо опцію [Request];
- у [3] вказуємо необхідну URL;
- у [4] вказуємо, що URL має бути запитано разом із POST;
Увімкніть журнали Chrome за допомогою (CTRL-I), щоб отримати відповідь HTTP від сервера. При виконанні [Send], що є попереднім запитом, обмін даними HTTP відбувається наступним чином:
Браузер надсилає такий запит:
- рядок 1: запит URL дійсно надсилається разом із POST;
- рядок 4: розмір у байтах відправлених елементів. Тут їх немає.
Відповідь HTTP від сервера має такий вигляд:
- рядок 3: сервер надсилає неформатований (plain) текстовий документ;
- рядок 12: 148 символів.
Надісланий документ має такий вигляд:
![]() |
Отримуємо той самий документ, що й у випадку з GET.
3.14. Дія, відфільтрована за атрибутом
Створимо таку нову дію:
// /Second/Action02
[HttpPost]
public ContentResult Action02()
{
return Content("Contrôleur=Second, Action=Action02", "text/plain", Encoding.UTF8);
}
Дія [Action02] аналогічна дії [Action01], але вказано, що вона доступна лише за допомогою команди HTTP POST (рядок 2). Можна використовувати й інші атрибути:
HttpGet | використовується лише з командою GET |
HttpHead | використовується лише для команди HEAD |
HttpOptions | використовується лише для команди OPTIONS |
HttpPut | використовується лише для команди PUT |
HttpDelete | працює лише з командою DELETE |
Запросімо URL [/Second/Action02] безпосередньо у браузері. Тоді вона запитується за допомогою GET. Після цього браузер відображає таку відповідь:
![]() |
Відповідь HTTP від сервера була такою:
- рядок 1: код HTTP 404 Not Found вказує, що сервер не знайшов запитуваний документ. У цьому випадку дія [Action02] не змогла обробити запит GET, оскільки вона обробляє лише команди POST;
- рядок 3: розмір повернутого документа. Це сторінка, яку відобразив браузер:
![]() |
3.15. Отримання елементів маршруту
У двох описаних вище діях ми писали щось на кшталт:
public ContentResult Action02()
{
return Content("Contrôleur=Second, Action=Action02", "text/plain", Encoding.UTF8);
}
Імена контролера та дії були жорстко вказані в коді. Якщо змінити ці імена, код перестане працювати. Отримати доступ до контролера та дії можна таким чином:
// /Секунда/Дія03
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], є таким:
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
У рядку 3 три елементи маршруту можна отримати за допомогою RouteData.Values["élément"] з елементом у [controller, action, id].
Запросимо URL та [http://localhost:49302/Second/Action03]:
![]() |
Ми успішно отримали як ім’я контролера, так і назву дії.




























