-
Notifications
You must be signed in to change notification settings - Fork 711
OData API Explorer Should Support All Routing Conventions #494
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
Comments
Hello, I am trying to implement your samples AspNetCore + OData + Swagger + Api Versioning. The problem i have is with routing. I would like to be able to have routes like these v1/security/Users or v1/tracking/Areas the problem is that when i get the EDM models it brings back all EDM Models. This means i can not build a separate route based on the EDM model. For example var models = modelBuilder.GetEdmModels(); routes.MapVersionedODataRoutes("security", "v{version:apiVersion}", models); I would like to be able to get EDM models for a set of controllers(not all of them at once) and be able to add them to a specified route. I have tried atrribute routing and it only allows the RoutePrefix to match the controller name e.g. [ODataRoutePrefix("Users")]. if i try [ODataRoutePrefix("/security/Roles")] it will return a 404. Please assist |
@ben5Kuda your question isn't exactly specific to this issue, but let me answer your question. There are two ways this can be achieved:
The VersionedODataModelBuilder creates an EDM for every discovered API version. Each EDM is tagged with the ApiVersionAnnotation. To divide them up, you can match them with: var models = modelBuilder.GetEdmModels();
foreach ( var model in models )
{
var version = model.GetAnnotationValue<ApiVersionAnnotation>( model ).ApiVersion;
if ( version == new ApiVersion( 1, 0 ) )
{
routes.MapVersionedODataRoute( "security", "v{version:apiVersion}", model, version );
}
// ... and so on
} Of course, if you feel you know better, you can always build the EDM as normal and register the route with Option 1. The annotation is automatically applied during registration so you don't have to worry about matching it up. I hope that helps. |
Thank you for your response, it has definitely helped a lot and my apologies for raising this issue on the the wrong thread. I have to admit i only saw your response today, however i have tried the 2 suggested approaches and it does appear that the routing only works per version. please see below routes.MapVersionedODataRoute("tracking", "v{version:apiVersion}/tracking", trackingEdm, new ApiVersion(2, 0));
Here as you suggested, i am building two different routes and it works fine (building my own EdmModels). The issue i have is that the routing i need is on functional lines (I want to group a set of resources based on functionality such security or tracking - regardless of their version). That means Users for example falls under security module and subsequent versions will still be under security. From what i can tell the suggested routing would create a different route for potentially every version. So simply put is it possible to have different routes e.g v1/tracking and v1/security all with same version? I can only get it to work if it is v1/tracking and v2/security. please see some of my futile attempts below.
private IEdmModel BuildSecurity(ODataModelBuilder builder)
if controller XYZ is tagged with version 2.0 then it works (assuming all others are tagged v1). If i change XYZ to v1 along with everything else then i get this error: An unhandled exception occurred while processing the request. if i uncomment ABC (everything else remaining on v1) i get this error: KeyNotFoundException: The given key 'Microsoft.AspNet.OData.EdmTypeKey' was not present in the dictionary. I cant seem to find a way to separate routes except via a different version. I would really appreciate if is possible to separate the routes in a way that is version agnostic. Thank you. |
This may be because of your prefix. OData uses convention-based routing under the hood, which doesn't have a resolver for inline route constraints by key. This means that your prefix should be I should point out that you'll probably still have issues with the |
@Discjoggy, saw your message, but not sure why it doesn't show up in the issue. I didn't think there was such a thing as a private comment. To restate the issue, the problem isn't OData or it's implementation supporting entity linking with OData provides zero functionality to build URLs. When you build the URLs yourself with attribute routing, things are pretty straight forward for the API Explorer. When you rely on the default OData conventions, the API Explorer has to build templates based on the EDM and method signature. As you can imagine, this is quite complicated and not all of the URL generation scenarios are covered today. A few convention scenarios that are not covered:
I hope that helps clear things up. |
Thank you, in the end i resolved to drop the route prefix and have everything under v{version:apiVersion} depending on the version and thank you for clearing things up. |
Overview
Today, the full set of OData routing conventions is not supported by the API Explorer. Generating proper OData route templates by inspecting compiled code is non-trivial. The common scenarios for entity sets, functions, actions, and navigation properties are currently supported. More complex scenarios such linking entities with
$ref
are not support - yet.Workaround
Most, if not all, routes should be property discovered using attribute-based routing. The API Explorer does little to nothing in the way of modification. Since the route templates are user-defined, the correct route templates should be correctly generated.
References
Useful references that describe the expected conventions code must match can be found at:
$ref
Routing ConventionThe text was updated successfully, but these errors were encountered: