注:下面涉及的代碼文件可查看我的LessSharp框架Github
按Asp.net core
默認的接口寫法,每個接口控制器都得繼承自ControllerBase
類,還需具有ApiController
特性及Route
特性,Route
特性上還得手動寫上路由規則。如下圖所示
我覺得挺麻煩的,可能我比較懶,其實我的寫的大多數的接口路徑都是按一定規則的,一般是以命名空間Controllers.后面的命名空間做為路徑前綴,然后以[controller]/[action]
路由規則進行匹配。
例如命名空間LessSharp.WebApi.Controllers.Sys
下面的UserController
控制器下面的Save
接口,那么根據命名空間的后面Sys,對應的接口路徑值就為/Sys/User/Save
那么我希望默認情況下,可以以我上面的規則自動生成路徑,如果有特殊情況的話,那我加個Route
特性,手動寫上我的路由規則,框架就優先按我Route
特性定義的路由路徑值。
我實現的方法主要使用了Asp.net Core
提供的控制器模型約定ControllerModelConvention
功能,再借助ApiConventionController
控制器基類,路由生成只會在系統啟動進行生成,所以對系統性能無任何影響。
以下是ApiConventionController
的代碼,這個類其實作用不大,主要起個標記作用,只要繼承這個控制器基類的控制器就說明要使用以上的Url生成規則。
namespace LessSharp.WebApi.Controllers { /// <summary> /// 繼承此控制器后,會自動根據命名空間結構修改Route增加前綴 /// 例如LessSharp.WebApi.Controllers.Sys.A.B命名空間下的UserController控制器,就會生成Sys/A/B/User這樣的路由 /// 如果派生控制器有自定義Route特性的話,就不會自動增加前綴 /// </summary> [Route("[controller]/[action]")] [ApiController] public abstract class AutoRouteControllerBase : ControllerBase { }
以下是這個Url生成功能最核心的類AutoRouteControllerModelConvention,它實現IControllerModelConvention接口
namespace LessSharp.WebApi.Conventions { public class AutoRouteControllerModelConvention : IControllerModelConvention { /// <summary> /// 路徑前綴 /// </summary> private readonly string _prefix; public AutoRouteControllerModelConvention (string prefix) { _prefix = prefix; } public void Apply(ControllerModel controller) { //判斷是否是ApiConventionController的派生控制器 if (controller.ControllerType.BaseType != typeof(AutoRouteControllerBase)) { return; } //判斷是否有自定義Route特性 if (controller.ControllerType.GetCustomAttributes(typeof(RouteAttribute), false).Length > 0) { return; } string controllerNamespace = controller.ControllerType.Namespace; string temp = "Controllers."; int index = controllerNamespace.IndexOf(temp); string prefix = _prefix.Trim('/'); if (index > -1) { prefix += "/" + controllerNamespace.Substring(index + temp.Length); } if (string.IsNullOrEmpty(prefix)) { return; } if (!string.IsNullOrEmpty(prefix)) { prefix = prefix.Replace(".", "/"); } foreach (var selector in controller.Selectors.Where(s => s.AttributeRouteModel != null)) { selector.AttributeRouteModel.Template = prefix + "/" + selector.AttributeRouteModel.Template; } } } }
最后在Startup的ConfigureServices方法里添加這個約定。我這里還添加了根據配置文件的RoutePrefix值統一添加Url前綴的功能
services.AddControllers(o => {//添加約定器,對ApiConventionController的派生類添加路由前綴 o.Conventions.Add(new AutoRouteControllerModelConvention(Configuration.GetValue<string>("RoutePrefix"))); })
最后你只要這么使用就行了,又省了不少代碼,哈哈哈