.Net Core 上的 OData 不会在 $select 上返回正确的结果

Posted

技术标签:

【中文标题】.Net Core 上的 OData 不会在 $select 上返回正确的结果【英文标题】:OData on .Net Core doesn't return the right results on $select 【发布时间】:2020-04-10 09:06:29 【问题描述】:

我已将 OData 添加到我的 WebAPI 项目中。

版本:

    核心 3.1 OData 7.3.0(测试版,以便与 Core 3.x 配合使用) EF Core 3.1.0

这是我的 startup.cs

public class Startup

    public Startup(IConfiguration configuration)
    
        Configuration = configuration;
    

    public IConfiguration Configuration  get; 

    public void ConfigureServices(IServiceCollection services)
    
        services.AddDbContext<Models.Contexts.EntityContext>(opts => opts.UseSqlServer(Configuration["ConnectionString:MailBackup"]));
        services.AddControllers();
        services.AddMvc(options =>
        
            options.EnableEndpointRouting = false;
        ).SetCompatibilityVersion(Microsoft.AspNetCore.Mvc.CompatibilityVersion.Version_3_0);

        services.AddOData();
    

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    
        if (env.IsDevelopment())
        
            app.UseDeveloperExceptionPage();
        

        app.UseMvc(routeBuilder =>
        
            routeBuilder.EnableDependencyInjection();
            routeBuilder.Expand().Select().OrderBy().Filter();
        );

        app.UseHttpsRedirection();
        app.UseAuthorization();

    

控制器是:

[EnableQuery()]
[HttpGet]
[Route("GetAll")]
public IQueryable<Models.EmailMessage> GetAll()
    
    return this._context.EmailMessages;

API 工作正常,但是当我尝试添加一些 OData 操作(如 $select)时,我得到以下结果,而不是预期结果:


    "instance": null,
    "container": ,
    "modelID": "529e8054-04c4-4729-aa91-d7eaf67a55d0",
    "untypedInstance": null,
    "instanceType": null,
    "useInstanceForProperties": false
,

    "instance": null,
    "container": ,
    "modelID": "529e8054-04c4-4729-aa91-d7eaf67a55d0",
    "untypedInstance": null,
    "instanceType": null,
    "useInstanceForProperties": false
,

【问题讨论】:

我希望拥有仅包含 $select 参数中指定的字段的 EmailMessages 列表 @Jawad [Queryable] 在 .net core 3 中不存在 @Jawad 谢谢,但它不起作用。 BTW 括号可用于指定查询的可选参数。 这行得通吗,[EnableQuery(AllowedQueryOptions = AllowedQueryOptions.All)] 能分享一下OData模型是怎么配置的吗? 【参考方案1】:

我遇到了同样的问题。这为我解决了这个问题。也许 odata 与 Asp.Net 3.1 中的新 JSON 序列化程序不完全兼容。我不知道。

services.AddControllers(mvcOptions =>
           mvcOptions.EnableEndpointRouting = false)
       .AddNewtonsoftJson();

【讨论】:

这就是答案!具体来说,问题在于 System.Text.Json 序列化程序仅限于 32 级深度的迭代。目前,没有简单的方法来更改 JsonSerializerOptions.MaxDepth 值,但在 dotnetcore 5 的路线图中:github.com/dotnet/runtime/issues/31094#issuecomment-567232806 你可以在nuget.org/packages/Microsoft.AspNetCore.Mvc.NewtonsoftJson找到NuGet 谢谢,我遇到了同样的问题,这有助于我解决问题。看来问题出在 net core 3.1 序列化程序上:)【参考方案2】:

API 工作正常,但是当我尝试添加一些 OData 操作(如 $select)时,我得到以下结果,而不是预期结果

我可以在我的.NET Core 3.x 应用程序中使用与您共享的代码相似的代码重现相同的问题,目前使用以下代码 sn-p 将 OData 服务注入现有 API 控制器似乎不能很好地支持 .NET Core 3。 x.

routeBuilder.EnableDependencyInjection();

根据我的测试,它可以在.NET Core 2.x 中运行良好。为了使$select 功能在.NET Core 3.x 中正常工作,目前,我们可以尝试以下解决方法:

在 Startup.cs 中

var builder = new ODataConventionModelBuilder(app.ApplicationServices);

builder.EntitySet<Product>("Products");


app.UseMvc(routeBuilder =>

    // and this line to enable OData query option, for example $filter

    routeBuilder.Expand().Select().OrderBy().Filter();

    routeBuilder.MapODataServiceRoute("ODataRoute", "api", builder.GetEdmModel());

);

在 ODataController 中

public class ProductsController : ODataController

    // ...
    //code logic here
    // ...

    [HttpGet]
    [EnableQuery]
    public IQueryable<Product> Get()
    
        var products = _context.Products;

        return products;
    

    // ...


测试结果

更多信息请查看:https://docs.microsoft.com/en-us/odata/webapi/netcore#e-configure-the-odata-endpoint

【讨论】:

Similar issue已在github上报告,我们可以跟踪有关ASP.NET Core 3.x支持的OData的更新 那个问题是不同的。摆脱那个问题。我升级到 3.1 核心并包含 包。现在 odata 部分工作..对我来说 $filter,$groupby, $top 工作正常。但像 $ select ,$expand 给出错误 "instance": null, "container": , "modelID": "529e8054-04c4-4729-aa91-d7eaf67a55d0", "untypedInstance": null, "instanceType": null , "useInstanceForProperties": false , 大家好,终于搞定了。因为 ODATA 对 mvc api 路由不友好。刚刚更改为按预期工作的 odata 路由。已删除 大家好,终于搞定了。因为 ODATA 对 mvc api 路由不友好。刚刚更改为按预期工作的 odata 路由。已删除路由。EnableDependencyInjection();从路线委托。最初我的网址是localhost:44352/api/controllername,现在是localhost:44352/odata/controllername。希望这对你有意义。有任何疑问请告诉我。在 mvc 路由委托下只保留两行 routes.Count().Filter().OrderBy().Select().Expand(); routes.MapODataServiceRoute("odata", "odata", GetEdmModel(app));

以上是关于.Net Core 上的 OData 不会在 $select 上返回正确的结果的主要内容,如果未能解决你的问题,请参考以下文章

使用 ASP.NET Core OData 8.0 映射动态 OData 路由

在 ASP.NET Core WebAPI 中获取 OData 计数

如何正确地将 OData 与 ASP.net Core 集成

Net Core:在洋葱架构中使用OData,将查询参数转换为Linq

在 .NET Core Web API for MongoDB 中使用 OData

带有 EF Core / ASP.NET Core 的 OData - 好还是坏?