Explaining IResultFilter in ASP.NET Core

In this article, we will cover ASP.NET Core IResultFilter. 

Please refer to my previous article:

So, Let's get started.

Result Filter in ASP.NET Core

Result Filters are a specific type of filter that runs after the action method has been executed but before the result is processed and sent to the client. This means that with Result Filters, we can modify the view or the result data before it is returned to the client.

IResultFilter

IResultFilter is one of the filter interfaces that you can implement to run custom logic just before and after the execution of an action result in a controller.

Advantages of IResultFilter

Separation of Concerns: By implementing `IResultFilter`, you can separate cross-cutting concerns (like logging, caching, or modifying the response) from your core business logic. This leads to cleaner and more maintainable code.

Centralized Logic: If you want to apply the same logic to multiple controllers or actions, you can do so in one place, making it easier to manage and update.

Access to Action Results: `IResultFilter` allows you to inspect or modify the action result before it is sent to the client. This can be useful for transforming responses, adding headers, or even changing result formats (like converting objects to different response types).

Asynchronous Support: You can use asynchronous implementations of `IResultFilter`, allowing for non-blocking operations if necessary. This can be beneficial if your filter logic involves I/O operations (like database calls or external services).

Built-in Dependency Injection: Like many ASP.NET Core components, filters can utilize the built-in dependency injection system, allowing you to easily inject required services

Disadvantages of IResultFilter

Complexity: Overusing filters can lead to complex code that is difficult to follow and debug. If business logic is placed in filters, it can be hard to determine where certain behaviors come from when looking at action methods alone.

Global Impact: If a filter is applied globally, it can unintentionally affect all actions in the application. This might lead to undesirable side effects if not carefully managed.

Performance Overhead: Adding multiple filters can introduce performance overhead, especially if the filtering logic is complex or involves multiple I/O operations. It’s essential to keep performance in mind when using filters extensively.

Debugging Challenges: Issues related to filters can sometimes be difficult to diagnose, as the flow of execution may not be straightforward, especially if multiple filters are influencing the same request.

Limited by Interface Scope: The interface has a defined scope of operations and might not cover all use cases you may want to handle. Depending on your scenario, you might need to combine it with other filters or use middleware for more complex request/response manipulation.

Example

public class CustomResultFilterAttribute : IResultFilter
{
    public override void OnResultExecuting(ResultExecutingContext context)
    {
        // This method is called before the result is executed.
        LogMessage("Executing custom result filter attribute before result execution.\n");
    }

    public override void OnResultExecuted(ResultExecutedContext context)
    {
        // This method is called after the result has been executed.
        LogMessage("Executing custom result filter attribute after result execution.\n");
    }

    private void LogMessage(string message)
    {
        string filePath = Path.Combine(Directory.GetCurrentDirectory(), "Log", "Log.txt");

        //saving the data in a text file called Log.txt
        File.AppendAllText(filePath, message);
    }
}
// Register the filter in Startup.cs

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers(options =>
    {
        options.Filters.Add<CustomResultFilterAttribute>();
    });
}

// Above .net 6

builder.Services.AddScoped<CustomResultFilterAttribute>();
public class HomeController : Controller
{
    [CustomResultFilterAttribute]
    public IActionResult Index()
    {
        return View();
    }
}

Logging Log messages 

IResultFIlter

File path

Log Path file

Log Creation on file path

Log Creation on file path