aspnet / Announcements

Subscribe to this repo to be notified about major changes in ASP.NET Core and Entity Framework Core
Other
1.66k stars 80 forks source link

[Breaking change]: ActionResult<T> set StatusCode to 200 #485

Open brunolins16 opened 2 years ago

brunolins16 commented 2 years ago

Description

When returning a T in a MVC/API Controller Action that declares the return type as ActionResult<T> will now always set the ObjectResult.StatusCode to 200, unless when the T is a ProblemDetails.

Since before this change the ObjectResult.StatusCode was null, in some scenarios where the status code is set manually, this change could cause unexpected behaviors. Also, an Action Filter could be affected by this change if it expects the null instead of 200.

Version

.NET 6

Previous behavior

Before if you have a Controller's Action that returns T and sets the Response.StatusCode manually, similar to the example:


// Generates a 202 Accepted response
public ActionResult<Model> Get()
{
    Response.StatusCode = StatusCodes.Status202Accepted;
    return new Model();
}

It will generate the expected 202 Accepted response status code.

New behavior

After the changes the same Controller's Action that returns T that sets the Response.StatusCode manually, will always generate a 200 OK response.


// Generates a 200 OK response
public ActionResult<Model> Get()
{
    Response.StatusCode = StatusCodes.Status202Accepted;
    return new Model();
}

Type of breaking change

Reason for change

This behavior is documented since ASP.NET Core 3.1 (https://docs.microsoft.com/en-us/aspnet/core/web-api/action-return-types?view=aspnetcore-3.1#actionresultt-type), however, it keeps the StatusCode as null that will eventually generate a 200 OK response as default. Since the default internal behavior could easily change, was decided to avoid relying on the internal default implementation and setting the StatusCode to the expected 200 OK.

Recommended action

If you are broken by this change, as the example mentioned before:

public ActionResult<Model> Get()
{
    Response.StatusCode = StatusCodes.Status202Accepted;
    return new Model();
}

You will need to change your Controller Action. These are some possible options that will keep the desired behavior:

public ActionResult<Model> Get()
{
   return Accepted(new Model());
}

//or

public ActionResult<Model> Get()
{
   return StatusCode(StatusCodes.Status202Accepted, new Model());
}

//or

public Model Get()
{
   Response.StatusCode = StatusCodes.Status202Accepted;
   return new Model();
}

Affected APIs

MVC/API Controller actions.