This is my ApplicationUserController
(I removed unneccessary parts like ctor etc):
[ODataRouting]
public class ApplicationUserController : ApiController
{
[EnableQuery]
[HttpGet("ApplicationUser")]
[HttpGet("ApplicationUser/$count")]
public IQueryable<ApplicationUser> Get()
{
return _applicationUserRepository.GetQueryable();
}
[HttpGet("ApplicationUser/{id}")]
[HttpGet("ApplicationUser({id})")]
public async Task<ApplicationUser> GetById([FromODataUri] long id)
{
return await _applicationUserRepository.SingleOrDefault(x => x.Id == id);
}
}
The first function works perfectly. I call http://localhost:5000/v1/ApplicationUser?$filter=startsWith(LastName, 'Test')
and I get all user that last name starts with "Test".
The second one doesn't work. I call
http://localhost:5000/v1/ApplicationUser/1
http://localhost:5000/v1/ApplicationUser(1)
and none of them do work. For both, I get a 404: Not found.
Is there something I did wrong?
I also tried adding the EnableQuery
-Attribute, but it doesn't make any difference.
Here my code from ConfigureServices
:
public void ConfigureServices(IServiceCollection services)
{
IEdmModel v1 = _getEdmModel();
services.AddOData(opt => opt
.AddModel("v{version}", v1)
.Select()
.Expand()
.OrderBy()
.Filter()
.Count()
);
}
and my _getEdmModel()
:
private static IEdmModel _getEdmModel()
{
ODataConventionModelBuilder builder = new (new DefaultAssemblyResolver());
builder.EntitySet<ApplicationUser>("ApplicationUser");
builder.EntityType<ApplicationUser>().HasKey(x => x.Id); // edit: added this line
return builder.GetEdmModel();
}
UPDATE:
I created a new repository, with basic code here: https://github.com/matthiasburger/ApplePie
same behaviour, reproducable with following URLs:
https://localhost:5001/api/testentity
: workshttps://localhost:5001/api/testentity?$filter=id%20eq%201
: workshttps://localhost:5001/api/testentity/1
: doesnt workhttps://localhost:5001/api/testentity(1)
: doesnt workIt's weird, but if you change the method name "GetById" to "GetTestEntity" it works...
Offtopic
You can simplify your Serilog instance (removing a lot of code that's already in the host builer) by doing
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) => Host
.CreateDefaultBuilder(args) // sets all the configuration options right!
.ConfigureAppConfiguration((hostingContext, config) =>
config.AddJsonFile("secrets.json", optional: true, reloadOnChange: true))
.UseSerilogLogger((hostBuilderContext, loggerConfiguration) => loggerConfiguration
.ReadFrom.Configuration(hostBuilderContext.Configuration)
.Enrich.FromLogContext()) // no output?
.ConfigureWebHostDefaults(webHostBuilder => webHostBuilder
.UseStartup<Startup>()
);
The only thing you'll miss is the starting and final exception of the web host. But if there's a problem there, you'll notice anyhow.