OData / OData/AspNetCoreOData

Routing by convention for functions creates duplicate GET route

Open
#632 0 comments 1 reaction 1 assignee View on GitHub

@Nthemba is already working on this.

Since Jul 12, 2022.

bug follow-up
Dominant language
C#
Stars
505
Forks
186
PR merge metrics
No merged PRs in 30d

Description

Assemblies affected
ASP.NET Core OData 8.0.10

Describe the bug
While using routing by convention for OData Functions it is required to use [HttpGet] before the FunctionRoutingConvention handles the route generation. However, when the [HttpGet] is applied, it also appears to be generating a route for the blank path too.

According to https://github.com/OData/AspNetCoreOData/blob/main/src/Microsoft.AspNetCore.OData/Routing/Conventions/FunctionRoutingConvention.cs#L39 [HttpGet] must be specified on the route as well which may be the reason it is being picked up and handled "twice".

The same logic appears to be in the Action routing convention as well so I would expect the same issue to occur for OData Actions as well.

My ODataController:

[Route("api/v1/Component")]
[ApiController]
public class ComponentController : ODataController {

	[EnableQuery]
	[HttpGet] // must be specified
	public ActionResult<IQueryable<Component>> GetComponents(string jobName) { ... }

}

Output in $odata debug:
image

Data Model

var entityType = builder.EntitySet<Component>(nameof(Component)).EntityType;
entityType.Select().Expand().OrderBy().Filter().Count().Page(ApiDefaultLimits.MaxTop, ApiDefaultLimits.PageSize);

var et2 = entityType
	.Collection
	.Function("GetComponents")
	.ReturnsCollectionFromEntitySet<Component>(nameof(Component));
et2.Parameter<string>("jobName");

Expected behavior
While using routing convention, it is expected that only a single route is generated for functions. However, a blank route (at /api/v1/Component) is also generated as shown in the screenshot above.

According to #428 we're not supposed to mix the usage of HTTP attributes (e.g. [HttpGet]) for methods handled by routing convention; however, the function will not be handled by the FunctionRoutingConvention without one being declared. This requirement appears to be inconsistent in behaviour compared to the other routing conventions.

Workaround
Rename the GetComponents method to something different like GetComponentsFunction and manually specify the route in the HTTP Get attribute like so. For instance:

[HttpGet("GetComponents(jobName={jobName})")]
public ActionResult<IQueryable<Component>> GetComponentsFunction(string jobName) { ... }

This workaround would be ignoring the utilization of routing by convention though.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.