使用 Microsoft 的 ASP.NET API Web API 2 和 ODATA 版本控制在 api 版本之间更改 JSON 属性的大小写?
Change casing of JSON properties between api versions using Microsoft's ASP.NET API Versioning for Web API 2 and ODATA?
我正在向现有 API 引入 API 版本控制。现有的 JSON 为其 属性 名称使用 Pascal 大小写,例如"FooBar":"foo"。对于 API 的 v2,我想使用常见的驼峰式大小写,"fooBar":"foo"。我需要保留 v1 Pascal 外壳,这样它就不会影响任何已经拉动该版本 API.
的客户端
我的项目是
- ASP.NETMVC 5.2.7
- ASP.NET 网页版 API 5.2.7
- ASP.NET ODATA 7.4.0
- ASP.NET 网络 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();
}
}
阅读文档后,特别是 Versioned ODataModelBuilder 我还没有找到一种方法来根据正在构建模型的 API 版本更改外壳。我可以得到它是所有 Pascal 外壳或所有骆驼外壳,但不是 v1 Pascal 外壳和 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;
每个 v1 IModelConfiguration
类,但是一旦我构建了多个模型,它就不起作用了。
有没有办法根据模型适用的 API 版本更改 JSON 属性 命名?
使用描述的 OData 模型配置方法 here
首先将派生自 IModelConfiguration
的 class 添加到您的项目中。
像这样:
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>
我正在向现有 API 引入 API 版本控制。现有的 JSON 为其 属性 名称使用 Pascal 大小写,例如"FooBar":"foo"。对于 API 的 v2,我想使用常见的驼峰式大小写,"fooBar":"foo"。我需要保留 v1 Pascal 外壳,这样它就不会影响任何已经拉动该版本 API.
的客户端我的项目是
- ASP.NETMVC 5.2.7
- ASP.NET 网页版 API 5.2.7
- ASP.NET ODATA 7.4.0
- ASP.NET 网络 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();
}
}
阅读文档后,特别是 Versioned ODataModelBuilder 我还没有找到一种方法来根据正在构建模型的 API 版本更改外壳。我可以得到它是所有 Pascal 外壳或所有骆驼外壳,但不是 v1 Pascal 外壳和 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;
每个 v1 IModelConfiguration
类,但是一旦我构建了多个模型,它就不起作用了。
有没有办法根据模型适用的 API 版本更改 JSON 属性 命名?
使用描述的 OData 模型配置方法 here
首先将派生自 IModelConfiguration
的 class 添加到您的项目中。
像这样:
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>