0

我正在向现有 API 引入 API 版本控制。现有的 JSON 对其属性名称使用 Pascal 大小写,例如“FooBar”:“foo”。对于 API 的 v2,我想使用常见的驼峰式大小写,“fooBar”:“foo”。我需要保留 v1 Pascal 大小写,这样它就不会影响任何已经在提取该 API 版本的客户端。

我的项目是

  • ASP.NET MVC 5.2.7
  • ASP.NET 网页 API 5.2.7
  • ASP.NET ODATA 7.4.0
  • ASP.NET WEB API 版本控制 4.0.0

我的配置如下

public static class WebApiConfig
{
    public static void Register(HttpConfiguration configuration)
    {
        configuration.AddApiVersioning(options => options.ReportApiVersions = true);

        var modelBuilder = new VersionedODataModelBuilder(configuration);

        AppDomain.CurrentDomain.GetAssemblies()
            .SelectMany(x => x.GetTypes())
            .Where(x => typeof(IModelConfiguration).IsAssignableFrom(x) && !x.IsInterface && !x.IsAbstract)
            .ForEach(t => modelBuilder.ModelConfigurations.Add((IModelConfiguration)Activator.CreateInstance(t)));

        var models = modelBuilder.GetEdmModels();

        configuration.MapVersionedODataRoutes("odata-bypath", "api/v{apiVersion}", models, builder =>
        {
            builder.AddService<IODataPathHandler>(Singleton, sp => new DefaultODataPathHandler { UrlKeyDelimiter = Parentheses });
            builder.AddService<ODataUriResolver>(Singleton, sp => new UnqualifiedCallAndEnumPrefixFreeResolver { EnableCaseInsensitive = true });
        });

        configuration.Count().Filter().OrderBy().Expand().Select().MaxTop(null);

        configuration.MapHttpAttributeRoutes();
    }
}

在阅读了文档,特别是版本化的ODataModelBuilder 之后,我还没有找到一种方法来根据构建模型的 API 版本来更改大小写。我可以让它成为所有帕斯卡套管或所有骆驼套管,但不是 v1 帕斯卡套管和 v2 骆驼套管。

调整上述配置

var modelBuilder = new VersionedODataModelBuilder( configuration )
{
    ModelBuilderFactory = () => new ODataConventionModelBuilder().EnableLowerCamelCase()
};

将使用驼峰式外壳(是的,我知道显式调用是不必要的,因为它是默认设置)。然后我构建了自己的扩展方法ODataConventialModelBuilder().EnablePascalCase(),该方法模仿EnableLowerCamelCase()了让 Pascal 套管工作的方法。

var modelBuilder = new VersionedODataModelBuilder( configuration )
{
    ModelBuilderFactory = () => new ODataConventionModelBuilder().EnablePascalCase()
};

但是,我永远无法知道我正在为哪个版本的 API 构建模型。

有一次,我以为我可以用它OnModelCreating来添加

((ODataConventionModelBuilder) builder).OnModelCreating += new PascalCaser().ApplyCase;

到每个 v1IModelConfiguration类,但是一旦我构建了多个模型,它就不起作用了。

有没有办法根据模型的 API 版本更改 JSON 属性命名?

4

1 回答 1

2

使用此处IModelConfiguration描述的 OData 模型配置方法,首先将派生自您的项目 添加一个类。

像这样的东西:

public class VersionedModelConfiguration : IModelConfiguration
{
    private void ConfigureV1(ODataModelBuilder builder)
    {
        builder.EntitySet<Product>("Products");
    }

    private void ConfigureV2(ODataModelBuilder builder)
    {
        if (builder.GetType().Equals(typeof(ODataConventionModelBuilder)))
        {
            ((ODataConventionModelBuilder)builder).EnableLowerCamelCase();
        }
        builder.EntitySet<Product>("Products");
    }

    public void Apply(ODataModelBuilder builder, ApiVersion apiVersion)
    {

        switch (apiVersion.MajorVersion)
        {
            case 1:
                ConfigureV1(builder);
                break;
            case 2:
                ConfigureV2(builder);
                break;
            default:
                ConfigureV1(builder);
                break;
        }
    }
}

然后在Register方法中:

// ...
var modelBuilder = new VersionedODataModelBuilder(configuration)
{
    ModelBuilderFactory = () => new ODataConventionModelBuilder(),
    ModelConfigurations = { new VersionedModelConfiguration() }
};

var models = modelBuilder.GetEdmModels();
// ...

不要试图离开这条线ModelBuilderFactory = () => new ODataConventionModelBuilder()

/api/v1/$metadata

<?xml version="1.0" encoding="UTF-8"?>
<edmx:Edmx xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx" Version="4.0">
   <edmx:DataServices>
      <Schema xmlns="http://docs.oasis-open.org/odata/ns/edm" Namespace="NS.Models">
         <EntityType Name="Product">
            <Key>
               <PropertyRef Name="Id" />
            </Key>
            <Property Name="Id" Type="Edm.Int32" Nullable="false" />
            <Property Name="Name" Type="Edm.String" />
         </EntityType>
      </Schema>
      <Schema xmlns="http://docs.oasis-open.org/odata/ns/edm" Namespace="Default">
         <EntityContainer Name="Container">
            <EntitySet Name="Products" EntityType="NS.Models.Product" />
         </EntityContainer>
      </Schema>
   </edmx:DataServices>
</edmx:Edmx>

/api/v2/$metadata

<?xml version="1.0" encoding="UTF-8"?>
<edmx:Edmx xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx" Version="4.0">
   <edmx:DataServices>
      <Schema xmlns="http://docs.oasis-open.org/odata/ns/edm" Namespace="NS.Models">
         <EntityType Name="Product">
            <Key>
               <PropertyRef Name="id" />
            </Key>
            <Property Name="id" Type="Edm.Int32" Nullable="false" />
            <Property Name="name" Type="Edm.String" />
         </EntityType>
      </Schema>
      <Schema xmlns="http://docs.oasis-open.org/odata/ns/edm" Namespace="Default">
         <EntityContainer Name="Container">
            <EntitySet Name="Products" EntityType="NS.Models.Product" />
         </EntityContainer>
      </Schema>
   </edmx:DataServices>
</edmx:Edmx>
于 2020-06-01T13:50:56.683 回答