自动给 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 服务注册

ApiVersionNetural

ApiVersionNeutralAttribute

ApiVersionActionSelector

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

有问题欢迎联系~~

自动给 Asp.Net Core WebApi 增加 ApiVersionNeutral的更多相关文章

  1. ionic + asp.net core webapi + keycloak实现前后端用户认证和自动生成客户端代码

    概述 本文使用ionic/angular开发网页前台,asp.net core webapi开发restful service,使用keycloak保护前台页面和后台服务,并且利用open api自动 ...

  2. ASP.NET Core WebApi使用Swagger生成api说明文档看这篇就够了

    引言 在使用asp.net core 进行api开发完成后,书写api说明文档对于程序员来说想必是件很痛苦的事情吧,但文档又必须写,而且文档的格式如果没有具体要求的话,最终完成的文档则完全取决于开发者 ...

  3. ASP.NET Core WebApi使用Swagger生成api

    引言 在使用asp.net core 进行api开发完成后,书写api说明文档对于程序员来说想必是件很痛苦的事情吧,但文档又必须写,而且文档的格式如果没有具体要求的话,最终完成的文档则完全取决于开发者 ...

  4. ASP.NET Core WebApi使用Swagger生成api说明文档

    1. Swagger是什么? Swagger 是一个规范和完整的框架,用于生成.描述.调用和可视化 RESTful 风格的 Web 服务.总体目标是使客户端和文件系统作为服务器以同样的速度来更新.文件 ...

  5. Asp.Net Core WebAPI入门整理(四)参数获取

    一.总结整理,本实例对应.Net Core 2.0版本 1.在.Net Core WebAPI 中对于参数的获取及自动赋值,沿用了Asp.Net  MVC的有点,既可以单个指定多个参数,右可以指定Mo ...

  6. 【转】ASP.NET Core WebApi使用Swagger生成api说明文档看这篇就够了

    原文链接:https://www.cnblogs.com/yilezhu/p/9241261.html 引言 在使用asp.net core 进行api开发完成后,书写api说明文档对于程序员来说想必 ...

  7. 使用 Swagger 自动生成 ASP.NET Core Web API 的文档、在线帮助测试文档(ASP.NET Core Web API 自动生成文档)

    对于开发人员来说,构建一个消费应用程序时去了解各种各样的 API 是一个巨大的挑战.在你的 Web API 项目中使用 Swagger 的 .NET Core 封装 Swashbuckle 可以帮助你 ...

  8. ASP.NET Core WebAPI 开发-新建WebAPI项目

    ASP.NET Core WebAPI 开发-新建WebAPI项目, ASP.NET Core 1.0 RC2 即将发布,我们现在来学习一下 ASP.NET Core WebAPI开发. 网上已经有泄 ...

  9. Asp.net Core WebApi 使用Swagger做帮助文档,并且自定义Swagger的UI

    WebApi写好之后,在线帮助文档以及能够在线调试的工具是专业化的表现,而Swagger毫无疑问是做Docs的最佳工具,自动生成每个Controller的接口说明,自动将参数解析成json,并且能够在 ...

随机推荐

  1. [Swift]LeetCode23. 合并K个排序链表 | Merge k Sorted Lists

    Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity. E ...

  2. [Swift]LeetCode255.验证二叉搜索树的先序序列 $ Verify Preorder Sequence in Binary Search Tree

    Given an array of numbers, verify whether it is the correct preorder traversal sequence of a binary ...

  3. [Swift]LeetCode917. 仅仅反转字母 | Reverse Only Letters

    Given a string S, return the "reversed" string where all characters that are not a letter  ...

  4. Kubernetes系列之监控Metres-server实战篇

    本次系列使用的所需部署包版本都使用的目前最新的或最新稳定版,安装包地址请到公众号内回复[K8s实战]获取 介绍 从 Kubernetes 1.8 开始,Kubernetes 通过 Metrics AP ...

  5. python编译、运行、反编译pyc文件

    为了加密 .py 文件,以前一般使用打包成 exe ,但是最近发现可以将其编译成二进制文件 pyc ,虽然反编译难度不大,但是也需要一些水平 编译生成 pyc: 单个文件 代码: import py_ ...

  6. 学习-xlsxwriter模块

    Xlsx是python用来构造xlsx文件的模块,可以向excel2007+中写text,numbers,formulas 公式以及hyperlinks超链接. 可以完成xlsx文件的自动化构造,包括 ...

  7. solr之环境配置一

    安装Java JDK solr运行需要java serverlet 容器,默认使用jetty,或者tomcat,jboss等等. 下载一个jdk,我的jdk是jdk1.7.0_65. 安装JDK的步骤 ...

  8. Spring Cloud中的负载均衡策略

    在上篇博客(Spring Cloud中负载均衡器概览)中,我们大致的了解了一下Spring Cloud中有哪些负载均衡器,但是对于负载均衡策略我们并没有去详细了解,我们只是知道在BaseLoadBal ...

  9. 知其所以然~redis的原子性

    原子性 原子性是数据库的事务中的特性.在数据库事务的情景下,原子性指的是:一个事务(transaction)中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节. 对于Redis而言,命 ...

  10. 实现一个简单的WebSocket聊天室

    WebSocket 简介 WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议. WebSocket 使得客户端和服务器之间的数据交换变得更加简单,允许服务端主 ...