zoukankan      html  css  js  c++  java
  • Asp.net core 3.1实现路由Url根据命名空间自动生成

    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")));
    })

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

  • 相关阅读:
    LinuxMySQL主从复制原理图
    flask中间件请求流程
    flask02
    flask01
    笔记本电脑播放声音前后会有吱吱声
    筛法欧拉函数
    矩阵快速幂
    最短路 P1144 最短路计数【Dijkstra堆优化/SPFA】
    SPFA算法以及负环判断【模板】
    最短路 P1629 邮递员送信 【反向图求最短路】
  • 原文地址:https://www.cnblogs.com/caijt/p/13581432.html
Copyright © 2011-2022 走看看