Asp.net core 3.1實現路由Url根據命名空間自動生成


注:下面涉及的代碼文件可查看我的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")));
})

 

最后你只要這么使用就行了,又省了不少代碼,哈哈哈

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM