自动给 Asp.Net Core WebApi 增长 ApiVersionNeutral

自动给 Asp.Net Core WebApi 增长 ApiVersionNeutral

Intro

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

错误信息以下:前端

{
    "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-versioninggit

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

services.AddApiVersioning();

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

ApiVersion 服务注册api

IServiceCollectionExtensions

ApiVersionNeturalmvc

apiversionneutral

ApiVersionNeutralAttributeui

ApiVersionNeutralAttribute

ApiVersionActionSelectorthis

ApiVersionActionSelector

ControllerApiVentionBuilderurl

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 会常常变,可使用这种方式。

有问题欢迎联系~~

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

相关文章
相关标签/搜索