Error Logging in ASP.NET Web API Using Custom Exception Filters

Introduction

This article explores how to implement centralized error logging and custom error responses in ASP.NET Web API applications using exception filters. When building APIs, proper error handling and logging are essential for debugging, monitoring, and providing meaningful feedback to API consumers.

Implementation

Exception Filter

The following exception filter attribute captures all unhandled exceptions thrown during API request processing and transforms them into structured error responses:

[AttributeUsage(AttributeTargets.All, AllowMultiple = false, Inherited = true)]
public sealed class GlobalExceptionFilterAttribute : ExceptionFilterAttribute
{
    public override void OnException(HttpActionExecutedContext context)
    {
        base.OnException(context);
        context.Response = CreateErrorResponse(context);
    }

    private HttpResponseMessage CreateErrorResponse(HttpActionExecutedContext context)
    {
        var requestUrl = context.ActionContext.Request.RequestUri.ToString();
        var httpMethod = context.ActionContext.Request.Method.ToString();
        var controllerType = context.ActionContext.ActionDescriptor.ControllerDescriptor.ControllerType.FullName;
        var actionName = context.ActionContext.ActionDescriptor.ActionName;
        var requestParameters = context.ActionContext.ActionArguments;
        var clientIp = HttpContext.Current.Request.UserHostAddress;

        // Log the exception details
        ExceptionLogger.Log(
            $"API Error - URL:{requestUrl}, " +
            $"Parameters:{requestParameters.ToJson()}, " +
            $"Exception:{context.Exception.ToJson()}");

        var errorPayload = new
        {
            StatusCode = 506,
            Message = $"{context.Exception.Message}, Request URL: {requestUrl}",
            Details = context.Exception
        };

        return ResponseBuilder.CreateJsonResponse(errorPayload);
    }
}

Response Helper

This utility class provides methods for creating standardized JSON HTTP responses:

public static class ResponseBuilder
{
    public static HttpResponseMessage CreateJsonResponse(object content)
    {
        string jsonContent;

        if (content is string || content is char)
        {
            jsonContent = content.ToString();
        }
        else
        {
            jsonContent = JsonConvert.SerializeObject(content, new JsonSerializerSettings
            {
                ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
                DateFormatString = "yyyy-MM-dd HH:mm:ss"
            });
        }

        return new HttpResponseMessage
        {
            Content = new StringContent(jsonContent, Encoding.GetEncoding("UTF-8"), "application/json")
        };
    }

    public static string ToJson(this object target)
    {
        return JsonConvert.SerializeObject(target, new JsonSerializerSettings
        {
            ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
            DateFormatString = "yyyy-MM-dd HH:mm:ss"
        });
    }
}

Registration

To activate the exception filter globally, register it in the Web API configuration:

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        config.Filters.Add(new GlobalExceptionFilterAttribute());
        config.MapHttpAttributeRoutes();
        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );
    }
}

The filter automatically intercepts exceptions from all controllers decorated with the [ApiController] attribute or inheriting from ApiController, providing consistent error hadnling across the entire API surface.

Posted on Mon, 29 Jun 2026 16:32:55 +0000 by swathin2