Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MVC 6 HttpResponseException

I am trying to return status codes in the following way

throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.Unauthorized) { ReasonPhrase = "invalid username/password" });

now this is not supported in MVC6, which sucks because using IActionResult seems really silly to me, and way less intuitive. I have found the following posts one and two. the first leads to a broken link, and the second applies to an MVC application.

I did realize that I need to create a middleware to address this issue, but I am not sure where to start, and since this is pretty useful stuff, I would expect there to be some open source solution I could use or maybe a code snippet.

For the record, I am using ASP.net 5 rc1 update 1 MVC 6

like image 610
gilmishal Avatar asked Feb 21 '16 13:02

gilmishal


People also ask

How do I register an exception filter globally?

To apply the filter globally to all Web API controllers, add an instance of the filter to the GlobalConfiguration. Configuration. Filters collection. Exception filters in this collection apply to any Web API controller action.

How do I return an exception from Web API?

Return InternalServerError for Handled Exceptionscs file and locate the Get(int id) method. Add the same three lines within a try... catch block, as shown in Listing 2, to simulate an error. Create two catch blocks: one to handle a DivideByZeroException and one to handle a generic Exception object.

How do you handle exceptions in .NET core API?

To handle exceptions we can use the try-catch block in our code as well as finally keyword to clean up resources afterward. Even though there is nothing wrong with the try-catch blocks in our Actions in Web API project, we can extract all the exception handling logic into a single centralized place.


1 Answers

I think this change is due to .NET Core - where ASP.NET tries to do everything out of the box, ASP.NET Core only does what you specifically tell it to (which is a big part of why it's so much quicker and portable).

If you want this behaviour in Core you need to add it, either as a package that someone has written for you or by rolling your own.

It's fairly simple. First you need a custom exception to check for:

public class StatusCodeException : Exception
{
    public StatusCodeException(HttpStatusCode statusCode)
    {
        StatusCode = statusCode;
    }

    public HttpStatusCode StatusCode { get; set; }
}

Then you need a RequestDelegate handler that checks for the new exception and converts it to the HTTP response status code:

public class StatusCodeExceptionHandler
{
    private readonly RequestDelegate request;

    public StatusCodeExceptionHandler(RequestDelegate next)
    {
        this.request = next;
    }

    public Task Invoke(HttpContext context) => this.InvokeAsync(context); // Stops VS from nagging about async method without ...Async suffix.

    async Task InvokeAsync(HttpContext context)
    {
        try
        {
            await this.request(context);
        }
        catch (StatusCodeException exception)
        {
            context.Response.StatusCode = (int)exception.StatusCode;
            context.Response.Headers.Clear();
        }
    }
}

Then you register this middleware in your startup:

public class Startup
{
    ...

    public void Configure(IApplicationBuilder app)
    {
        ...
        app.UseMiddleware<StatusCodeExceptionHandler>();

Finally you can throw the HTTP status code exception in your actions, while still returning an explicit type that you can easily unit test:

public Thing Get(int id) {
    Thing thing = GetThingFromDB();

    if (thing == null)
        throw new StatusCodeException(HttpStatusCode.NotFound);

    return thing;
}

This is fairly simple and someone out there has probably written a more complete one, but I haven't been able to find one or get a clear answer as to why this was dropped.

like image 98
Keith Avatar answered Oct 21 '22 05:10

Keith