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

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

  • 相关阅读:
    使用 Promise.all 同时发起多个请求
    vite 开发 Cesium 程序最佳配置实践
    【linux学习】使用grep命令获取过滤的数据作为下个命令的入参
    记一次k8s depolyment失败处理
    powerdesigner导出excel数据字典
    vue 时间格式
    ASP.NET MVC4 跨域配置
    Win10系统中切换虚拟桌面的快捷键如何设置
    不顾一切最简NHinbernate配置并读写数据库
    Windows time_wait过多解决办法
  • 原文地址:https://www.cnblogs.com/caijt/p/13581432.html
Copyright © 2020-2023  润新知