OData не может сериализовать модель с помощью конструктора - PullRequest
1 голос
/ 03 апреля 2020

Я пытаюсь включить обнуляемые ссылочные типы в своем проекте и следовал модели рекомендации , предоставленной командой EF Core. Но это нарушает создание модели в OData.

Включаемые в Nullable ссылочные типы включаются в файл .csproj

<Nullable>enable</Nullable>

Я использую

  • netcoreapp3.1
  • Microsoft.AspNetCore.OData Version = "7.4.0-beta"
  • Microsoft.EntityFrameworkCore.SqlServer Version = "3.1.3"

Моя модель выглядит следующим образом

public class Blog
{
    public Blog(int id, string name, string author)
    {
        Id = id;
        Name = name;
        Author = author;
    }

    public int Id { get; set; }
    public string Name { get; set; }
    public string Author { get; set; }

    public ICollection<Post> Posts { get; } = new List<Post>();
}

Когда я пытаюсь POST к конечной точке

[Route("odata/[controller]s")]
public class BlogController : ODataController
{
    private readonly MyContext _context;

    public BlogController(MyContext context)
    {
        _context = context;
    }

    [HttpGet]
    [EnableQuery]
    public IActionResult Get() {...}

    [HttpPost]
    public async Task<IActionResult> Post([FromBody] Blog blog) {...}
}

Полезная нагрузка:

{
    "id": 123,
    "name": "foo",
    "author": "bar"
}

Тогда параметр blog равен null.

Если я отключу «обнуляемые ссылочные типы» и удаляю конструктор, он работает.

Пожалуйста, совет.

Запуск

Возможно, стоит упомянуть, что я использую новый API конечных точек в AS PNET Core 3.1 и только что добавил поддержку OData v7.4.0-beta

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddDbContext<MMContext>(options => options.UseSqlServer(Configuration.GetConnectionString("MyDatabase")));
        services.AddControllersWithViews();

        // In production, the Angular files will be served from this directory
        services.AddSpaStaticFiles(configuration =>
        {
            configuration.RootPath = "..\\frontend\\dist";
        });

        services.AddOData();
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseExceptionHandler("/Error");
            // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
            app.UseHsts();
        }

        app.UseHttpsRedirection();
        app.UseStaticFiles();
        if (!env.IsDevelopment())
        {
            app.UseSpaStaticFiles();
        }

        app.UseRouting();

        var model = EdmModelBuilder.GetEdmModel(); // EnableLowerCamelCase = true

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllers();
            endpoints.Select().Filter().OrderBy().Count().MaxTop(50);
            endpoints.MapODataRoute("odata", "odata", model);
        });

        app.UseSpa(spa =>
        {
            // To learn more about options for serving an Angular SPA from ASP.NET Core,
            // see https://go.microsoft.com/fwlink/?linkid=864501

            spa.Options.SourcePath = "..\\frontend";

            if (env.IsDevelopment())
            {
                spa.UseProxyToSpaDevelopmentServer("http://localhost:4200");
            }
        });
    }
}

Обновление Я полагаю, что проблема сводится к тому, что OData не поддерживает модели с конструкторами, даже если Json. Net поддерживает это из коробки.

1 Ответ

0 голосов
/ 07 апреля 2020

Когда я пытаюсь POST к конечной точке с полезной нагрузкой:

{"id": 123, "name": "foo", "author": "bar"}

Тогда параметр blog равен null

В этой проблеме github , мы можем найти: он не поддерживает регистронезависимый в содержимом полезной нагрузки .

И чтобы он мог хорошо обрабатывать вышеупомянутую полезную нагрузку, как вы упомянули, мы можем отключить «ссылочные типы, допускающие обнуляемость», а затем изменить код, как показано ниже.

В классе блога

public class Blog
{
    public Blog()
    {

    }
    public Blog(int id, string name, string author)
    {
        Id = id;
        Name = name;
        Author = author;
    }

    public int Id { get; set; }
    public string Name { get; set; }
    public string Author { get; set; }

    public ICollection<Post> Posts { get; } = new List<Post>();
}

и настройте ODataConventionModelBuilder с EnableLowerCamelCase.

var builder = new ODataConventionModelBuilder()
    .EnableLowerCamelCase();

Результат теста

enter image description here

...