0

I have a controller method that I'm using to validate a token. I have it set up to return a boolean value and then on the front end, which makes an API call into the controller, I have an if/else if block set up to handle the result.

If the result is false, I want to throw a BadRequest so that I can present an error message to the user. I really want this handled on the back end rather than on the front end. I thought maybe I could wrap a boolean in an ActionResult, but that doesn't seem to be working. It only works when I return either a true or a false (I know, it's a boolean, so that should be obvious, but I thought the ActionResult wrapper might let me return a BadRequest).

Any advice on how I can do this?

public async Task<ActionResult<bool>> ValidateStuff(params)
{
    return BadRequest("BAD REQUEST!");
}
EylM
  • 5,196
  • 2
  • 13
  • 24
PowerGTD
  • 1
  • 1
  • When the param is valid you return Ok and true, and if not valid you return BadRequest and false. Do you think someone can misread the true or false or Ok/BadRequest or what problem do you want to solve with this redundant informations? – Sir Rufo Jul 16 '19 at 20:23
  • I want to return an error message along with the false. You're saying I can return both false and a BadRequest when the method return type is ActionResult? Thanks! – PowerGTD Jul 16 '19 at 20:24
  • 2
    No, I did not say that - I want to say it is as useless as a method returning true if everything was ok and throw an exception if an error occured. The returned bool is only noise. – Sir Rufo Jul 16 '19 at 20:26
  • 3
    The HTTP status code should be more than sufficient to indicate success or failure. **Note:** You should *only* return 400 BAD REQUEST when the request body cannot be read because it is malformed. See https://www.restapitutorial.com/httpstatuscodes.html –  Jul 16 '19 at 20:27
  • I'm returning a bool because on the front end I'm executing one block of code if the value is true and another if the value is false. Along with the code I'm executing for a false result (which includes resetting username and password fields) I want to generate an error message via the BadRequest method. – PowerGTD Jul 16 '19 at 20:35
  • If the operation is a success, return `200 OK` or a `204 NO CONTENT`, and if it is not, return the appropriate error code. –  Jul 16 '19 at 20:43
  • Try just setting the status code you want on the response and returning the data as normal `Response.StatusCode = 400;` – Will Sullivan Jul 16 '19 at 20:44
  • Additional problem, on an error 404 / 500 you'd get undefined from what you propose... So neither if (error.Result === true) nor error.Result === false would hit... But if you fell through to else { /// this would hit } – Austin T French Jul 16 '19 at 20:59
  • I see what everyone is saying that my proposed methodology isn't going to work. What would be the easiest way to go about building a controller method that seeks to validate a token, and if the token is valid, executes a block of code that creates the user, and if it is false, resets all the fields on the login page AND displays an error message ***that is generated on the back end, not the front end*** – PowerGTD Jul 16 '19 at 21:05
  • Again, if it validates, return a `200 OK` or `204 NO CONTENT`, and if it does not validate, return the appropriate HTTP status code with a message indicating why it did not validate. a `400 BAD REQUEST` is **only** appropriate when the request cannot be understood because it is malformed. 4XX codes are for client-caused issues, 5XX codes are for server-side issues where the client cannot be reasonably expected to resolve the issue. –  Jul 16 '19 at 21:10
  • What should my method return type be? Just a plain ActionResult? – PowerGTD Jul 16 '19 at 21:11
  • @PowerGTD I gave you some info... But at this point your last comment is like 4 different questions, and this question (on those comments) has become unanswerable (at least not really further answerable) – Austin T French Jul 16 '19 at 21:44

2 Answers2

0

Don't!

If you want to handle that, then it's fine. But don't return the wrong error code.

You can write custom Authorization or Access decorators ([example documentation])1 and return a 401.

Don't arbitrarily return a code that doesn't equal the problem though, these standards are well defined and understood.

And finally: Another example using HttpResponse

 var msg = new HttpResponseMessage(HttpStatusCode.Unauthorized) { ReasonPhrase = "Oops!!!" };
 throw new HttpResponseException(msg);
Austin T French
  • 4,373
  • 1
  • 18
  • 37
0

It is documented how to handle different return types.

See Controller action return types in ASP.NET Core Web API

IActionResult type

The IActionResult return type is appropriate when multiple ActionResult return types are possible in an action. The ActionResult types represent various HTTP status codes. Some common return types falling into this category are BadRequestResult (400), NotFoundResult (404), and OkObjectResult (200).

Because there are multiple return types and paths in the action, liberal use of the [ProducesResponseType] attribute is necessary. This attribute produces more descriptive response details for API help pages generated by tools like Swagger. [ProducesResponseType] indicates the known types and HTTP status codes to be returned by the action.

Synchronous action

Consider the following synchronous action in which there are two possible return types:

[HttpGet("{id}")]
[ProducesResponseType(typeof(Product), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public IActionResult GetById(int id)
{
    if (!_repository.TryGetProduct(id, out var product))
    {
        return NotFound();
    }

    return Ok(product);
}

In the preceding action, a 404 status code is returned when the product represented by id doesn't exist in the underlying data store. The NotFound helper method is invoked as a shortcut to return new NotFoundResult();. If the product does exist, a Product object representing the payload is returned with a 200 status code. The Ok helper method is invoked as the shorthand form of return new OkObjectResult(product);.

But in your case I would not return any value, because the status code already contains enough information.

[HttpPost]
[ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public async Task<IActionResult> ValidateStuff(params)
{
    if ( !await ValidateAsync(params) )
        return ValidationProblem( 
            new ValidationProblemDetails 
            { 
                Detail = "params are invalid" 
            } );

    return NoContent();
}

If params are valid you will receive the status code 204 and in case of invalid params you will receive the status code 400 with this json as response body

{
  "errors": {},
  "type": null,
  "title": "One or more validation errors occurred.",
  "status": 400,
  "detail": "params are invalid",
  "instance": null,
  "extensions": {}
}
Sir Rufo
  • 16,671
  • 2
  • 33
  • 66