Saya memperkenalkan versi API ke API yang ada. JSON yang ada menggunakan casing Pascal untuk nama propertinya mis. "FooBar": "foo". Untuk API v2, saya ingin menggunakan casing unta yang umum, "fooBar": "foo". Saya perlu menyimpan casing Pascal v1 sehingga tidak memengaruhi klien mana pun yang sudah menarik versi API itu.

Proyek saya adalah

  • ASP.NET MVC 5.2.7
  • ASP.NET WEB API 5.2.7
  • ASP.NET ODATA 7.4.0
  • ASP.NET WEB API Versi 4.0.0

Konfigurasi saya adalah sebagai berikut

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

Setelah membaca dokumen dan khususnya ODataModelBuilder Berversi saya belum menemukan cara untuk mengubah casing berdasarkan versi API yang digunakan untuk model tersebut. Saya bisa mendapatkannya menjadi semua casing Pascal atau semua casing unta, tetapi tidak casing v1 Pascal dan casing unta v2.

Menyesuaikan konfigurasi di atas

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

Akan menggunakan casing unta (ya saya tahu panggilan eksplisit tidak diperlukan karena ini adalah default). Kemudian saya membangun metode ekstensi saya sendiri ODataConventialModelBuilder().EnablePascalCase() yang meniru metode EnableLowerCamelCase() agar casing Pascal berfungsi.

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

Namun, saya tidak pernah dapat menemukan cara untuk mengetahui versi API mana yang saya buat modelnya.

Pada satu titik, saya pikir saya menggunakan OnModelCreating untuk menambahkan

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

Untuk setiap kelas v1 IModelConfiguration, tetapi tidak berfungsi setelah saya membuat beberapa model.

Apakah ada cara untuk mengubah penamaan properti JSON berdasarkan versi API mana model tersebut?

0
jsmorris 1 Juni 2020, 12:51

1 menjawab

Jawaban Terbaik

Menggunakan pendekatan Konfigurasi Model OData yang dijelaskan di sini pertama tambahkan kelas yang berasal dari IModelConfiguration ke proyek Anda.

Sesuatu seperti ini:

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;
        }
    }
}

Kemudian dalam metode Register:

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

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

Jangan tergoda untuk meninggalkan garis 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>
0
John Gathogo 1 Juni 2020, 13:50