Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[OData] /odata/v1/orders() gives 400 Bad Request "Unspecified API version" #911

Closed
1 task done
dnperfors opened this issue Nov 15, 2022 · 3 comments
Closed
1 task done
Assignees
Labels

Comments

@dnperfors
Copy link

Is there an existing issue for this?

  • I have searched the existing issues

Describe the bug

When trying to request a specific item, for example a product in de ODataBasicExample, but not providing a key: GET ~/api/v1/orders(), the service returns the following:

HTTP/1.1 400 Bad Request
Content-Type: application/problem+json
Date: Tue, 15 Nov 2022 11:30:37 GMT
Server: Kestrel
Transfer-Encoding: chunked

{
  "type": "https://docs.api-versioning.org/problems#unspecified",
  "title": "Unspecified API version",
  "status": 400,
  "detail": "An API version is required, but was not specified.",
  "Code": "ApiVersionUnspecified",
  "traceId": "00-93b92d7cb1971c4932902abcc9d4ea8d-93ab6594370d9afd-00"
}

Expected Behavior

I would expect (and removing versioning from the example confirms this) a 404 Not Found.

Steps To Reproduce

As an extra test I made a simple example here: https://github.com/dnperfors/eLibrary

The following requests give the following responses:

Project Request Response
eLibrary.OData /odata/books 200 Ok -> List with books
eLibrary.OData /odata/books() 404 Not Found
eLibrary.OData /odata/books(1) 200 Ok -> single book
eLibrary.OData.Versioning /odata/v1/books 200 Ok -> List with books
eLibrary.OData.Versioning /odata/v1/books() 400 Bad Request --> "Unspecified API version"
eLibrary.OData.Versioning /odata/v1/books(1) 200 Ok -> single book

Exceptions (if any)

No response

.NET Version

6.0.300

Anything else?

Asp.Versioning.OData.ApiExplorer Version: 6.2.1

@commonsensesoftware
Copy link
Collaborator

Strange, I don't see why that would happen based on your configuration. Everything looks correct. Out of curiosity, what happens if you don't use ()? Does GET /odata/v1/books the same result? The repro is helpful. I'll get into this some more.

@dnperfors
Copy link
Author

Strange, I don't see why that would happen based on your configuration. Everything looks correct. Out of curiosity, what happens if you don't use ()? Does GET /odata/v1/books the same result? The repro is helpful. I'll get into this some more.

That is why I report it 😄, I didn't expect it either and was doubting myself, but since it does work without versioning, it has to be something with the versioning magic (or some other weird magic of course 😄)

As shown in the table (😉) GET /odata/v1/books returns the list of books. If I remove the "GetBooks()" method from the controller and call GET /odata/v1/books I get a 404 Not Found.

@commonsensesoftware
Copy link
Collaborator

It might be surprising, but as configured, this is the expected behavior. By default, the configuration allows for the API version to be defined via the query string and a URL segment (e.g. the un-RESTful way). Extracting the API version from the URL is tricky. Since there are no suitable templates with the route constraint that match, the routing system presumes that GET /odata/v1/books()?api-version=### could exist, but the client didn't specify a version. 400 is the expected response in this case and is necessary to continue endpoint resolution.

Now, if you change the configuration to:

builder.Services
       .AddApiVersioning(options => options.ApiVersionReader = new UrlSegmentApiVersionReader())
       .AddOData(options => options.AddRouteComponents("/odata/v{version:apiVersion}"))

the API version can only come from a URL segment. Unfortunately, /odata/v1/books() will still return 400. This, I think, is a 🐞. If, and only if, the API version can only come from the URL and none is found, then the routing system should lead to a path that will produce 404. There are couple of edge cases such as if you have version-neutral endpoints or you allow assuming a default version, but those paths should eventually lead to 404 too.

I believe I have a fix that will result in the desired behavior when versioning is restricted to just the URL. Any other combination will likely be 400. This problem only exists when versioning by URL segment. I'll try to get the fix out ASAP.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants