Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Returning error string from MVC6/WepApi controller

The template WebApi controller in MVC6/WebApi implements an action that returns a collection for the Get method like this:

[HttpGet]
public IEnumerable<MyEntity> Get()
{
    //my code to return entities
}

Assuming that my code to return the result throws an exception, how would I return an error message to the consumer?

As far as I noticed an exception would result in HTTP 500. This is fine but I would like to give the caller a message telling him what went wrong. Because of the signature of the template action I can not catch the exception and return some Http*** or ObjectResult instance.

like image 428
NicolasR Avatar asked Mar 09 '16 01:03

NicolasR


1 Answers

You will need to add some piece of code yourself that will handle errors and return a message.

One option is to use an exception filter and add it either globally or on selected controllers, although this approach would only cover exceptions coming from the controller action methods. For example the following filter will return a json object only when the request accept was application/json (Otherwise it would let the exception pass through which for example could be handled by the global error page):

public class CustomJSONExceptionFilter : ExceptionFilterAttribute
{    
    public override void OnException(ExceptionContext context)
    {
        if (context.HttpContext.Request.GetTypedHeaders().Accept.Any(header => header.MediaType == "application/json"))
        {
            var jsonResult = new JsonResult(new { error = context.Exception.Message });
            jsonResult.StatusCode = Microsoft.AspNetCore.Http.StatusCodes.Status500InternalServerError;
            context.Result = jsonResult;
        }
    }
}

services.AddMvc(opts => 
{
    //Here it is being added globally. 
    //Could be used as attribute on selected controllers instead
    opts.Filters.Add(new CustomJSONExceptionFilter());
});

Another option is You can change the signature to make providing a response more flexible. Then you can handle the error like one normally would and then return a user friendly error message.

public IActionResult Get() {
    try {
        IEnumerable<MyEntity> result;
        //...result populated
       return new HttpOkObjectResult(result);
    } catch (Exception ex) {
        //You should handle the error
        HandleError(ex);//the is not an actual method. Create your own.
        //You could then create your own error so as not to leak
        //internal information.
        var error = new 
            { 
                 message = "Enter you user friendly error message",
                 status = Microsoft.AspNetCore.Http.StatusCodes.Status500InternalServerError
            };
        Context.Response.StatusCode = error.status;            
        return new ObjectResult(error);
    }
}
like image 97
Nkosi Avatar answered Oct 17 '22 19:10

Nkosi