ASP.NET Core MVC는 전역 라우팅 접두사를 구성합니다
머리말
안녕하세요 여러분, 오늘은 ASP.NET Core MVC의 새로운 기능을 소개하겠습니다. 글로벌 라우팅 통합 접두사를 추가합니다. 엄밀히 말하면 새로운 기능은 아니지만 Core MVC만의 고유한 기능입니다.
애플리케이션 배경
Web Api 애플리케이션을 만들 때 이런 시나리오를 접한 적이 있는지 모르겠습니다. 즉, 모든 인터페이스가 /api로 시작합니다. 인터페이스 요청 주소는 다음과 같습니다:
http://www.example.com/api/order/333
또는 그러한 요구 사항
http:/ /www.example.com/api/v2/order/333
과거에는 이 요구 사항을 충족하려면 [Route("/api /order")]를 추가할 수 있었습니다. , 그러면 MVC 프레임워크는 라우팅 테이블을 스캔하여 /api/order와 같은 요청을 일치시킵니다.
그러나 버전 번호가 있는 두 번째 요구 사항의 경우 원래 컨트롤러의 경로 정의는 [Route("/api/v1/order")]였으며 이제 v2로 업그레이드해야 합니다. 수백 개가 넘는 인터페이스를 하나씩 수정해야 하므로 혼란이 생길 수 있습니다.
이제 통합된 방식으로 전역 접두사 라우팅 태그를 추가할 수 있는 더 간단하고 우아한 방법이 있습니다.
IApplicationModelConvention 인터페이스
먼저 Microsoft.AspNetCore.Mvc.ApplicationModels 네임스페이스에 있는 IApplicationModelConvention 인터페이스를 사용해야 합니다. 인터페이스의 정의를 살펴보겠습니다.
public interface IApplicationModelConvention { void Apply(ApplicationModel application); }
우리는 MVC 프레임워크에 몇 가지 규칙이 있다는 것을 알고 있으므로 이 인터페이스는 주로 일부 MVC 규칙을 사용자 정의하는 데 사용됩니다. 인터페이스가 Apply 메소드를 제공하는 것을 볼 수 있습니다. 이 메소드는 필요한 것을 수정하기 위해 이 객체를 사용할 수 있습니다. MVC 프레임워크 자체는 서비스가 시작될 때 이 인터페이스를 삽입하기만 하면 됩니다. 인터페이스를 약간 구성할 수 있습니다.
그런 다음 ApplicationModel 개체에 무엇이 있는지 살펴보겠습니다.
public class ApplicationModel : IPropertyModel, IFilterModel, IApiExplorerModel { public ApiExplorerModel ApiExplorer { get; set; } public IList<ControllerModel> Controllers { get; } public IList<IFilterMetadata> Filters { get; } public IDictionary<object, object> Properties { get; } }
ApiExplorer, Controllers, Filters, Properties 및 기타 속성이 있는 것을 볼 수 있습니다.
ApiExplorerModel: Api 설명 정보, 그룹 정보, 가시성 등을 포함하여 기본 MVC Api Explorer의 일부 항목을 주로 구성합니다.
ControllerModel: 주로 Comtroller의 기본 규칙과 관련되어 있으므로 나중에 하나씩 소개하지 않겠습니다.
IFilterMetadata: 주로 마커로 사용되는 빈 인터페이스입니다.
한 가지 더 말씀드리고 싶은 점은 위의 Controllers 속성이 IList
다음으로 오늘은 이 기능을 사용해 테마를 구현해 보겠습니다. 좋아요 눌러주셔서 감사합니다~ :)
글로벌 라우팅을 위한 통합 접두사 추가
더 이상 말도 안 되는 소리는 하지 마세요. 코드로 직접 이동하세요. 말하고 싶은 모든 것이 코드에 있습니다.
//定义个类RouteConvention,来实现 IApplicationModelConvention 接口 public class RouteConvention : IApplicationModelConvention { private readonly AttributeRouteModel _centralPrefix; public RouteConvention(IRouteTemplateProvider routeTemplateProvider) { _centralPrefix = new AttributeRouteModel(routeTemplateProvider); } //接口的Apply方法 public void Apply(ApplicationModel application) { //遍历所有的 Controller foreach (var controller in application.Controllers) { // 已经标记了 RouteAttribute 的 Controller var matchedSelectors = controller.Selectors.Where(x => x.AttributeRouteModel != null).ToList(); if (matchedSelectors.Any()) { foreach (var selectorModel in matchedSelectors) { // 在 当前路由上 再 添加一个 路由前缀 selectorModel.AttributeRouteModel = AttributeRouteModel.CombineAttributeRouteModel(_centralPrefix, selectorModel.AttributeRouteModel); } } // 没有标记 RouteAttribute 的 Controller var unmatchedSelectors = controller.Selectors.Where(x => x.AttributeRouteModel == null).ToList(); if (unmatchedSelectors.Any()) { foreach (var selectorModel in unmatchedSelectors) { // 添加一个 路由前缀 selectorModel.AttributeRouteModel = _centralPrefix; } } } } }
그런 다음 정의한 클래스를 사용하면 됩니다.
public static class MvcOptionsExtensions { public static void UseCentralRoutePrefix(this MvcOptions opts, IRouteTemplateProvider routeAttribute) { // 添加我们自定义 实现IApplicationModelConvention的RouteConvention opts.Conventions.Insert(0, new RouteConvention(routeAttribute)); } }
마지막으로 Startup.cs 파일에 위의 확장 메서드를 추가하면 됩니다.
public class Startup { public Startup(IHostingEnvironment env) { //... } public void ConfigureServices(IServiceCollection services) { //... services.AddMvc(opt => { // 路由参数在此处仍然是有效的,比如添加一个版本号 opt.UseCentralRoutePrefix(new RouteAttribute("api/v{version}")); }); } public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) { //... app.UseMvc(); } }
그 중 opt.UseCentralRoutePrefix는 위에서 정의한 확장 메소드로 여기에 라우팅 매개변수를 그대로 사용할 수 있으므로 예를 들어 줄 수 있습니다. 인터페이스 버전 번호와 같은 것을 지정하십시오. 그런 다음 모든 컨트롤러의 RoteAttribute에 이 접두사가 추가되어 원래 버전 번호 요구 사항을 완벽하게 해결합니다.
[Route("order")] public class OrderController : Controller { // 路由地址 : /api/v{version}/order/details/{id} [Route("details/{id}")] public string GetById(int id, int version) { //上面是可以接收到版本号的,返回 version 和 id return $"other resource: {id}, version: {version}"; } } public class ItemController : Controller { // 路由地址: /api/v{version}/item/{id} [Route("item/{id}")] public string GetById(int id, int version) { //上面是可以接收到版本号的,返回 version 和 id return $"item: {id}, version: {version}"; } }
요약
위의 굵은 단어는 모두가 이해하고 사용할 수 있기를 바랍니다. 이 예는 단지 실제 사례 아주 작은 수요 시나리오에서는 특정 프로젝트마다 다양한 정상 또는 비정상 수요가 있을 것입니다. 실제로 MVC 프레임워크에 대해 디자인을 포함하여 배울 점이 많습니다. 아이디어, 확장성 등은 천천히 이해해야 합니다. ASP.NET Core에 관심이 있으시면 저를 팔로우하세요. 학습 결과 중 일부를 블로그에 정기적으로 공유하겠습니다.
이 기사가 모든 사람에게 도움이 되기를 바랍니다. 이 사이트를 지원해 주셔서 감사합니다!
글로벌 라우팅 접두사를 구성하는 ASP.NET Core MVC와 관련된 더 많은 기사를 보려면 PHP 중국어 웹사이트를 주목하세요!