I got an API on .NET 5, made with Entity Framework Core.
The query-URLs with methods are something like GET https://api.mydomain.ch/v1/applicationusers
This would retrieve all application users (which makes sense).
In C# this looks:
[HttpGet]
public async Task<ActionResult<ApplicationUser>> Get()
{
return Ok(await _applicationUserRepository.GetAll());
}
Now a client that consumes my API wants to request: GET https://api.mydomain.ch/v1/applicationusers?$filter=startswith(givenName,'Peter')
I have seen this matches the Microsoft Graph API and its query parameters. And my client also wants to use the other implementations for this (https://learn.microsoft.com/en-us/graph/query-parameters)
I couldn't find any implementation example that works with Entity Framework Core. Is it possible to implement this with an easy way, and not to make big modifications on the database?
Do I need to implement the functions completely on my own? Or is there support from Microsoft between those query parameter functions and Entity Framework Core?
Okay the answer is quite simple and it's not the Microsoft Graph that needs to be implemented, but simply OData
.
For .NET 5 it's not well documented, since the NuGet for this .NET-version is still in RC-state (pre-release).
To implement OData, we need to add Microsoft.AspNetCore.OData
in nuget packages. My answer is written with state from 8.0.0-rc
. For v7.x the calls look bit different but are better documented.
What we need to do is:
Add OData in StartUp.ConfigureServices
:
ODataConventionModelBuilder builder = new(new DefaultAssemblyResolver());
builder.EntitySet<ApplicationUser>("ApplicationUser");
IEdmModel model = builder.GetEdmModel();
services.AddOData(opt =>
{
opt
.AddModel("api/v1", model)
.Select()
.Expand()
.OrderBy()
.Filter()
.Count();
});
with .Select().Expand().OrderBy().Filter().Count()
you add the api-query-parameters for $select, $expand,...
My UseEndpoints
call in Configure()
looks this way:
app.UseEndpoints(endpoints => { endpoints.MapControllers(); });
Make sure, the controller inherit from ODataApiController
.
An action looks like this:
[HttpGet]
[EnableQuery]
public async Task<ActionResult<ApplicationUser>> Get()
{
return Ok(await _applicationUserRepository.GetAll());
}
This would not execute the expected query. We need to return the IQueryable<T>
to make this work, so we don't query for all records:
[HttpGet]
[EnableQuery]
public IQueryable<ApplicationUser> Get()
{
return _applicationUserRepository.GetAll();
}