OData – API Versioning

前言

先看这 3 篇 

ASP.NET Core – Web API Versioning

ASP.NET Core – Swagger OpenAPI (Swashbuckle)

ASP.NET Core – Swagger API Versioning

OData versioning 和普通 Web API versioning 大同小异,最大的区别是 EDM 是否换了。

 

主要参考

Docs – aspnet-api-versioning example(新的)

API versioning extension with ASP.NET Core OData 8(旧的)

 

Step by Step

安装 package 

dotnet add package Microsoft.AspNetCore.OData
dotnet add package Asp.Versioning.Mvc
dotnet add package Asp.Versioning.OData

Product Model

namespace ODataVersioning;

public class Product1
{
  public int Id { get; set; }
  public string Name { get; set; } = "";
}

public class Product2
{
  public int Id { get; set; }
  public string Name { get; set; } = "";
  public int Age { get; set; }
}

有 2 个版本的 Product。

Product ModelConfiguration

public class ProductModelConfiguration : IModelConfiguration
{
  private static void ConfigureV1(ODataModelBuilder builder)
  {
    builder.EntitySet<Product1>("products");
  }

  private static void ConfigureV2(ODataModelBuilder builder)
  {
    builder.EntitySet<Product2>("products");
  }

  public void Apply(ODataModelBuilder builder, ApiVersion apiVersion, string? routePrefix)
  {
    switch (apiVersion.MajorVersion)
    {
      case 1:
        ConfigureV1(builder);
        break;
      case 2:
        ConfigureV2(builder);
        break;
      default:
        ConfigureV2(builder);
        break;
    }
  }
}

ModelConfiguration 是让我们声明不同版本使用不同 EDM model 的地方。IModelConfiguration 可以有很多个,通常为了方便管理,一个 Entity 会有一个 IModelConfiguration。

Program.cs

首先是基本的 OData 配置,我们不在这里设置 EMD 了哦。

builder.Services.AddControllers().AddOData(
  options => options.Select().Filter().OrderBy().Expand().Count().SetMaxTop(null)
);

setup API versioning

var apiVersioningBuilder = builder.Services.AddApiVersioning(options =>
{
  options.ReportApiVersions = true;
  options.DefaultApiVersion = new ApiVersion(1, 0);
  options.AssumeDefaultVersionWhenUnspecified = true;
})
.AddMvc().AddOData(options => options.AddRouteComponents("api/v{version:apiVersion}"));

主要是加了 .AddOData 这一句,它会去查找所有的 IModelConfiguration 做 setup。

.AddMvc 不是必须的,因为我的 Controller 是 Web API 混搭 OData(odata 负责 get 而已)所以才需要。

注:Swagger 暂时不要放哦。

Product Controller

[ODataAttributeRouting]
[ApiController]
[ApiVersion("1.0", Deprecated = true)]
[ApiVersion("2.0")]
[Route("api/v{version:apiVersion}")]
public class ProductController : ControllerBase
{
  [EnableQuery]
  [HttpGet("products"), MapToApiVersion("1.0")]
  public IEnumerable<Product1> GetProducts_v1()
  {
    return _products_v1;
  }

  [EnableQuery]
  [HttpGet("products"), MapToApiVersion("2.0")]
  public IEnumerable<Product2> GetProducts_v2()
  {
    return _products_v2;
  }

  [EnableQuery]
  [HttpGet("products/{id}"), MapToApiVersion("2.0")]
  public ActionResult<Product2> GetProduct(int id)
  {
    return Ok(SingleResult.Create(_products_v2.AsQueryable().Where(e => e.Id == id)));
  }

  [ODataIgnored]
  [HttpPost("products"), MapToApiVersion("2.0")]
  public ActionResult CreateProduct()
  {
    return CreatedAtAction(nameof(GetProduct), new { id = 3 }, new Product2 { Id = 3, Name = "p3", Age = 3 });
  }

  public static readonly List<Product1> _products_v1 = [
    new () { Id = 1, Name = "p1" },
    new () { Id = 2, Name = "p2" }
  ];

  public static readonly List<Product2> _products_v2 = [
    new () { Id = 1, Name = "p1", Age = 1 },
    new () { Id = 2, Name = "p2", Age = 2 }
  ];
}

和 API Versioning 没有太多的区别。唯一需要注意的是,Controller 一定要有 [ODataAttributeRouting],不然某些情况下 response 会变成普通的 Web API 而不是 OData。

具体细节和原因我懒得去查,我猜是 Bug,总之顺风水使用 [ODataAttributeRouting] + [ODataIgnored] 就对了。

测试

http://localhost:5298/api/v2.0/products
http://localhost:5298/api/v2.0/products/1
POST http://localhost:5298/api/v2.0/products

 

Swagger

OData 的 swagger 和普通 Web API 的 Swagger 配置差不多。查看这篇 ASP.NET Core – Swagger API Versioning

唯一的区别是需要安装

dotnet add package Asp.Versioning.OData.ApiExplorer

还有

就可以了。

 

posted @ 2021-10-25 18:50  兴杰  阅读(86)  评论(0编辑  收藏  举报