自动给 Asp.Net Core Api 增加 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    }
}

因此希望可以在没有设置 ApiVersion 的时候也可以响应前端特定版本号的请求,而微软提供了 ApiVersionNeutral 可以忽略版本,任意版本号均可访问,于是就想自动给没有设置 ApiVersion 的 Controller 自动设置 ApiVersionNeutral,下面就通过分析源码来实现自动设置 ApiVersionNeutral

分析源代码

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();

实现源码

源码很简单,主要是看源码分析的过程,源码地址:https://github.com/WeihanLi/AspNetCorePlayground/blob/master/TestWebApplication/Conventions/ApiControllerConvention.cs

现在 .net core 是开源的,有许多问题都可以通过查看源码得到答案,有问题多 Google ,多看 Github 上的 issue,多看源码,相信大部分问题都可以解决了。

End

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

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

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

有问题欢迎联系~~

自动给 Asp.Net Core Api 增加 ApiVersionNeutral相关推荐

  1. AutoWrapper:通过有意义的响应来美化您的ASP.NET Core API

    目录 介绍 默认的ASP.NET Core API响应 AutoWrapper.Core的救援 主要特点: TL,DR 给我看代码 定义自己的自定义消息 定义自己的Api异常 选项 版本1.0.0 1 ...

  2. 基于ASP.NET Core api 的服务器事件发送

    现如今程序员对Web API的调用已经是轻车熟路.但是传统的api调用都是拉模式,也就是主动发起请求去调用一个api. 但是程序员往往对另一种很有用的模式很陌生,即推模式. 拉模式 - 主动调用并获取 ...

  3. 客户要求ASP.NET Core API返回特定格式,怎么办?

    当ASP.NET Core API提供给到外部系统使用时,在某些情况下,可能需要根据这些外部系统的要求来格式化数据. 比如,客户就要求API的返回值属性名必须是PascalCase(如UserName ...

  4. 小范笔记:ASP.NET Core API 基础知识与Axios前端提交数据

    跟同事合作前后端分离项目,自己对 WebApi 的很多知识不够全,虽说不必要学全栈,可是也要了解基础知识,才能合理设计接口.API,方便与前端交接. 晚上回到宿舍后,对 WebApi 的知识查漏补缺, ...

  5. iactionresult 图片_从显式类型的ASP.NET Core API控制器(不是IActionResult)返回404

    在ASP.NET Core 2.1中使用return null;解决了此问题: public ActionResult Get(int id) { Thing thing = GetThingFrom ...

  6. 客户要求ASP.NET Core API返回特定格式,怎么办?(续2)

    前言 前2次,我们都是假设客户需要返回不同的字符串格式. 但是,有可能客户要求的返回是非本文格式,比如文件流. 怎么办? 思路 前提,当然还是使用同一API接口,不影响现有使用方式. 虽然ASP.NE ...

  7. 客户要求ASP.NET Core API返回特定格式,怎么办?(续)

    前言 上次,我们用 客户就要求API的返回值属性名必须是PascalCase(如UserName),但是这些API需要同时提供给内部系统使用,默认都是CamelCase(如userName). 其实, ...

  8. ASP.NET Core API 版本控制

    几天前,我和我的朋友们使用 ASP.NET Core 开发了一个API ,使用的是GET方式,将一些数据返回到客户端 APP.我们在前端进行了分页,意味着我们将所有数据发送给客户端,然后进行一些dat ...

  9. 实现BUG自动检测 - ASP.NET Core依赖注入

    我个人比较懒,能自动做的事绝不手动做,最近在用ASP.NET Core写一个项目,过程中会积累一些方便的工具类或框架,分享出来欢迎大家点评. 如果以后有时间的话,我打算写一个系列的[实现BUG自动检测 ...

最新文章

  1. No.3 clojure 调用 Java
  2. FTP服务器之vsftp
  3. c语言javapython哪个好-C#、C++、Java、Python 选择哪个好?
  4. java在所选路径中找到分号,classpath
  5. 《社交网站界面设计(原书第2版)》——2.11 提问
  6. html选择按钮select,Html选择使用select来改变一个按钮的链接使用Javascript
  7. plotting and saving over line in paraView
  8. java写小游戏代码可复制
  9. IR2130与MOSFET驱动电路分析
  10. 极品五笔输入法2009_考场指南!2020年注会机考计算器使用指南及输入法切换
  11. date time 分开存储如何合并_关于TDateTime的TDate与TTime合并的问题 | 菲菲的家
  12. 无需root对oppo内置软件卸载方法
  13. socat 端口转发
  14. miRNA数据库篇——miRDB:软件预测的哺乳动物miRNA靶基因数据库(假阳性较高)
  15. 【云计算基础服务-Nginx WEB服务器---原理及简介详解】
  16. VS code 左侧菜单栏不见了/只能打开一个编辑页面
  17. java中的while和do while循环语句
  18. VLR via C# 泛型
  19. 淘宝天猫重组换血,原核心高管离职;Google Bard 大更新,数学和逻辑能力有所提升;K8s 1.27 发布|极客头条
  20. 驻定相位原理在求解频域表达式中的应用

热门文章

  1. FireFox与IE的兼容
  2. 如何将世界时钟和时区小部件添加到您的iPhone
  3. 禁用磁盘检查_如何在Windows上禁用“磁盘空间不足”警告
  4. wii拆机_设置防砖保护以保护和增强Wii
  5. MariaDB基础(二)
  6. 100亿人口会挨饿吗?人工智能迎击全球粮食问题
  7. 曾鸣:未来十年,将确定智能商业的格局|干货
  8. Jenkins入门系列之——03PDF文档下载
  9. Centos7 安装gitlab 8.7.5
  10. C++学习之路: 线程封装(基于对象编程)