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

Combined [FromRoute] and [FromBody] confuses Swashbuckle #2346

Open
ffMathy opened this issue Feb 18, 2022 · 3 comments
Open

Combined [FromRoute] and [FromBody] confuses Swashbuckle #2346

ffMathy opened this issue Feb 18, 2022 · 3 comments
Labels
help-wanted A change up for grabs for contributions from the community

Comments

@ffMathy
Copy link

ffMathy commented Feb 18, 2022

The reason I want a combined [FromRoute] and [FromBody] is because I am using the NuGet package Ardalis.ApiEndpoints, which forces your controller's action method to only have a single argument (a request type).

Ardalis.ApiEndpoints can be found here: https://github.com/ardalis/ApiEndpoints

For instance, consider the following code (EndpointBaseAsync inherits ControllerBase and also has an [ApiController] attribute on it):

public record Request(
    [FromRoute] Guid UserId,
    [FromBody] RequestBody Body);

public record RequestBody(
    string FirstName,
    string LastName);

public class UpdateUserEndpoint : EndpointBaseAsync
    .WithRequest<Request>
    .WithoutResult
{
    [HttpPut]
    [Route("users/{userId}")]
    public override async Task HandleAsync(
        [FromRoute] Request request,
        CancellationToken cancellationToken = default)
    {
        
    }
}

With the above, Swashbuckle generates this example. Notice how the FirstName and LastName properties incorrectly come from the "path", where as it should be a response body.

image

Accessing the endpoint from Postman works though. If I make the following request:

PUT /users/foobar
{
  "firstName": "Jonathan",
  "lastName": "Peterson"
}

And place a breakpoint, the request object correctly has all values (including both the route parameter and the body parameters).

But Swashbuckle should be recognizing that the firstName and lastName are part of the body, not path parameters.

Tested using latest dotnet (6.0) and latest Swashbuckle (6.2.3) as of writing.

More context (if interested): ardalis/ApiEndpoints#42

@ffMathy
Copy link
Author

ffMathy commented Feb 21, 2022

Workaround: If I change RequestBody and Request into classes, everything works as it should.

@nZeus
Copy link

nZeus commented Jul 14, 2022

Nice workaround.
I did a bit of investigation, and I know why it didn't work with the record types.

When you declare it like this:

public record Request(
    [FromRoute] Guid UserId,
    [FromBody] RequestBody Body);

you add attributes to the constructor parameters, not to the properties of your class/record.

So, in your case you could also keep it as a record, but declare it as:

public record Request
{
    [FromRoute] 
    public Guid UserId { get; init; }

    [FromBody]
    public RequestBody Body { get; init; } 
}

Copy link
Contributor

This issue is stale because it has been open for 60 days with no activity. It will be automatically closed in 14 days if no further updates are made.

@github-actions github-actions bot added the stale Stale issues or pull requests label Apr 29, 2024
@martincostello martincostello added help-wanted A change up for grabs for contributions from the community and removed stale Stale issues or pull requests labels Apr 29, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
help-wanted A change up for grabs for contributions from the community
Projects
None yet
Development

No branches or pull requests

3 participants