Skip to content

ASP.NET Core (Handler to Endpoint)

Shiny Mediator now can map up your request handlers to ASP.NET Core endpoints using the minimal API. This saves you the effort of implementing the following boilerplate over and over and over again

app.MapPost("/api/MyResultHandler", async (IMediator mediator, MyRequest request, CancellationToken ct) =>
{
return await mediator.Request(request, ct);
});

The only thing that changes in this setup is the http method type, request type, and route. Now, all you have to do is following;

  1. Install Shiny.Mediator.AspNet to your ASP.NET Core project.

  2. On your request handler (void or result based), add [MediatorHttpPost("OperationId", "MyRoute")] or [MediatorHttpPut("OperationId", "MyRoute")] (GET & DELETE attributes also available) attribute to the handler.

    [MediatorScoped] // if you want this registration through source gen (best practice) - you can only used scoped for handlers in ASPNET
    [MediatorHttpGroup("/routes", RequiresAuthorization = true)]
    public class MyHandler : IRequestHandler<MyRequest, MyResult>
    {
    [MediatorHttpPost("MyOperation", "/my")] // creates a route with the operationId of "MyOperation" and a route of "/routes/my"
    public async Task<MyResult> Handle(MyRequest request, IMediatorContext context, CancellationToken ct)
    {
    return new MyResult();
    }
    }
  3. In your host startup, add the following after your build your app. Here is a full-ish sample

    var builder = WebApplication.CreateBuilder(args);
    // Use mediator registry method if using [MediatorScoped] attributes to register your handlers
    builder.Services.AddShinyMediator(x => x.AddMediatorRegistry());
    // OR ADD YOUR HANDLER(S) manually
    services.AddScopeAsImplementedInterfaces<MyHandler>();
    var app = builder.Build();
    // ADD REGISTERED HANDLERS THAT ARE ATTRIBUTED TO THE HTTP ENDPOINTS
    app.MapGeneratedMediatorEndpoints());
    app.Run();

Here is a list of all the properties supported by the Http attributes

public class MediatorHttpAttribute(string operationId, string uriTemplate, HttpMethod httpMethod) : Attribute
{
public string OperationId => operationId;
public string UriTemplate => uriTemplate;
public HttpMethod Method => httpMethod;
public bool RequiresAuthorization { get; set; }
public string[]? AuthorizationPolicies { get; set; }
public string? DisplayName { get; set; }
public string? GroupName { get; set; }
public string[]? Tags { get; set; }
public string? Description { get; set; }
public string? Summary { get; set; }
public bool UseOpenApi { get; set; } = true;
public string? CachePolicy { get; set; }
public string? CorsPolicy { get; set; }
public bool ExcludeFromDescription { get; set; }
public string? RateLimitingPolicy { get; set; }
public bool AllowAnonymous { get; set; }
}

MediatorHttpGet & MediatorHttpDelete parameters can only be set on the route or querystring. All http handlers are automatically generated to map against a scoped mediator handler

Minimal API allows you some fine grained control that attribute registration may restrict as it returns the standard RouteHandleBuilder object that ASP.NET registration returns

var builder = WebApplication.CreateBuilder(args);
// Use mediator registry method if using [MediatorScoped] attributes to register your handlers
builder.Services.AddShinyMediator(x => x.AddMediatorRegistry());
var app = builder.Build();
// fluent registration can be mixed with the attribute registration
app.MapMediatorGet<MappedRequest, string>("/mapped").WithOpenApi();
app.Run();

Server Sent Events (SSE) allow you to stream data from the server to the client over HTTP. Shiny Mediator now supports sending stream requests as SSE endpoints.

This feature comes in two flavours

We take your standard stream request handlers and allow you to send them as SSE endpoints. Here is an example of a stream request to SSE.

app.MapGet(
"/sse",
(
[FromServices] IMediator mediator,
[FromServices] IHttpContextAccessor context, // remember to call services.AddHttpContextAccessor() in your startup
[AsParameters] TickerStreamRequest request // a stream request
) => mediator.RequestServerSentEvents(request, context)
).ExcludeFromDescription();

Maybe you want to listen for a specific event publication through mediator. This easy extension method allows you to do just that.

public class MyEvent : IEvent;
app.MapGet(
"/subscribe",
(
[FromServices] IMediator mediator,
[FromServices] IHttpContextAccessor context // remember to call services.AddHttpContextAccessor() in your startup
) => mediator.EventStreamToServerSentEvents<MyEvent>(context)
).ExcludeFromDescription();