Getting OData Count in ASP.NET Core WebAPI

纵饮孤独 提交于 2020-02-24 06:48:50

问题


Using the sample code from Hassan Habib's Supercharging ASP.NET Core API with OData blog post, I am able to get the record count using an OData query of $count=true:

What needs to be configured to get the response object to be wrapped in an OData context so that the @odata.count property will show?

In my own ASP.NET Core web API project, I cannot get the simple $count parameter to work and I have no idea why.

With Hassan's sample code, the response JSON is wrapped in an OData context and the payload (an IEnumerable<Student> object) is in the value property of the JSON response. In my project, the OData context wrapper does not exist; my code never returns OData context, it only returns the payload object of type IEnumerable<T>:

I've also noticed that the Content-Type in the response header is application/json; odata.metadata=minimal; odata.streaming=true; charset=utf-8 in the sample project, where as it is simply application/json; charset=utf-8 in my project. I don't see any setting that controls this in either project, so I'm assuming the Microsoft.AspNetCore.Odata NuGet package is magically changing the response when it's configured properly.

My project is also using .NET Core 2.2 (Upgraded from 2.1), all the same versions of NuGet packages as Hassan's sample projects, and all the same settings in the StartUp.cs class... although my StartUp.cs is way more complicated (hence the reason I'm not posting it's content here.)


回答1:


I could reproduce your issue when i use [Route("api/[controller]")]and [ApiController] with the startup.cs like below:

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

To fix it,be sure you have built a private method to do a handshake between your existing data models (OData model in this case) and EDM.

Here is a simple demo:

1.Controller(comment on Route attribute and ApiController attribute):

//[Route("api/[controller]")]
//[ApiController]
public class StudentsController : ControllerBase
{
    private readonly WSDbContext _context;
    public StudentsController(WSDbContext context)
    {
        _context = context;
    }
    // GET: api/Students
    [HttpGet]
    [EnableQuery()]
    public IEnumerable<Student> Get()
    {
        return _context.Students;
    }
}
//[Route("api/[controller]")]
//[ApiController]
public class SchoolsController : ControllerBase
{
    private readonly WSDbContext _context;
    public SchoolsController(WSDbContext context)
    {
        _context = context;
    }
    // GET: api/Schools
    [HttpGet]
    [EnableQuery()]
    public IEnumerable<School> Get()
    {
        return _context.Schools;
    }

2.Startup.cs():

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.AddMvcCore(action => action.EnableEndpointRouting = false);
        services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
        var connection = @"Server=(localdb)\mssqllocaldb;Database=WSDB;Trusted_Connection=True;ConnectRetryCount=0";
        services.AddDbContext<WSDbContext>(options => options.UseSqlServer(connection));
        services.AddOData();
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseHsts();
        }

        app.UseHttpsRedirection();
        app.UseMvc(routeBuilder =>
        {
            routeBuilder.Expand().Select().Count().OrderBy().Filter();
            routeBuilder.MapODataServiceRoute("api", "api", GetEdmModel());
        });
    }

    private static IEdmModel GetEdmModel()
    {
        var builder = new ODataConventionModelBuilder();
        builder.EntitySet<Student>("Students");
        builder.EntitySet<Student>("Schools");
        return builder.GetEdmModel();
    }
}


来源:https://stackoverflow.com/questions/58838970/getting-odata-count-in-asp-net-core-webapi

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!