Данное руководство устарело. Актуальное руководство: Руководство по ASP.NET Core 7
Вместо использования конечных точек и EndpointMiddleware для созданию системы маршрутизации в приложении мы можем применять метод UseMvc(). Он встраивает в конвейер обработки запроса компонент RouterMiddleware, который используется для сопоставления запросов с маршрутами.
Стоит отметить, что мы можем использовать либо новую форму маршрутизации на основе конечных точек на основе EndpointRoutingMiddleware + EndpointMiddleware,
либо старую форму маршрутизации с использованием RouterMiddleware. Поэтому если мы хотим использовать метод UseMvc()
, то необходимо при подключении сервисов
MVC в методе ConfigureServices явным образом отключить использование конечных точек. Вне зависимости от того, какой метод используется для подключения
сервисов MVC, все эти методы в качестве параметра могут принимать делегат Action<MvcOptions>. И с помощью свойства
EnableEndpointRouting объекта MvcOptions можно отключить использование конечных точек:
public void ConfigureServices(IServiceCollection services) { services.AddControllersWithViews(mvcOtions=> { mvcOtions.EnableEndpointRouting = false; }); // или так //services.AddControllers(mvcOtions => //{ // mvcOtions.EnableEndpointRouting = false; //}); // или так //services.AddMvcCore(mvcOtions => //{ // mvcOtions.EnableEndpointRouting = false; //}); // или так //services.AddMvc(mvcOtions => //{ // mvcOtions.EnableEndpointRouting = false; //}); }
Применим метод UseMvc()
для определения маршрутов:
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; //using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; namespace MvcRoutingApp { public class Startup { public Startup(IConfiguration configuration) { Configuration = configuration; } public IConfiguration Configuration { get; } public void ConfigureServices(IServiceCollection services) { services.AddControllersWithViews(mvcOtions=> { mvcOtions.EnableEndpointRouting = false; }); } public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.UseStaticFiles(); // добавление компонентов mvc и определение маршрута app.UseMvc(routes => { routes.MapRoute( name: "default", template: "{controller=Home}/{action=Index}/{id?}"); }); } } }
Обратите внимание, что теперь естественно не надо использовать методы UseRouting и UseEndpoints для встраивания в конвейер системы маршрутизации.
Метод app.UseMvc()
в качестве параметра принимает объект Action<IRouteBuilder>, который добавляет
один маршрут. Параметр "controller" будет сопоставляться по имени с одним из контроллеров приложения, а параметр "action" - с действием этого контроллера.
Например, при запросе http://localhost:3456/Home/Index система выберет для обработки запроса контроллер Home - имя контроллера без префикса Controller и его
действие Index.
Хотя данный способ является альтернативой использованию конечных точек, но в целом определение маршрутов будет выглядеть также, как и в методе UseEndpoints. Например, определим несколько маршрутов:
app.UseMvc(routes => { routes.MapRoute("api", "api/get", new { controller = "Home", action = "About" }); routes.MapRoute( name: "default", template: "{controller=Home}/{action=Index}/{id?}"); });
Первый маршрут сопоставляется с запросом типа http://localhost:xxxx/api/get, и для обработки такого запроса будет выбираться метод About контроллера Home. Второй маршрут стандартный.
Поскольку второй маршрут является стандартным и применяется многими разработчиками, то для его создания определен специальный метод:
app.UseMvcWithDefaultRoute();
То есть этот вызов метода равносилен конструкции:
app.UseMvc(routes => { routes.MapRoute( name: "default", template: "{controller=Home}/{action=Index}/{id?}"); });
Поэтому вместо определения стандартного маршрута через app.UseMvc()
, мы можем применять метод app.UseMvcWithDefaultRoute()
.
Метод UseMvc имеет следующее определение:
public static IApplicationBuilder UseMvc( this IApplicationBuilder app, Action<IRouteBuilder> configureRoutes) { if (app == null) { throw new ArgumentNullException(nameof(app)); } if (configureRoutes == null) { throw new ArgumentNullException(nameof(configureRoutes)); } VerifyMvcIsRegistered(app); var options = app.ApplicationServices.GetRequiredService<IOptions<MvcOptions>>(); if (options.Value.EnableEndpointRouting) { var message = "Endpoint Routing does not support 'IApplicationBuilder.UseMvc(...)'. To use " + "'IApplicationBuilder.UseMvc' set 'MvcOptions.EnableEndpointRouting = false' inside " + "'ConfigureServices(...)."; throw new InvalidOperationException(message); } var routes = new RouteBuilder(app) { DefaultHandler = app.ApplicationServices.GetRequiredService<MvcRouteHandler>(), }; configureRoutes(routes); routes.Routes.Insert(0, AttributeRouting.CreateAttributeMegaRoute(app.ApplicationServices)); return app.UseRouter(routes.Build()); }
Исходный код можно найти на гитхабе
Как можно увидеть, данный метод полагается на компонент RouterMiddleware, который был рассмотрен в статье RouteMiddlevare. Для создания маршрута применяетс класс RouteBuilder, а для обработки маршрутов фреймворк предоставляет встроенный класс MvcRouteHandler, исходный код которого можно найти здесь.
Хотя по умолчанию все маршруты в UseMvc обрабатываются с помощью MvcRouteHandler, но его применение необязательно, и мы можем задать свою логику обработки маршрутов. Например, изменим класс Startup следующим образом:
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.AspNetCore.Routing; namespace MvcRoutingApp { public class Startup { public Startup(IConfiguration configuration) { Configuration = configuration; } public IConfiguration Configuration { get; } public void ConfigureServices(IServiceCollection services) { services.AddControllersWithViews(mvcOtions=> { mvcOtions.EnableEndpointRouting = false; }); } public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.UseStaticFiles(); app.UseMvc(routes => { routes.MapRoute("api/get", async context => { await context.Response.WriteAsync("для обработки использован маршрут api/get"); }); routes.MapRoute( name: "default", template: "{controller=Home}/{action=Index}/{id?}"); }); } } }
Для первого маршрута с шаблоном "api/get" здесь задан свой обработчик в виде асинхронного делегата, который отправляет в выходной поток одну строку. Остальные маршруты будут обрабатываться стандартным MvcRouteHandler.