How do I configure the response type of a void
/Task
action method to be 204 No Content
rather than 200 OK
?
For example, consider a simple controller:
public class MyController : Controller
{
[HttpPost("foo")]
public async Task Foo() {
await Task.CompletedTask;
}
[HttpPost("bar")]
public async Task<IActionResult> Bar() {
await Task.CompletedTask;
return NoContent();
}
}
I'd like both methods to return 204 No Content
, but the default (and thus what /foo
returns) seems to be 200 OK
. I tried various things, such as adding a [ProducesResponseType(204)]
attribute to /foo
, but I haven't found anything that seems to have any effect.
The IActionResult return type is appropriate when multiple ActionResult return types are possible in an action. The ActionResult types represent various HTTP status codes. Any non-abstract class deriving from ActionResult qualifies as a valid return type.
A Web API controller action can return any of the following: void. HttpResponseMessage. IHttpActionResult.
Here is a solution that returns 204 instead of 200 for all controller methods that return void
or Task
. First, create a result filter:
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.AspNetCore.Mvc.Filters;
using static Microsoft.AspNetCore.Http.StatusCodes;
namespace StackOverflow.SampleCode
{
/// <summary>
/// A filter that transforms http status code 200 OK to 204 No Content for controller actions that return nothing,
/// i.e. <see cref="System.Void"/> or <see cref="Task"/>.
/// </summary>
internal class VoidAndTaskTo204NoContentFilter : IResultFilter
{
/// <inheritdoc/>
public void OnResultExecuting(ResultExecutingContext context)
{
if (context.ActionDescriptor is ControllerActionDescriptor actionDescriptor)
{
var returnType = actionDescriptor.MethodInfo.ReturnType;
if (returnType == typeof(void) || returnType == typeof(Task))
{
context.HttpContext.Response.StatusCode = Status204NoContent;
}
}
}
/// <inheritdoc/>
public void OnResultExecuted(ResultExecutedContext context)
{
}
}
}
Then register the filter globally:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers(options => options.Filters.Add<VoidAndTaskTo204NoContentFilter>());
}
This will affect all your controller methods.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With