Getting OData Count in ASP.NET Core WebAPI
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(); }}
Just been battling this.
I found that if I request my controller at /api/Things
that most of the OData options work but $count
doesn't.
However, $count
does work if I request the same method via /odata/Things
.
You can just set an empty preffix route when you map OData, and you will receive OData with your request your endpoint.
routeBuilder.MapODataServiceRoute("ODataEdmModel", "", GetEdmModel());