Uniform, consistent error responses from ASP.Net Web API 2

北战南征 提交于 2019-11-30 06:44:08

You can override the DelegatingHandler abstract class and intercept the response to the client. This will give you the ability to return what you want.

Here's some info on it. http://msdn.microsoft.com/en-us/library/system.net.http.delegatinghandler(v=vs.118).aspx

Here's a poster of the Web Api pipeline that shows what can be overriden. http://www.asp.net/posters/web-api/asp.net-web-api-poster.pdf

Create a Handler class like this to override the response

public class MessageHandler1 : DelegatingHandler
{
    protected override Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request, CancellationToken cancellationToken)
    {
        Debug.WriteLine("Process request");
        // Call the inner handler.
        var response = base.SendAsync(request, cancellationToken);

        Debug.WriteLine("Process response");
        if (response.Result.StatusCode == HttpStatusCode.NotFound)
        {
            //Create new HttpResponseMessage message
        }
        ;
        return response;
    }
}

In your WebApiConfig.cs class add the handler.

config.MessageHandlers.Add(new MessageHandler1());

UPDATE As Kiran mentions in the comments you can use the OwinMiddleware to intercept the response going back to the client. This would work for MVC and Web Api running on any host.

Here's an example of how to get the response and change it as it goes to the client.

public class Startup
{
    public void Configuration(IAppBuilder app)
    {
        app.Use(typeof(MyMiddleware)); 
    }
}

public class MyMiddleware : OwinMiddleware
{
    public MyMiddleware(OwinMiddleware next) : base(next) { }

    public override async Task Invoke(IOwinContext context)
    {
        await Next.Invoke(context);
        if(context.Response.StatusCode== 404)
        {
            context.Response.StatusCode = 403;
            context.Response.ReasonPhrase = "Blah";
        }
    }
}

I have done in same way as @Dan H mentioned

 public class ApiGatewayHandler : DelegatingHandler
{
    protected async override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        try
        {
            var response = await base.SendAsync(request, cancellationToken);
            if (response.StatusCode == HttpStatusCode.NotFound)
            {
                var objectContent = response.Content as ObjectContent;
                return await Task.FromResult(new ApiResult(HttpStatusCode.NotFound, VmsStatusCodes.RouteNotFound, "", objectContent == null ? null : objectContent.Value).Response());
            }
            return response;
        }
        catch (System.Exception ex)
        {
            return await Task.FromResult(new ApiResult(HttpStatusCode.BadRequest, VmsStatusCodes.UnHandledError, ex.Message, "").Response());
        }

    }
}

Added routing like below and now it hits the try catch for invalid url

  config.Routes.MapHttpRoute(name: "DefaultApi",routeTemplate: "api/{controller}/{id}",defaults: new { id = RouteParameter.Optional });
        config.Routes.MapHttpRoute(name: "NotFound", routeTemplate: "api/{*paths}", defaults: new { controller = "ApiError", action = "NotFound" });
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!