Lets assume you have an entity with a key of type string. The value for this id is some%30value. This leads to an uri like odata/model/entity(%27some%2530value%27)/ or odata/model/entity('some%30value')/. The Url seems to be unescaped multiple times, until the key is unescaped to "some0value" (%30 is an escaped zero) which is not present in the database.
I think that the issue have been present before the fix of https://github.com/OData/WebApi/issues/2240, but since that fix I wasn't able create an entity with such an id, because the link generation thrown an error..
In the project AspNetCore3xODataSample.Web you can load the Customer (http://localhost:5000/odata/Customers)
If you load the customer with the ID "a%30b" you will get an internal server error http://localhost:5000/odata/Customers(%27a%2530b%27) with the message InvalidOperationException: Request URI 'http://localhost:5000/odata/Customers('a0b')' does not contain OData path 'Customers('a%30b')'.
System.InvalidOperationException: Request URI 'http://localhost:5000/odata/Customers('a0b')' does not contain OData path 'Customers('a%30b')'.
at Microsoft.AspNet.OData.Routing.ODataPathRouteConstraint.RemoveODataPath(String uriString, String oDataPathString) in C:\Projekte\OSS\WebApi\src\Microsoft.AspNet.OData.Shared\Routing\ODataPathRouteConstraint.cs:line 160
at Microsoft.AspNet.OData.Routing.ODataPathRouteConstraint.GetODataPath(String oDataPathString, String uriPathString, String queryString, Func`1 requestContainerFactory) in C:\Projekte\OSS\WebApi\src\Microsoft.AspNet.OData.Shared\Routing\ODataPathRouteConstraint.cs:line 74
at Microsoft.AspNet.OData.Routing.ODataPathRouteConstraint.Match(HttpContext httpContext, IRouter route, String routeKey, RouteValueDictionary values, RouteDirection routeDirection) in C:\Projekte\OSS\WebApi\src\Microsoft.AspNetCore.OData\Routing\ODataPathRouteConstraint.cs:line 70
at Microsoft.AspNetCore.Routing.RouteConstraintMatcher.Match(IDictionary`2 constraints, RouteValueDictionary routeValues, HttpContext httpContext, IRouter route, RouteDirection routeDirection, ILogger logger)
at Microsoft.AspNetCore.Routing.RouteBase.RouteAsync(RouteContext context)
at Microsoft.AspNetCore.Routing.RouteCollection.RouteAsync(RouteContext context)
at Microsoft.AspNetCore.Builder.RouterMiddleware.Invoke(HttpContext httpContext)
at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
Expected result
The generated location points to the created Element
Following the link will lead to the entity
Actual result
In my application these keys leads to 404 Not Found or 500 Internal Server Error.
In the sample aplication it will bring also 204 No Content in some cases
Additional detail
If I request the complete list of elements, with full metadata, the generated URLs point so the non-functioning locations:
There are some issues with the URL parsing.
Lets assume you have an entity with a key of type string. The value for this id is
some%30value
. This leads to an uri likeodata/model/entity(%27some%2530value%27)/
orodata/model/entity('some%30value')/
. The Url seems to be unescaped multiple times, until the key is unescaped to "some0value" (%30 is an escaped zero) which is not present in the database.I think that the issue have been present before the fix of https://github.com/OData/WebApi/issues/2240, but since that fix I wasn't able create an entity with such an id, because the link generation thrown an error..
Assemblies affected
Reproduce steps
I've created a fork where I changed two of the sample projects to show the bevaivior: https://github.com/ckuetbach/WebApi/tree/bugfix/special_chars_in_key
In the project
AspNetCoreODataSample.Web
you load the Movies (http://localhost:5912/efcore/Movies) and then one of the movies by ID, likeIn the project
AspNetCore3xODataSample.Web
you can load the Customer (http://localhost:5000/odata/Customers) If you load the customer with the ID "a%30b" you will get an internal server errorhttp://localhost:5000/odata/Customers(%27a%2530b%27)
with the messageInvalidOperationException: Request URI 'http://localhost:5000/odata/Customers('a0b')' does not contain OData path 'Customers('a%30b')'.
Expected result
Actual result
404 Not Found
or500 Internal Server Error
.204 No Content
in some casesAdditional detail
If I request the complete list of elements, with full metadata, the generated URLs point so the non-functioning locations:
There is another issue, given there are two entitites with the IDs
a/b
anda%2Fb
the response will be (correctly, I assume):But both links will lead to the element with the unescaped ID
a/b/c
, the other one is not accessable. It looks like the issue is present because of this line, but I'm not entirely sure: https://github.com/OData/WebApi/blob/master/src/Microsoft.AspNet.OData.Shared/Routing/ODataPathRouteConstraint.cs#L165