aspnet-api-versioning: OData - Same Named Function in Two Configurations Causes System.InvalidOperationException on Startup
tldr - In the OData example project I added a function with the same name to two different configurations. The examples can no longer run. I used to be able to add functions with the same name to two different OData endpoints without issue.
Example Repo - https://github.com/benhysell/aspnet-api-versioning Example Project - https://github.com/benhysell/aspnet-api-versioning/tree/master/samples/aspnetcore/SwaggerODataSample
Using the examples I’ve duplicated the MostExpensive
function from Order
to Person
via the steps below to trigger the exception.
Steps to Reproduce
- Take the Example project
SwaggerODataSample
- Modify the configuration of PersonModelConfiguration.cs to add function
person.Collection.Function( "MostExpensive" ).ReturnsFromEntitySet<Person>( "People" );
https://github.com/benhysell/aspnet-api-versioning/blob/master/samples/aspnetcore/SwaggerODataSample/Configuration/PersonModelConfiguration.cs#L34 - Note this same function exists in the OrderModelConfiguration.cs – https://github.com/benhysell/aspnet-api-versioning/blob/c29e95940cbaa66784b38f864ed51c60a9971d55/samples/aspnetcore/SwaggerODataSample/Configuration/OrderModelConfiguration.cs#L31
- Run the application
- Exception is thrown ODataRouteBuilderContext.cs ln 252
Is it allowable to have the same named function in two different models? And if not why not?
About this issue
- Original URL
- State: closed
- Created 4 years ago
- Reactions: 2
- Comments: 19
Commits related to this issue
- Disambiguate OData operations by action parameters. Fixes #697 — committed to dotnet/aspnet-api-versioning by commonsensesoftware 3 years ago
- Add special handling for OData actions because they map as a single action parameter. Related #697 — committed to dotnet/aspnet-api-versioning by commonsensesoftware 3 years ago
- Disambiguate OData operations by action parameters. Fixes #697 — committed to dotnet/aspnet-api-versioning by commonsensesoftware 3 years ago
- Add special handling for OData actions because they map as a single action parameter. Related #697 — committed to dotnet/aspnet-api-versioning by commonsensesoftware 3 years ago
- Disambiguate OData operations by action parameters. Fixes #697 — committed to dotnet/aspnet-api-versioning by commonsensesoftware 3 years ago
- Add special handling for OData actions because they map as a single action parameter. Related #697 — committed to dotnet/aspnet-api-versioning by commonsensesoftware 3 years ago
- Add special handling for OData actions because they map as a single action parameter. Related #697 — committed to dotnet/aspnet-api-versioning by commonsensesoftware 3 years ago
I’ve run into this issue as well.
This appears to be caused by a bug way down in the depths of Microsoft.OData.Edm, right here.
For some context, I created a quick sample to isolate this issue with two edm entity types
Foo
andBar
, each having a functionBulk
The line of code linked above is ultimately called by
ODataRouteBuilderContext
, from hereWhen we hit line 2528 of
HasEquivalentBindingType
,parameterType.TypeKind
isEdmTypeKind.Collection
whilebindingType.TypeKind
isEdmTypeKind.Entity
. This results in this method immediately returning false on line 2530.I do not know, but it looks like the special collection handling on line 2533 might need to be run first such as
or something along those lines. I should point out that the above code doesn’t actually work because
parameterType.TypeKind
isCollection
andbindingType
does not implementIEdmCollectionType
@commonsensesoftware I don’t know if it’d be more productive for you to communicate this issue with whoever maintains Microsoft.OData.Edm or if I should write up an issue against that repo.
Sample project can be found here
It should be allowable. Resolving an operation by its qualified name was previously an issue. I could have sworn I had a test for that. I’ll have to spelunk some more. This seems to be the issue. I distinctly recall using
SingleOrDefault
to make sure this exact failure would happen in the event the name is ambiguous (asFirstOrDefault
would likely be harder to understand or track down).I did notice you copied the MostExpensive method verbatim from OrdersController. The OrdersController intentionally uses attribute-routing and PeopleController intentionally uses convention-based routing to demonstrate the different styles. I doubt that’s the cause this issue, but you’ll want to be careful with mixing and matching as it’s bound to cause issues.
Since you already have a repro setup with the source, you might break inside
ODataRouteBuilderContext.ResolveOperation
. You might find why the function is not being resolved.