-
Notifications
You must be signed in to change notification settings - Fork 712
CreateRef and DeleteRef Issue #573
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
Unfortunately, this is limitation in the API Versioning route building infrastructure. I knew it was there, but I wasn't sure anyone would actually hit it. This issue wasn't hit in earlier iterations because building routes for In the meantime, you have a couple of options. You can use attribute routing, which will bypass the internal route building process because you've already provided the template. I'm not sure exactly what that looks like for this scenario. If I knew what that looked like, then I should be able to generate the same template by convention. Since you're using convention-based routing, the second option is to provide methods that complete the template. OData maps this using magic method names as a convention. For example // from the samples, where the entity set is Products
// PUT ~/products/supplier/$ref
[HttpPut]
public IActionResult CreateRefToSupplier(
[FromODataUri] int key,
[FromODataUri] string navigationProperty,
[FromBody] Uri link ) => CreateRef(key, navigationProperty, link);
// DELETE ~/products/supplier/$ref
[HttpDelete]
public IActionResult DeleteRefToSupplier(
[FromODataUri] int key,
[FromODataUri] string navigationProperty ) => DeleteRef(key, navigationProperty);
private IActionResult CreateRef(int key, string navigationProperty, Uri link ) => NoContent();
private IActionResult DeleteRef(int key, string navigationProperty ) => NoContent(); It's not ideal, but that should unblock you. Making this work the way it ought to will likely take quite a bit more investigation and I didn't want to hold up the entire 4.0 release for this one issue that has a workaround. If anyone else knows of a way OData will allow a route parameter in the template (and what it's key must be), that would be the simplest, fastest solution. |
This is now resolved in 5.0.0-RC.1. The official release will likely occur after 2 weeks of burn-in. The setup has been added in the test suite and samples. Thanks. |
I'm using Version 4.0.0-preview8.19405.7 which works great, thanks 👍
Yesterday I updated to Version 4.0.0 and running into the following issue (see bellow please).
Setup:
All Controllers inherit from a BaseController. The BaseController got the following definition which makes problem in 4.0.0.
In Version 4.0.0-preview8.19405.7 the recognized Path-Template is:
EntityName/{key}
where the recognized Path-Template in Version 4.0.0 is:
EntityName/{key}/{navigationProperty}/$ref
(Value from: ActionParameterContext ctor - odataPathTemplate variable)
Because of this, in the method TryGetNextSegmentText from the Odata.Core Lib, we have now 3 Segments. The last one is {navigationProperty} (PathTemplateSegment) with TargetKind Nothing, so the exception will throw.
Exception on AppStart:
ODataUnrecognizedPathException: The request URI is not valid. The segment '{navigationProperty}' must be the last segment in the URI because it is one of the following: $ref, $batch, $count, $value, $metadata, a named media resource, an action, a noncomposable function, an action import, a noncomposable function import, an operation with void return type, or an operation import with void return type. Microsoft.OData.UriParser.ODataPathParser.ThrowIfMustBeLeafSegment(ODataPathSegment previous) Microsoft.OData.UriParser.ODataPathParser.TryGetNextSegmentText(bool previousSegmentWasEscapeMarker, out string segmentText) Microsoft.OData.UriParser.ODataPathParser.ParsePath(ICollection<string> segments) Microsoft.OData.UriParser.ODataPathFactory.BindPath(ICollection<string> segments, ODataUriParserConfiguration configuration) Microsoft.OData.UriParser.ODataUriParser.ParsePathImplementation() Microsoft.OData.UriParser.ODataUriParser.Initialize() Microsoft.AspNet.OData.Routing.DefaultODataPathHandler.Parse(string serviceRoot, string odataPath, IServiceProvider requestContainer, bool template) Microsoft.AspNet.OData.Routing.DefaultODataPathHandler.ParseTemplate(string odataPathTemplate, IServiceProvider requestContainer) Microsoft.AspNet.OData.Routing.ActionParameterContext..ctor(ODataRouteBuilder routeBuilder, ODataRouteBuilderContext routeContext) Microsoft.AspNet.OData.Routing.ODataRouteBindingInfoConvention.UpdateBindingInfo(ControllerActionDescriptor action, ODataRouteMapping mapping, ICollection<ODataAttributeRouteInfo> routeInfos) Microsoft.AspNet.OData.Routing.ODataRouteBindingInfoConvention.Apply(ActionDescriptorProviderContext context, ControllerActionDescriptor action) Microsoft.AspNetCore.Mvc.ODataActionDescriptorProvider.OnProvidersExecuted(ActionDescriptorProviderContext context) Microsoft.AspNetCore.Mvc.Infrastructure.DefaultActionDescriptorCollectionProvider.UpdateCollection() Microsoft.Extensions.Primitives.ChangeToken+<>c.<OnChange>b__0_0(Action callback) Microsoft.Extensions.Primitives.ChangeToken+ChangeTokenRegistration<TState>.OnChangeTokenFired() Microsoft.Extensions.Primitives.ChangeToken+ChangeTokenRegistration<TState>+<>c.<RegisterChangeTokenCallback>b__7_0(object s) Microsoft.AspNetCore.Mvc.ODataActionDescriptorChangeProvider+ChangeToken.Callback() Microsoft.AspNetCore.Mvc.ODataActionDescriptorChangeProvider.NotifyChanged() Microsoft.AspNet.OData.Extensions.IRouteBuilderExtensions.MapVersionedODataRoutes(IRouteBuilder builder, string routeName, string routePrefix, IEnumerable<IEdmModel> models, Action<IContainerBuilder> configureAction, Action<ODataConventionConfigurationContext> configureRoutingConventions) Microsoft.AspNet.OData.Extensions.IRouteBuilderExtensions.MapVersionedODataRoutes(IRouteBuilder builder, string routeName, string routePrefix, IEnumerable<IEdmModel> models, Action<IContainerBuilder> configureAction) OrphyApi.Startup+<>c__DisplayClass28_0.<Configure>b__0(IRouteBuilder b) in Startup.cs + b.MapVersionedODataRoutes("ODataRoute", "odata/v{v:apiVersion}", GetPublicModels(modelBuilder), ConfigureAction); Microsoft.AspNetCore.Builder.MvcApplicationBuilderExtensions.UseMvc(IApplicationBuilder app, Action<IRouteBuilder> configureRoutes) OrphyApi.Startup.Configure(IApplicationBuilder app, IHostingEnvironment env, VersionedODataModelBuilder modelBuilder, IApiVersionDescriptionProvider provider) in Startup.cs + app.UseMvc(b => Microsoft.AspNetCore.Hosting.ConventionBasedStartup.Configure(IApplicationBuilder app) Microsoft.AspNetCore.Mvc.Internal.MiddlewareFilterBuilderStartupFilter+<>c__DisplayClass0_0.<Configure>g__MiddlewareFilterBuilder|0(IApplicationBuilder builder) Microsoft.Extensions.DependencyInjection.AutoRegisterMiddleware+<>c__DisplayClass4_0.<Configure>b__0(IApplicationBuilder app) Microsoft.AspNetCore.Server.IISIntegration.IISSetupFilter+<>c__DisplayClass4_0.<Configure>b__0(IApplicationBuilder app) Microsoft.AspNetCore.HostFilteringStartupFilter+<>c__DisplayClass0_0.<Configure>b__0(IApplicationBuilder app) Microsoft.AspNetCore.Hosting.Internal.AutoRequestServicesStartupFilter+<>c__DisplayClass0_0.<Configure>b__0(IApplicationBuilder builder) Microsoft.AspNetCore.Hosting.Internal.WebHost.BuildApplication().
How we can fix it ?
The text was updated successfully, but these errors were encountered: