武装你的WEBAPI-OData Versioning

这篇具有很好参考价值的文章主要介绍了武装你的WEBAPI-OData Versioning。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

本文属于OData系列

Intro

对外提供WEBAPI时,如果遇上了版本升级,那么控制WEBAPI的版本也是非常必要的。OData官方提供了版本控制以及管理的解决方案,我个人是实践体会是不好用,好在社区提供了对应的nuget包,与.NET主版本同步更新。

介绍

ASP.NET API Versioning是一个提供ASP.NET WEBAPI版本管理的包,支持ASP.NET、ASP.NET CORE、ASP.NET CORE ODATA,作者以前是微软的员工,现在不在微软工作了,因此原先的命名空间不能继续用了。现在这个项目已经加入.NET Foundation,作者也非常活跃。

版本管理

首先对现有的项目安装这个包:

Install-Package Asp.Versioning.OData

在Program.cs文件中修改一下:

var builder = WebApplication.CreateBuilder( args );

builder.Services.AddControllers().AddOData();
builder.Services.AddProblemDetails();
builder.Services.AddApiVersioning().AddOData(
    options =>
    {
        options.AddRouteComponents();
    } );

var app = builder.Build();

app.MapControllers();
app.Run();

然后在需要控制版本的控制器上加上[ApiVersion]修饰就可以了。

[ApiVersion( 1.0 )]
public class PeopleController : ODataController
{
    [EnableQuery]
    public IActionResult Get() => Ok( new[] { new Person() } );
}

注意,默认的版本是1.0,不过最好显式声明一下。

EDM升级

EDM根据版本不同也会有一些区别,需要分别进行配置,原来的GetEdm()模式显得有点麻烦,而EDM配置在这个库中变得非常灵活,使用的是Configuration模式。

示例代码如下:

public class DeviceInfoModelConfiguration : IModelConfiguration
{
	public void Apply(ODataModelBuilder builder, ApiVersion apiVersion, string routePrefix)
	{
		switch (apiVersion.MajorVersion)
		{
			case 1:
				builder.EntitySet<DeviceInfo>("DeviceInfoes").EntityType.HasKey(p => p.DeviceId);
				break;
			case 2:
				builder.EntitySet<DeviceInfo>("DeviceInfos").EntityType.HasKey(p => p.DeviceId).Ignore(w => w.Layout);
				break;
			default:
				break;
		};
	}
}

只需要实现IModelConfiguration接口,并在Apply函数中根据版本对实体或者DTO对象进行配置,不同版本的EDM可以不一样。

一般实践是一个实体对象一个IModelConfiguration,方便后面管理。

配置Swagger

因为有重复配置的模型,直接使用默认的Swagger会报错,这个时候需要使用到Versioned API Explorer,对Swagger拓展版本信息。

Install-Package Asp.Versioning.OData.ApiExplorer

安装Asp.Versioning.OData.ApiExplorer,重新改造一下Program.cs文件:

var builder = WebApplication.CreateBuilder( args );

builder.Services.AddControllers().AddOData();
builder.Services.AddProblemDetails();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddApiVersioning()
                .AddOData( options => options.AddRouteComponents() )
                .AddODataApiExplorer(
                     // format the version as "'v'major[.minor][-status]"
                     options => options.GroupNameFormat = "'v'VVV" );

services.AddTransient<IConfigureOptions<SwaggerGenOptions>, ConfigureSwaggerOptions>();
services.AddSwaggerGen();

var app = builder.Build();

app.UseSwagger();
app.UseSwaggerUI(
    options =>
    {
        foreach ( var description in app.DescribeApiVersions() )
        {
            var url = $"/swagger/{description.GroupName}/swagger.json";
            var name = description.GroupName.ToUpperInvariant();
            options.SwaggerEndpoint( url, name );
        }
    } );
app.MapControllers();
app.Run();

还需要一个配置的类如下:

public class ConfigureSwaggerOptions : IConfigureOptions<SwaggerGenOptions>
{
  readonly IApiVersionDescriptionProvider provider;

  public ConfigureSwaggerOptions( IApiVersionDescriptionProvider provider ) =>
    this.provider = provider;

  public void Configure( SwaggerGenOptions options )
  {
    foreach ( var description in provider.ApiVersionDescriptions )
    {
      options.SwaggerDoc(
        description.GroupName,
          new OpenApiInfo()
          {
            Title = $"Example API {description.ApiVersion}",
            Version = description.ApiVersion.ToString(),
          } );
    }
  }
}

这样,swagger界面就可以下拉选择不同版本的API了。
武装你的WEBAPI-OData Versioning

旧系统升级

WEBAPI Versioning对这个内容有介绍,其中需要注意的是,基于路径的版本匹配并不支持默认版本的特性,对于以前系统直接使用api/开头的控制器,并不能直接默认转到到api/v1(参考介绍)。为了兼容旧系统,我们只能在ASP.NET CORE的管线上想想办法:插入一个中间件,对路径进行判断,如果是api开头的,就直接转到api/v1;如果是api/v开头的,那么就直接下一步。

    public class RedirectMiddlewareForV1
    {
        private readonly RequestDelegate _next;

        public RedirectMiddlewareForV1(RequestDelegate next)
        {
            _next = next;
        }

        public async Task InvokeAsync(HttpContext context)
        {
            if (context.Request.Path.StartsWithSegments("/api") && !context.Request.Path.Value.StartsWith("/api/v"))
            {
                //千万小心,一定需要保留原来的QueryString
                var newUrl = $"{context.Request.Path.Value.Replace("/api/", "/api/v1/")}{context.Request.QueryString}";
                //permanent指示永久迁移,preserveMethod指示保留原来的谓词与body
                context.Response.Redirect(newUrl, permanent: true, preserveMethod: true);
            }
            else
            {
                await _next(context);
            }
        }


    }

然后在configure函数中注册这个中间件就可以了。

app.UseMiddleware<RedirectMiddlewareForV1>();

请注意:文章来源地址https://www.toymoban.com/news/detail-434380.html

  • context.Request.Path.StartsWithSegments函数只能匹配完整的路径词汇,/api/v2去匹配/api/v会返回false。
  • 另外需要了解HTTP 301/302/307/308之间的区别,如果需要保留原来的请求body,需要使用307/308,308是永久移动。
  • Redirect并不保留原来的QueryString,需要手动拼接。

FAQ

  1. 无法正确显示不同版本的Swagger,提示InvalidOperationException: Can't use schemaId "\(B" for type "\)A.B". The same schemaId is already used for type "$A.B"
    这个问题是由多次对同一个类型Schema生成造成的。最常见的情况是你的控制器有方法不属于OData Routing的一部分(比如直接使用HttpGet指定),这样程序在扫描的过程中会重复对对象进行生成。解决办法有两种:
  • 在EDM正确配置控制器中的Action或者Function,不要有不在OData路由的路径。(UseODataRouteDebug()可以启用$odata的路径,这样可以查看哪些路径不被OData解析)
  • 为每一个对象使用唯一名称:在配置中增加options.CustomSchemaIds(type => type.AssemblyQualifiedName)这个项目,所有的swagger对外名称会变成随机生成的值,也可以规避这个问题。
    详细分析看这个:Ignoring property on EDM causes InvalidOperationException: Can't use schemaId "\(B" for type "\)A.B". The same schemaId is already used for type "$A.B" · Issue #772 · dotnet/aspnet-api-versioning (github.com)
  1. 无法加载Swagger,提示System.MissingMethodException: Method not found: 'Microsoft.OData.ModelBuilder.Config.DefaultQuerySettings Microsoft.AspNetCore.OData.ODataOptions.get_QuerySettings()
    这个是版本问题,本人使用的OData版本在8.1.0,有一些破坏性更改,只要保持引用的OData版本<= 8.0.12就可以了。
    详细分析看这个MissingMethodException with OData v8.1.0 · Issue #980 · dotnet/aspnet-api-versioning (github.com)
  2. 找不到DescribeApiVersions()方法
    app找不到这个方法,大概率是在.NET 6的Minimal API之前的代码升级出现的,之前app是用IWebhostBuilder构建的,而现在的app是直接用过WebApplication构建得到的,含义不同,最简单的方法是改造一下,使用WebApplication重写一下Startup内容。

参考

  • API Documentation · dotnet/aspnet-api-versioning Wiki (github.com)
  • API versioning extension with ASP.NET Core OData 8 - OData (microsoft.com)

到了这里,关于武装你的WEBAPI-OData Versioning的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • OData WebAPI实践-与ABP vNext集成

    本文属于 OData 系列文章 ABP 是一个流行的 ASP. NET 开发框架,旧版的的 ABP 已经能够非常好的支持了 OData ,并提供了对应的 OData 包。 ABP vNext 是一个重新设计的,面向微服务的框架,提供了一些非常有用的特性,包括分页查询等但是它并不能原生支持 OData ,我们需要自行实现

    2024年02月04日
    浏览(38)
  • OData WebAPI实践-Non-EDM模式

    本文属于OData系列文章 前文说到了 EDM 与 OData 之间的关系,具有 EDM 的 OData 提供了强大的查询能力,但是 OData 并不必须要配置 EDM ,我们也可以使用 Non-EDM 方案。 所谓 Non-EDM ,并不是说在 OData 运行时不需要 EDM 配置了,而是由 OData 动态生成的 EDM ,进而实现 OData 功能。 配置

    2024年02月04日
    浏览(35)
  • 【Cesium创造属于你的地球】相机系统

    相机系统里面有 setView,flyTo,lookAt,viewBoundingsphere 这几种方法,以下是相关的使用方法,学起来!!! 该方法可以直接切换相机视口,从而不需要通过一个飞入的效果切换 flyTo该方法可以直接切换相机视口,从而不需要通过一个飞入的效果切换 方法使用,lookAt方法一般适用

    2024年02月06日
    浏览(46)
  • 10分钟训练属于你的AI变声器

    今天推荐一款开源AI变声器,安装过程很友好,不用经历各种麻烦的环境问题, 作者提供了windows下的安装包,一键安装启动很方便。 目前好像对显卡有要求,nvidia显卡支持,amd显卡不支持。 功能特点 使用top1检索替换输入源特征为训练集特征来杜绝音色泄漏 即便在相对较差

    2024年02月16日
    浏览(50)
  • 零基础,零成本,部署一个属于你的大模型

    前言 看了那么多chatGPT的文章,作为一名不精通算法的开发,也对大模型心痒痒。但想要部署自己的大模型,且不说没有算法相关的经验了,光是大模型占用的算力资源,手头的个人电脑其实也很难独立部署。就算使用算法压缩后的大模型,部署在个人电脑上,还要忍受极端

    2024年02月07日
    浏览(45)
  • 外汇天眼:在交易中有多少属于你的行情?

    期货、股票、外汇不同的市场有着不同的特性,就一个市场而言,也不会是每一段行情都适合你。 刚刚进入期货、股票、外汇市场的朋友都会被其巨大的财富效应所震慑:还有这样赚钱的? 而且机会比比皆是,一夜暴富不是神话呀。 他们依靠自己的欣喜、陶醉、冲动进行着

    2024年02月04日
    浏览(48)
  • 「AIGC」如何助力个人创意,打造属于你的独特时代?

    当今时代,人工智能(AI)不仅仅是科幻电影中的概念,也已经广泛应用于各行各业。其中,AI在创意领域的应用越来越受到关注。从AI生成的诗歌、绘画、音乐等作品的出现,到AI辅助创意产生的创意设计、广告营销等领域的应用,都为我们展示了AI在创意领域的无限可能。 AI生

    2024年02月11日
    浏览(55)
  • 如何真正“不花一分钱”部署一个属于你的大模型

    看了那么多chatGPT的文章,作为一名不精通算法的开发,也对大模型心痒痒。但想要部署自己的大模型,且不说没有算法相关的经验了,光是大模型占用的算力资源,手头的个人电脑其实也很难独立部署。就算使用算法压缩后的大模型,部署在个人电脑上,还要忍受极端缓慢的

    2023年04月22日
    浏览(49)
  • AIGC时代,基于云原生 MLOps 构建属于你的大模型(上)

      为了满足企业在数字化转型过程中对更新迭代生产力工具的需求,灵雀云近日推出了云原生 MLOps 解决方案,帮助企业快速落地AI技术、实现智能化应用和服务。 随着信息化技术的不断发展,企业在数字化转型的过程中,需要不断地更新迭代生产力工具,从最早的将物理世界

    2024年02月11日
    浏览(43)
  • AIGC时代,基于云原生 MLOps 构建属于你的大模型(下)

    为了满足企业在数字化转型过程中对更新迭代生产力工具的需求,灵雀云近日推出了Alauda MLOps 解决方案,帮助企业快速落地AI技术、实现智能化应用和服务。 随着ChatGPT的爆火,越来越多的人考虑使用AI来提升我们日常工作的效率和质量,通过对话协助生成需要的文本数据。无

    2024年02月12日
    浏览(48)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包