Webapi: Async OData functions result in 404 - Asp.Net Core 3.1, OData 7.3

Created on 28 Jan 2020  路  4Comments  路  Source: OData/WebApi

Any async odata functions result in a 404. Syncronous functions work fine.

Assemblies affected

Asp.Net Core 3.1, OData 7.3

Reproduce steps

model.Collection
    .Function("MyFunctionAsync")
    .ReturnsFromEntitySet<MODEL>("MODELNAME")
    .Parameter<Guid>("key");

[EnableQuery]
public async Task<ActionResult<IQueryable<MODEL>>> MyFunctionAsync([FromODataUri] Guid key) 
{ ...return Ok(IQueryable<RESULT>) }

https://localhost:5001/odata/MODEL/MyFunctionAsync(key=00ccd63f-717c-4e3d-a758-3dfad9ab4bd4)

Expected result

In Asp.net 2.2 core this worked fine. All of my synchronous functions returning ActionResult> work fine still.

Actual result

20-01-28 13:00:15.9694|1|INFO|Microsoft.AspNetCore.Hosting.Diagnostics|Request starting HTTP/1.1 GET https://localhost:5001/odata/reviews/UserQueueAsync(key=00ccd63f-717c-4e3d-a758-3dfad9ab4bd4)?%24expand=Customer,ReviewCollection,ReviewTemplate   
2020-01-28 13:00:15.9724|2|INFO|Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler|Successfully validated the token. 
2020-01-28 13:00:15.9895|2|INFO|Microsoft.AspNetCore.Hosting.Diagnostics|Request finished in 6.6109ms 404  
bug

All 4 comments

@joelmeaders Thanks for posting this issue. I have managed to reproduce the error. Based on my preliminary investigation, it seems the issue is related to the Async suffix. When I create an async function called SomeFunc, it works just fine, but when I create it as SomeFuncAsync, I get a 404 error response. Quite odd.

@habbes Thanks for your time on this and thanks for figuring out a workaround. It is an odd bug for sure!

@joelmeaders So I took a closer look and found that the SelectAction(RouteContext routeContext) gets the ControllerActionDescriptor collection from the IActionDescriptorCollectionProvider defined in AspNetCore. These action descriptors have action names with the Async suffix removed. So when OData WebApi fails to match SomeFuncAsync cause it cannot find.

I assume AspNetCore removed Async suffix so that whether you name your controller action SomeFunc or SomeFuncAsync, it would still resolve to the some route. Following this train of thought, I assume that if you name the function in your EdmModel as SomeFunc, then the correct action will be called even if you called the action SomeFuncAsync. I will have to confirm this though.

So I don't know whether this is really a bug. If it is, I think we can change the SelectAction to also consider the actual method name of the action descriptor (via the MethodInfo property) if it fails to match the ActionName.

@joelmeaders This AspNet.Core migration guide confirms that starting with version 3.0, AspNetCore removes the "Async" suffix from controller action names. So you could resolve your issue by:

  • Changing the function name in your EDM from SomeFuncAsync to SomeFunc
  • Disable the removal of Async suffix by setting the MvcOptions.SuppressAsyncInActionNames to false as described in the migration guide
  • Use the [ActionName] attribute to explicitly specify the name of the action, as described in the migration guide.

Seeing that this is not an OData WebApi bug, I'm going to go ahead and close this issue. Thanks.

Was this page helpful?
0 / 5 - 0 ratings