0

So, I've been implementing a Web API in ASP.NET MVC and have everything working.

But now I have a need to return special status information. So I know I can just return a custom class from the API, and the caller can deserialize that to an object. But, in this case, what happens if my API throws an exception?

MVC seems to automatically return information about an exception and I'm curious how that logic would meld with my logic to return a custom class result.

I realize I can use a try...catch block, but if there is an exception, it seems like I may want to keep the logic MVC has in place for returning appropriate values.

2 Answers 2

1

If you want to ensure that the api returns the same class even if an error occurs I would use the ExceptionFilters

Create your own implementation of IHttpActionResult

public class FormatErrorResponse : IHttpActionResult
{
    public HttpRequestMessage Request { get; set; }
    public Exception exception { get; set; }

    public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
    {
        //Here, create the response you want to be returned when an exception occurs 

        //Here's my implementation of it where ErrorObj is my custom class which formats the exception the way I want
        var response = Request.CreateResponse<ErrorObj>(HttpStatusCode.InternalServerError, ErrorObj.GetError(exception));
        response.RequestMessage = Request;
        return Task.FromResult(response);   
    }
}

Then create the filter where you use the FormatErrorResponse class

public class ExceptionProvider : IExceptionHandler
{
    public virtual Task HandleAsync(ExceptionHandlerContext context,
                                    CancellationToken cancellationToken)
    {
        if (!ShouldHandle(context))
        {
            return Task.FromResult(0);
        }

        return HandleAsyncCore(context, cancellationToken);
    }

    public virtual Task HandleAsyncCore(ExceptionHandlerContext context,
                                       CancellationToken cancellationToken)
    {
        HandleCore(context);
        return Task.FromResult(0);
    }

    public virtual void HandleCore(ExceptionHandlerContext context)
    {
        //Use the FormatErrorResponse here
        context.Result = new FormatErrorResponse
        {
            Request = context.ExceptionContext.Request,
            exception = context.Exception
        };
    }

    public virtual bool ShouldHandle(ExceptionHandlerContext context)
    {

        return context.ExceptionContext.CatchBlock.IsTopLevel;
    }
}

Finally, attach the filter to the HttpConfiguration in the WebApiConfig class

config.Services.Replace(typeof(IExceptionHandler), new ExceptionProvider());
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for this, but is this what everyone who returns a custom class does? I mean, a lot of Web APIs return custom classes. If they don't always implement code like this, how does the client handle the return value when it could be of different types?
@JonathanWood I would say this would be the web api way to do it. Another way is to use Global.asax class but then the code is commited to IIS. How the client handle return values is rather wide question, I usually make sure to allways know which return value which comes with a specific http return code. Like, when 200 I know it's my DTO.class and when 500 etc I know its my error class
1

Unhandled Exceptions can be handled in the Application_Error function of Global.asax. Alternatively, you could use exception filters, See Exception Filters on Microsoft Docs

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.