Loading

自动给 Asp.Net Core WebApi 增加 ApiVersionNeutral

自动给 Asp.Net Core WebApi 增加 ApiVersionNeutral

Intro#

新增加一个 Controller 的时候,经常忘记在 Controller 上增加 ApiVersion ,结果就导致前端使用指定的 ApiVersion 访问的时候就会失败,不支持的 Api 版本。

错误信息如下:

{
    "error": {
        "code": "UnsupportedApiVersion",
        "message": "The HTTP resource that matches the request URI 'http://localhost:5000/api/values' does not support the API version '1.2'.",
        "innerError": null
    }
}

分析源代码#

Asp.Net Core ApiVersion 源码地址:https://github.com/Microsoft/aspnet-api-versioning

使用 ApiVersion 会在注册服务的地方注册 ApiVersion 相关的服务

    services.AddApiVersioning();

找到源码 会发现注册服务的时候把 mvc 默认的 ActionSelector 替换成了 ApiVersionActionSelector,然后查看 ApiVersionActionSelector 的源码,找到了以下几处关键代码

ApiVersion 服务注册

IServiceCollectionExtensions

ApiVersionNetural

apiversionneutral

ApiVersionNeutralAttribute

ApiVersionNeutralAttribute

ApiVersionActionSelector

ApiVersionActionSelector

ControllerApiVentionBuilder

ControllerApiVentionBuilder

总结如下:

如果 Controller 的 Attribute 定义的有 ApiVersionNeutralAttribute 就会忽略 ApiVersion 的限制,即使没有使用 ApiVersion 或者使用任意一个 ApiVersion 都可以路由到 Action,都可以访问得到,也不会出现开篇提到的错误。

解决方案#

可以自己实现一个 IControllerModelConvention,去给没有定义 ApiVersion 的控制器加 ApiVersionNeutralAttribute,实现代码如下:

public class ApiControllerVersionConvention : IControllerModelConvention
{
    public void Apply(ControllerModel controller)
    {
        if (!(controller.ControllerType.IsDefined(typeof(ApiVersionAttribute)) || controller.ControllerType.IsDefined(typeof(ApiVersionNeutralAttribute))))
        {
            if (controller.Attributes is List<object>
                attributes)
            {
                attributes.Add(new ApiVersionNeutralAttribute());
            }
        }
    }
}

在注册 Mvc 服务的时候,配置 MvcOptions

services.AddMvc(options =>
    {
        options.Conventions.Add(new ApiControllerVersionConvention());
    });

启动项目,这时候再访问原来因为没有定义 ApiVersion 的控制器下的路由,这时就不会再报错了,使用任意一个 ApiVersion 也都不会有问题了,问题解决啦~~~

扩展方法#

为了方便使用,你也可以加一个扩展方法,在扩展方法里配置 MvcOptions,根据自己的需要,我觉得两种方式都 OK 的,扩展方法示例如下:

public static class MvcBuilderExtensions
{
    public static IMvcBuilder AddApiControllerVersion(this IMvcBuilder builder)
    {
        if (builder == null)
        {
            throw new ArgumentNullException(nameof(builder));
        }
        builder.Services.Configure<MvcOptions>(options=> options.Conventions.Add(new ApiControllerVersionConvention()));
        return builder;
    }
}

使用的时候可以直接在 AddMvc 之后加上扩展方法就可以了

services.AddMvc()
    .AddApiControllerVersion();

End#

问题解决,完美收官,最后还是要说一下,注意这个的使用情景,如果你要指定一个默认的 ApiVersion 有更好的方法,直接配置 ApiVersioningOptions 中的 DefaultApiVersion
就可以了

services.AddApiVersioning(options =>
    {
        options.AssumeDefaultVersionWhenUnspecified = true;
        options.DefaultApiVersion = ApiVersion.Default;
    });

如果你的 ApiVersion 不定,可能有些 Api 的 ApiVersion 会经常变,可以使用这种方式。

有问题欢迎联系~~

作者:weihanli

出处:https://www.cnblogs.com/weihanli/p/automatic-add-ApiVersionNetural.html

版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。

posted @   WeihanLi  阅读(1099)  评论(3编辑  收藏  举报
编辑推荐:
· .NET Core GC计划阶段(plan_phase)底层原理浅谈
· .NET开发智能桌面机器人:用.NET IoT库编写驱动控制两个屏幕
· 用纯.NET开发并制作一个智能桌面机器人:从.NET IoT入门开始
· 一个超经典 WinForm,WPF 卡死问题的终极反思
· ASP.NET Core - 日志记录系统(二)
阅读排行:
· 支付宝事故这事儿,凭什么又是程序员背锅?有没有可能是这样的...
· https证书一键自动续期,帮你解放90天限制
· 在线客服系统 QPS 突破 240/秒,连接数突破 4000,日请求数接近1000万次,.NET 多
· 推荐几个不错的 Linux 服务器管理工具
· C# 开发工具Visual Studio 介绍
点击右上角即可分享
微信分享提示
more_horiz
keyboard_arrow_up dark_mode palette
选择主题
menu