Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/ServiceComposer/ServiceComposer.AspNetCore/llms.txt

Use this file to discover all available pages before exploring further.

ICompositionRequestFilter introduces a middleware-style pipeline that wraps individual composition handlers. Filters allow you to execute logic before and after a handler runs — for example, to perform authorization checks, enrich request context, measure execution time, or short-circuit a request with an error response. The filter pipeline is structurally identical to ASP.NET Core’s endpoint filter pipeline. Two implementation strategies are available:
  • ICompositionRequestFilter — a class that implements the filter and is associated with a handler via ICompositionRequestFilter<T> or attribute decoration.
  • CompositionRequestFilterAttribute — an abstract attribute that you derive from, allowing filters to be applied directly as class/method attributes.
Available since v2.3.0.

Namespace

ServiceComposer.AspNetCore

Interface definitions

ICompositionRequestFilter

public interface ICompositionRequestFilter
{
    ValueTask<object> InvokeAsync(
        CompositionRequestFilterContext context,
        CompositionRequestFilterDelegate next);
}

ICompositionRequestFilter<T>

public interface ICompositionRequestFilter<T> : ICompositionRequestFilter { }
ICompositionRequestFilter<T> targets a specific handler type T. When you implement this interface, ServiceComposer automatically applies the filter to every composition endpoint served by handler T. This is the preferred approach for associating reusable filters with handlers without modifying the handler class.

CompositionRequestFilterAttribute

CompositionRequestFilterAttribute is an abstract base class that combines Attribute and ICompositionRequestFilter. Derive from it to create an attribute that can be applied directly to a handler class or its Handle method.
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public abstract class CompositionRequestFilterAttribute : Attribute, ICompositionRequestFilter
{
    public abstract ValueTask<object> InvokeAsync(
        CompositionRequestFilterContext context,
        CompositionRequestFilterDelegate next);
}

CompositionRequestFilterContext

Passed to every InvokeAsync call. Provides access to the current HttpContext.
public sealed class CompositionRequestFilterContext
{
    public HttpContext HttpContext { get; }
}
HttpContext
HttpContext
The current ASP.NET Core HttpContext. Use it to inspect or modify the request, access services from the DI container, or write to the response.

CompositionRequestFilterDelegate

The delegate type that represents the remainder of the filter pipeline (or the handler itself):
public delegate ValueTask<object> CompositionRequestFilterDelegate(
    CompositionRequestFilterContext context);
Call next(context) to pass control to the next filter or to the handler. Returning without calling next short-circuits the pipeline and prevents the handler from executing.

Methods

InvokeAsync

context
CompositionRequestFilterContext
required
Contains the HttpContext for the current composition request. Inspect or mutate request/response state here.
next
CompositionRequestFilterDelegate
required
A delegate that invokes the next filter in the pipeline, or the handler if no more filters remain. You must await (or return) the result of next(context) to allow downstream execution to proceed. To short-circuit, return a result without calling next.
Returns ValueTask<object> — the composition result produced by the remainder of the pipeline.

Applying filters

Via attribute on the handler

Derive from CompositionRequestFilterAttribute and apply the attribute to the handler class or Handle method:
using System.Threading.Tasks;
using ServiceComposer.AspNetCore;

public class SampleCompositionFilterAttribute : CompositionRequestFilterAttribute
{
    public override ValueTask<object> InvokeAsync(
        CompositionRequestFilterContext context,
        CompositionRequestFilterDelegate next)
    {
        // Pre-handler logic here
        return next(context);
        // Post-handler logic can be added after awaiting next
    }
}
Apply the attribute to the handler:
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using ServiceComposer.AspNetCore;

public class SampleHandler : ICompositionRequestsHandler
{
    [SampleCompositionFilter]
    [HttpGet("/sample/{id}")]
    public Task Handle(HttpRequest request)
    {
        return Task.CompletedTask;
    }
}

Via typed ICompositionRequestFilter<T>

Implement ICompositionRequestFilter<T> to associate a filter with handler type T without modifying the handler:
using System.Threading.Tasks;
using ServiceComposer.AspNetCore;

public class SampleCompositionFilter : ICompositionRequestFilter<SampleHandler>
{
    public ValueTask<object> InvokeAsync(
        CompositionRequestFilterContext context,
        CompositionRequestFilterDelegate next)
    {
        // Pre-handler logic here
        return next(context);
    }
}
When using ICompositionRequestFilter<T>, the filter is automatically applied to all endpoints handled by T. No attribute decoration on the handler is needed.

Short-circuiting the pipeline

Return a result without calling next to prevent the handler (and any subsequent filters) from executing:
public class AuthorizationFilter : ICompositionRequestFilter<SecureHandler>
{
    public ValueTask<object> InvokeAsync(
        CompositionRequestFilterContext context,
        CompositionRequestFilterDelegate next)
    {
        var user = context.HttpContext.User;
        if (!user.Identity?.IsAuthenticated ?? true)
        {
            context.HttpContext.Response.StatusCode = 401;
            return ValueTask.FromResult<object>(null!);
        }

        return next(context);
    }
}
Short-circuiting a filter prevents all downstream filters and the handler itself from running. Ensure that the response status code and body are set appropriately before returning.

DI registration

ICompositionRequestFilter<T> implementations are discovered automatically by the assembly scanner and registered as transient services. CompositionRequestFilterAttribute subclasses do not need separate DI registration — they are instantiated by the attribute infrastructure. Enable scanning with:
builder.Services.AddViewModelComposition();

Build docs developers (and LLMs) love