5
votes

As pointed out here, having a double slash in a URL is valid.

I have an ASP Net Core project that uses attribute routing, a controller named GroupController for handling operations on Groups and an action for PUTting RuleParts of a group, specified by its ImportId of type string.

[Route("/api/[controller]")]
public class GroupController : ControllerBase
{
    [HttpPut("{groupImportId?}/ruleParts")]
    public async Task<IActionResult> PutRuleParts(string groupImportId, [FromBody]List<RulePartDto> ruleParts)
    {
        return null; //actual code ommitted for brevity
    }
}

A URL like http://localhost/api/group/groupImportId/ruleParts matches as expected.

I would expect that null groupImportIds, i.e. URLs like http://localhost/api/group//ruleParts would call that same action, since the groupImportId route parameter has been marked as optional. However, when trying to call this URL, I get a 404 error and the action is not hit.

Is there a possibility to match an empty URL path segment in ASP Net Core?

1
Do not use the double slash. add another route so that http://localhost/api/group/ruleParts will also be valid.Nkosi
@Nkosi I don't get to choose what a web-client is going to call, hence I can't control if he's using a double slash. Please don't mark the question as dup when it's not actually a dup.Thaoden
Also, optional parameters are suppose to be used at the end of a URL. wont work when embedded in the middle. What you expected and what the framework handles are different.Nkosi
Then please remove the dup-flag, reopen, write this as an answer along with some link for me to get more information about the expected placement of optional params in AspNet Core WebApi and I even get to mark an answer as accepted.Thaoden
Curious though. Why would an import have an optional Id? what is the case for that scenario?Nkosi

1 Answers

5
votes

Do not use the optional parameter in the middle of the route template.

Optional parameters are supposed to be used at the end of a URL. Routes won't match when optional parameters embedded in the middle segments are omitted as this will result in not found errors.

Instead attribute routing allows for multiple routes to be mapped to the same action.

[HttpPut("ruleParts")] // PUT api/group/ruleParts
[HttpPut("{groupImportId}/ruleParts")] //PUT api/group/123456/ruleParts
public async Task<IActionResult> PutRuleParts([FromBody]List<RulePartDto> ruleParts, string groupImportId = null) {
    //...
}

The groupImportId argument of the action is made optional to allow the optional parameter to be omitted in the URL when the other route is requested.

Reference Routing to Controller Actions in ASP.NET Core