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

StatusCode() method broken by [Produces] attribute (AutoWrapper 5.0) #135

Open
nwoolls opened this issue May 10, 2022 · 1 comment
Open

Comments

@nwoolls
Copy link

nwoolls commented May 10, 2022

I am trying to upgrade AutoWrapper from 4.5 to 5.0 in order to work around the problems reported in issue #133.

In doing so, I've found a problem that does not seem to exist in 4.5, and am hoping you can provide some advice.

The problem is that, when using the controller's StatusCode() method to return a status code, if the controller or action has the [Produces("application/json")] attribute, the result is returned as a string rather than an object. As seen in the details of issue #133, this does not seem to be the case w/ 4.5.

You can reproduce this with the following steps.

From the command line:

dotnet --version 
6.0.101 
mkdir autowrapper-statuscode-issue 
cd autowrapper-statuscode-issue/ 
dotnet new webapi 
dotnet add package AutoWrapper.Core --version 5.0.0-rc-03 

Edit Program.cs and add:

var options = new AutoWrapperOptions
{
    IsDebug = app.Environment.IsDevelopment()
};
app.UseAutoWrapper(options);

Edit WeatherForecastController.cs and add:

public class InputModel
{
    [Required(AllowEmptyStrings = false)]
    public string? FirstName { get; set; }
}

[HttpPost("foo")]
[Produces("application/json")]
public IActionResult PostFoo(InputModel inputModel)
{
    if (inputModel.FirstName == "foo")
    {
        return StatusCode(StatusCodes.Status400BadRequest, "An error occurred - returning status code");
    }
    
    return StatusCode(StatusCodes.Status201Created);
}

[HttpPost("bar")]
public IActionResult PostBar(InputModel inputModel)
{
    if (inputModel.FirstName == "bar")
    {
        return StatusCode(StatusCodes.Status400BadRequest, "An error occurred - returning status code");
    }
    
    return StatusCode(StatusCodes.Status201Created);
}

Run the project.

The following are examples where the result may either by an object or a string:

Example 1 - Returns a string

curl -X 'POST' \
  'https://localhost:7284/WeatherForecast/foo' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "firstName": "foo"
}'
"An error occurred - returning status code"

Example 2 - returns an object

curl -X 'POST' \
  'https://localhost:7284/WeatherForecast/bar' \
  -H 'accept: text/plain' \
  -H 'Content-Type: application/json' \
  -d '{
  "firstName": "bar"
}'
{
  "isError": true,
  "errors": null,
  "validationErrors": null,
  "type": "https://httpstatuses.com/400",
  "title": "Bad Request",
  "status": 400,
  "detail": "An error occurred - returning status code",
  "instance": "/WeatherForecast/bar"
}

Please note that, while this is the minimal set of steps to reproduce the issue, in my larger and more complex project, where both ASP.NET Core MVC and API are hosted in a single project, removing the [Produces] attribute is not enough to work around the issue. The result is still being encoded as JSON by (some) middleware before it reaching AutoWrapper.

@nwoolls nwoolls changed the title StatusCode() method broken by [Produces] attribute StatusCode() method broken by [Produces] attribute (AutoWrapper 5.0) May 10, 2022
@nwoolls
Copy link
Author

nwoolls commented May 10, 2022

I was able to confirm that this issue does not exist w/ AutoWrapper 4.5 by taking the above documented sample and making the following changes:

Edit the .csproj:

<PackageReference Include="AutoWrapper.Core" Version="4.5.0" />

Edit Program.cs:

var options = new AutoWrapperOptions
{
    IsDebug = app.Environment.IsDevelopment(),
    UseApiProblemDetailsException = true
};
app.UseApiResponseAndExceptionWrapper(options);

The following request:

curl -X 'POST' \
  'https://localhost:7050/WeatherForecast/foo' \
  -H 'accept: */*' \
  -H 'Content-Type: application/json' \
  -d '{
  "firstName": "foo"
}'

Now results in:

{
  "isError": true,
  "errors": null,
  "validationErrors": null,
  "details": null,
  "type": "https://httpstatuses.com/400",
  "title": "Bad Request",
  "status": 400,
  "detail": "An error occurred - returning status code",
  "instance": "/WeatherForecast/foo"
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant