Creating Custom Web API Filters in .NET
A complete guide on creating, applying, and managing custom filters for your .NET Web API applications.
Introduction to Web API Filters
In any web API, filters are essential for handling cross-cutting concerns such as logging, validation, authorization, and error handling. Custom Web API filters in .NET allow developers to implement these concerns in a modular, reusable manner, separating them from business logic and keeping code cleaner and more maintainable.
Filters in .NET Web API are attributes that can be applied to controllers or actions to execute code before or after the action is executed. They can also be used to handle errors, perform authentication, or implement logging logic.
Types of Filters in .NET Web API
In .NET Web API, filters are categorized into different types, each serving a specific purpose:
- Authorization Filters: Handle user authorization, ensuring that the user has the right to access the resource.
- Action Filters: Perform logic before or after an action method is called, like logging and caching.
- Result Filters: Modify the result returned by the action method before sending it to the client.
- Exception Filters: Handle exceptions thrown during the execution of the action.
- Custom Filters: These can be created to implement your own functionality like custom logging, performance monitoring, or more complex tasks.
Creating Custom Web API Filters
Custom filters in .NET Web API are created by inheriting from the appropriate filter interface. Let’s go through a few examples of how to create custom filters.
Creating a Custom Authorization Filter
Authorization filters are used to check whether a user has the necessary permissions to access a given resource.
public class CustomAuthorizationFilter : IAuthorizationFilter
{
public void OnAuthorization(HttpActionContext actionContext)
{
var user = actionContext.ControllerContext.RequestContext.Principal;
if (user == null || !user.Identity.IsAuthenticated)
{
actionContext.Response = new HttpResponseMessage(HttpStatusCode.Unauthorized);
}
}
}
This filter checks whether the user is authenticated. If not, it returns a 401 Unauthorized status code.
Creating a Custom Action Filter
Action filters are executed before or after the action method runs. Let’s create a filter that logs method execution time.
public class LogExecutionTimeFilter : IActionFilter
{
public void OnActionExecuting(HttpActionContext actionContext)
{
actionContext.Request.Properties["StartTime"] = DateTime.Now;
}
public void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
{
var startTime = (DateTime)actionExecutedContext.Request.Properties["StartTime"];
var executionTime = DateTime.Now - startTime;
// Log execution time
Console.WriteLine($"Execution Time: {executionTime.TotalMilliseconds} ms");
}
}
This filter logs the execution time of the action method.
Applying Filters to Web API Methods
Filters can be applied to individual action methods or globally to all actions in the Web API project. To apply a filter to a specific action or controller, simply add the filter as an attribute:
[CustomAuthorizationFilter]
public IHttpActionResult GetSensitiveData()
{
// Your action code here
}
To apply the filter globally, add it to the GlobalConfiguration.Filters
collection in the WebApiConfig.cs
file:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.Filters.Add(new LogExecutionTimeFilter());
}
}
Filter Ordering in .NET
In .NET Web API, the order in which filters are executed is important. Filters are executed in the following order:
- Authorization Filters
- Action Filters
- Result Filters
- Exception Filters
Custom filters will be executed based on this order. You can also control the order of custom filters by specifying the Order
property when adding filters:
public static void Register(HttpConfiguration config)
{
config.Filters.Add(new LogExecutionTimeFilter() { Order = 1 });
}
Advanced Custom Filter Examples
Custom Exception Filter
Exception filters handle exceptions thrown by action methods. Let’s create a custom exception filter to return a specific error response:
public class CustomExceptionFilter : IExceptionFilter
{
public void OnException(HttpActionExecutedContext context)
{
var exception = context.Exception;
context.Response = context.Request.CreateErrorResponse(HttpStatusCode.InternalServerError, "An error occurred: " + exception.Message);
}
}
Custom Result Filter
Result filters modify the action result before it’s sent to the client. Here’s an example of a custom result filter that adds a custom header to the response:
public class CustomResultFilter : IResultFilter
{
public void OnResultExecuting(HttpActionContext actionContext)
{
actionContext.Response.Headers.Add("X-Custom-Header", "This is a custom header");
}
public void OnResultExecuted(HttpActionExecutedContext actionExecutedContext)
{
// Logic after the result is executed
}
}
Common Use Cases for Web API Filters
- Authorization: Restrict access to specific resources based on user roles or claims.
- Logging: Log API request and response details for debugging and monitoring.
- Input Validation: Validate incoming data before processing in controller actions.
- Exception Handling: Manage global exception handling across all Web API methods.
- Performance Monitoring: Measure API method execution times and log performance metrics.
Best Practices for Using Filters
- Keep Filters Focused: Filters should be focused on a single responsibility, whether that’s logging, authorization, validation, or exception handling. This ensures maintainability and reusability.
- Apply Filters Globally When Possible: Instead of adding filters to each controller or action individually, apply them globally to reduce duplication and ensure consistency across your Web API.
- Use Dependency Injection (DI): When creating custom filters, use dependency injection to manage dependencies rather than hard-coding them into the filter, which promotes flexibility and testability.
- Handle Errors Gracefully: Always ensure that exception filters return clear and appropriate error messages, which help users and developers understand what went wrong.
- Ensure Filter Performance: Avoid adding complex logic to filters that could impact performance. Filters should be lightweight to prevent slowing down the overall application.
Conclusion
Creating custom Web API filters in .NET is an effective way to handle common cross-cutting concerns such as logging, validation, authorization, and error handling. By utilizing the built-in filter types (authorization, action, result, and exception filters) and creating custom ones, you can implement reusable logic that improves the maintainability and scalability of your application.
In this blog, we have explored how to create and apply custom Web API filters, manage their execution order, and shared examples of advanced filter implementations. By following best practices, you can enhance your API’s functionality while keeping the codebase clean and manageable.
If you have any questions or feedback, feel free to share them in the comments section below. Happy coding!