Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Null response returns a 204

My controller returns a 204 when I do a GET request and I don't find any data.

[Route("user/v1/[controller]")]
public class UserLoginController : Controller
{
    [HttpGet]
    public async Task<UserLogin> Get(int userId)
    {
        var userLoginLogic = new UserLoginLogic();

        return await userLoginLogic.GetUserLogin(userId);
    }
}

This is only for GET requests, POST, PUT, DELETE return a 200 empty response. This messes with my swagger definition which has a response defined for a 200 response, and I would rather be consistent.

The 204 would be fine if I was serving HTML out of this controller but it is for a REST API.

How do I get it to return a 200?

like image 526
Cale Avatar asked Jul 18 '18 22:07

Cale


People also ask

How do I fix 204 No Content response?

By default, 204 (No Content) the response is cacheable. If caching needs to be overridden then the response must include cache respective cache headers. For example, you may want to return status 204 (No Content) in UPDATE operations where request payload is large enough not to transport back and forth.

Can a 204 response have a body?

The 204 response MUST NOT include a message-body, and thus is always terminated by the first empty line after the header fields.

What is the difference between 200 and 204 status code?

The 204 (No Content) status code indicates that the server has successfully fulfilled the request and that there is no additional content to send in the response payload body. While 200 OK being a valid and the most common answer, returning a 204 No Content could make sense as there is absolutely nothing to return.

Can post return 204?

From the service's perspective, a 204 (No Content) response may be a perfectly valid response to a POST, PUT or DELETE request.


2 Answers

With the new ActionResult<T> in v2.1+ you can also refactor to specifically tell the controller to return Ok 200 using the Ok() helper methods

[Route("user/v1/[controller]")]
public class UserLoginController : Controller {
    [HttpGet]
    public async Task<ActionResult<UserLogin>> Get(int userId) {
        var userLoginLogic = new UserLoginLogic();
        var model = await userLoginLogic.GetUserLogin(userId);
        return Ok(model);
    }
}

however this can be misleading if there is in fact no content to return. Consider using an appropriate response status

[Route("user/v1/[controller]")]
public class UserLoginController : Controller {
    [HttpGet]
    public async Task<ActionResult<UserLogin>> Get(int userId) {
        var userLoginLogic = new UserLoginLogic();
        var model = await userLoginLogic.GetUserLogin(userId);
        if(model == null) return NotFound(); //404
        return Ok(model); //200
    }
}

If intent on returning 200 Ok with no content use ControllerBase.Ok() method

Creates a OkResult object that produces an empty Status200OK response.

[Route("user/v1/[controller]")]
public class UserLoginController : Controller {
    [HttpGet]
    public async Task<ActionResult<UserLogin>> Get(int userId) {
        var userLoginLogic = new UserLoginLogic();
        var model = await userLoginLogic.GetUserLogin(userId);
        if(model == null) return Ok(); //200 with no content
        return Ok(model); //200
    }
}

Reference Controller action return types in ASP.NET Core Web API:

like image 155
Nkosi Avatar answered Nov 04 '22 23:11

Nkosi


See:

  • https://learn.microsoft.com/en-us/aspnet/core/web-api/advanced/formatting?view=aspnetcore-3.1#special-case-formatters
  • https://www.colabug.com/2020/0224/7036191/
  • https://weblog.west-wind.com/posts/2020/Feb/24/Null-API-Responses-and-HTTP-204-Results-in-ASPNET-Core

services.AddControllers(opt =>  // or AddMvc()
{
    // remove formatter that turns nulls into 204 - No Content responses
    // this formatter breaks Angular's Http response JSON parsing
    opt.OutputFormatters.RemoveType<HttpNoContentOutputFormatter>();
})
like image 30
McKabue Avatar answered Nov 04 '22 21:11

McKabue