Global Filters
4/22/26Less than 1 minute
Global Filters
In addition to applying IApiFilterAttribute subclass attributes in interface declarations, you can also register IApiFilter type filters during interface configuration.
These filters apply to the entire interface and execute before IApiFilterAttribute filters applied via attributes.
Configuring Global Filters
services.AddHttpApi<IUserApi>().ConfigureHttpApi(o =>
{
o.GlobalFilters.Add(new UserFilter());
});Implementing Custom Filters
public class UserFilter : IApiFilter
{
public async Task OnRequestAsync(ApiRequestContext context)
{
// Pre-request processing
var userContext = context.HttpContext.ServiceProvider.GetRequiredService<IUserContext>();
context.HttpContext.RequestMessage.Headers.Add("X-User-Id", userContext.UserId);
}
public async Task OnResponseAsync(ApiResponseContext context)
{
// Post-response processing
var response = context.HttpContext.ResponseMessage;
// Logging, monitoring, etc.
}
}Filter Execution Order
- Interface-level
GlobalFilters(in order of addition) - Interface-declared
IApiFilterAttributeattributes - Method-declared
IApiFilterAttributeattributes
Common Use Cases
Request Signing
public class SignFilter : IApiFilter
{
public async Task OnRequestAsync(ApiRequestContext context)
{
var signService = context.HttpContext.ServiceProvider.GetRequiredService<SignService>();
var sign = signService.SignValue(DateTime.Now);
context.HttpContext.RequestMessage.AddUrlQuery("sign", sign);
}
public Task OnResponseAsync(ApiResponseContext context) => Task.CompletedTask;
}
services.AddHttpApi<IExternalApi>().ConfigureHttpApi(o =>
{
o.GlobalFilters.Add(new SignFilter());
});Request Logging
public class RequestLoggingFilter : IApiFilter
{
private readonly ILogger<RequestLoggingFilter> _logger;
public RequestLoggingFilter(ILogger<RequestLoggingFilter> logger)
{
_logger = logger;
}
public async Task OnRequestAsync(ApiRequestContext context)
{
var request = context.HttpContext.RequestMessage;
_logger.LogInformation("Request: {Method} {Uri}", request.Method, request.RequestUri);
}
public async Task OnResponseAsync(ApiResponseContext context)
{
var response = context.HttpContext.ResponseMessage;
_logger.LogInformation("Response: {StatusCode}", response.StatusCode);
}
}Tenant Context Injection
public class TenantFilter : IApiFilter
{
public async Task OnRequestAsync(ApiRequestContext context)
{
var tenantContext = context.HttpContext.ServiceProvider.GetRequiredService<ITenantContext>();
context.HttpContext.RequestMessage.Headers.Add("X-Tenant-Id", tenantContext.TenantId);
}
public Task OnResponseAsync(ApiResponseContext context) => Task.CompletedTask;
}Dependency Injection
Global filters support constructor dependency injection:
services.AddHttpApi<IUserApi>().ConfigureHttpApi(o =>
{
o.GlobalFilters.Add(new SignFilter()); // If SignFilter has dependencies, register it in DI first
});
// Or use factory method
services.AddHttpApi<IUserApi>().ConfigureHttpApi((o, sp) =>
{
o.GlobalFilters.Add(sp.GetRequiredService<SignFilter>());
});