.Net6 web API (全局路由扩展和新版本控制代码)

前沿

全局路由扩展

如果在开发中,需要把API的请求地址来一个修改,按照目前的做法只能一个一个的修改;

新建个路由文件夹

然后在新建个:

RouteConvention.cs 文件

 

复制代码
using System;
using System.Linq;
using Microsoft.AspNetCore.Mvc.ApplicationModels;
using Microsoft.AspNetCore.Mvc.Routing;

namespace yanfanNet6WebApi.Utility.Route
{
    public class RouteConvention: IApplicationModelConvention
    {
        /// 定义一个路由前缀变量
        private readonly AttributeRouteModel _centralPrefix;
        /// <summary>
        /// 调用时传入指定的路由前缀
        /// </summary>
        /// <param name="routeTemplateProvider"></param>
        public RouteConvention(IRouteTemplateProvider routeTemplateProvider)
        {
            _centralPrefix = new AttributeRouteModel(routeTemplateProvider);
        }


        /// <summary>
        /// 接口的Apply的方法,在这个方法中根据情况来添加API 路由前缀
        /// </summary>
        /// <param name="application"></param>
        /// <exception cref="NotImplementedException"></exception>
        public void Apply(ApplicationModel application)
        {
            //遍历所有的Controller
            foreach (var controller in application.Controllers)
            {
                //l、已经标记了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);
                    }
                }

                //2、没有标记RouteAttribute的Controller
                var unmatchedSelectors = controller.Selectors.Where(x => x.AttributeRouteModel
                == null).ToList();
                if (unmatchedSelectors.Any())
                {
                    foreach (var selectorModel in unmatchedSelectors)
                    {
                        //添加一个路由前缀
                        selectorModel.AttributeRouteModel = _centralPrefix;
                    }
                }

            }
            //throw new NotImplementedException();
        }

    }
}
复制代码

这就是全局理由的方法

然后在Program.cs 中方法 应用这个方法

 

        .AddControllers(option => {
            // 全局路由加上 api/ 这个
            option.Conventions.Insert(0, new RouteConvention(new RouteAttribute("api/")));
            })

解释下: 

option.Conventions.Insert 插入 这个必须从0开始 计算 或者最后一个 不然会报错

然后运行 你会看到

 所以的路由请求前面都加上了api 

 

新版本控制管理:

Nuget:
Microsoft.AspNetcore.Mvc.Versioning
Microsoft.AspNetcore.Mvc.Versioning.ApiExplorer

 

 

 搜索这个 

Microsoft.AspNetcore.Mvc.Versioning

然后成功添加

 

看到新的更新依赖 

 

然后更改代码

复制代码
using System;
using Microsoft.AspNetCore.Mvc.ApiExplorer;
using Microsoft.OpenApi.Models;

namespace yanfanNet6WebApi.Utility.Swagger
{
    /// <summary>
    /// swagger 扩展独立一个独立封装
    /// </summary>
    public static class SwaggerExtension
    {
        /// <summary>
        /// 扩展方法
        /// </summary>
        /// <param name="builder"></param>
        public static void AddSwaggerGenExt(this WebApplicationBuilder builder)
        {
            builder.Services.AddEndpointsApiExplorer();
            builder.Services.AddSwaggerGen(option => {

                #region 自定义 支持API分版本展示
                {
                    // 根据 API 版本信息生成 API 文档
                    var provider = builder.Services.BuildServiceProvider
                    ().GetRequiredService<IApiVersionDescriptionProvider>();

                    foreach (var description in provider.ApiVersionDescriptions)
                    {
                        option.SwaggerDoc(description.GroupName, new OpenApiInfo
                        {
                            Contact = new OpenApiContact
                            {
                                Name = "yanfan",
                                Email = "1784498@163.com"
                            },
                            Description = "yanfan.NET6WebAPI文档",
                            Title = "yanfan,NET6WebAPI文档",
                            Version = description.ApiVersion.ToString()
                        });
                    }
                    //在Swagger文档显示的API地址中将版本信息参数替换为实际的版本号
                    option.DocInclusionPredicate((version, apiDescription) =>
                    {
                        if (!version.Equals(apiDescription.GroupName))
                            return false;

                        IEnumerable<string>? values = apiDescription!.RelativePath
                            .Split('/')
                            .Select(v => v.Replace("v(version)", apiDescription.GroupName));

                        apiDescription.RelativePath = string.Join("/", values);
                        return true;
                     });
                    //参数使用驼峰命名方式
                    option.DescribeAllParametersInCamelCase();
                    //取消API文档需要输入版本信息
                    //option.OperationFilter<RemoveVersionFromParameter>();
                }
                #endregion

                #region 版本配置
                //typeof(ApiVersions).GetEnumNames().ToList().ForEach(version =>
                //{
                //    option.SwaggerDoc(version, new OpenApiInfo()
                //    {
                //        Title = $"{version}:我的CoreWebApi~",
                //        Version = version,
                //        Description = $"coreWebApi版本{version}"
                //    });
                //});
                #endregion

                #region 支持token产值
                {
                    option.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme()
                    {
                        Description = "请输入token,格式为Bearer xxxxxxxx(注意中间必须有空格)",
                        Name = "Authorization",
                        In = ParameterLocation.Header,
                        Type = SecuritySchemeType.ApiKey,
                        BearerFormat = "JWT",
                        Scheme = "Bearer"
                    });
                }
                #endregion

                #region 文件按钮上传
                //{
                //    option.OperationFilter<IOperationFilter>();
                //}
                #endregion
            });
        }

        /// <summary>
        /// swagger 中间件配置应用
        /// </summary>
        /// <param name="app"></param>
        public static void UseSwaggerExt(this WebApplication app)
        {
            app.UseSwagger();
            app.UseSwaggerUI(option =>
            {
                #region MYRegion
                //foreach (string version in typeof(ApiVersions).GetEnumNames())
                //{
                //    option.SwaggerEndpoint($"/swagger/{version}/swagger.json", $"API版本:{version}");
                //}
                #endregion

                #region 调用第三方程序包支持版本控制
                {
                    var provider =
                        app.Services.GetRequiredService<IApiVersionDescriptionProvider>();
                    //默认加载最新版本的API文档
                    foreach (var description in provider.ApiVersionDescriptions.Reverse())
                    {
                        option.SwaggerEndpoint($"/swagger/{description.GroupName}/swagger.json",
                            $"yanfan API {description.GroupName.ToUpperInvariant()}");
                    }
                }
                #endregion
            });
        }
    }
}
View Code
复制代码

再 你的Program.cs  注释 版本的代码

 

 然后添加版本新的控制

复制代码
        #region 添加API版本控制的支持
        {
            // 添加API版本支持
            builder.Services.AddApiVersioning(o =>
            {
                //是否在响应的header信息中返回API版本信息
                o.ReportApiVersions = true;
                //默认的API版本
                o.DefaultApiVersion = new ApiVersion(1, 0);
                //未指定API版本时,设置API版本为默认的版本
                o.AssumeDefaultVersionWhenUnspecified = true;
            });

            //配置API版本信息
            builder.Services.AddVersionedApiExplorer(option =>
            {
                //api版本分组名称
                option.GroupNameFormat = "'v'VVVV";
                //未指定API版本时,设置API版本为默认的版本
                option.AssumeDefaultVersionWhenUnspecified = true;
            });
        }
        #endregion




        // 关于swagger 完整配置
        //SwaggerExtension.AddSwaggerGenExt();
        builder.AddSwaggerGenExt();
复制代码

然后再新建页面2个版本的文件

 

复制代码
using Microsoft.AspNetCore.Mvc;
using yanfanNet6WebApi.Utility.Swagger;

namespace yanfanNet6WebApi.Controllers;

/// <summary>
/// 文件资源
/// </summary>
/// 
[ApiController]
[ApiVersion("1.0")]
[Route("[controller]")]
//[ApiExplorerSettings(IgnoreApi = false, GroupName = nameof(ApiVersions.V3))]
public class VersionController : ControllerBase
{

    private readonly ILogger<VersionController> _logger;

    public VersionController(ILogger<VersionController> logger)
    {
        _logger = logger;
    }

    /// <summary>
    /// 获取版本号
    /// </summary>
    /// <returns></returns>
    [HttpGet]
    public User GetVersion()
    {
        return new()
        {
            Id = 234,
            Name = " 版本号1.0-来着yanfan",
            Age = 18
        };
    }

}
复制代码

V2 

里面就是这个不同

[ApiVersion("2.0")]

 

然后再运行就看到了新的版本

 

 

 

OK。 每天鼓励自己一下 

posted @   -鹿-  阅读(217)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
点击右上角即可分享
微信分享提示