MitMediator.AutoApi.HttpMediator
9.0.0-alfa-4
dotnet add package MitMediator.AutoApi.HttpMediator --version 9.0.0-alfa-4
NuGet\Install-Package MitMediator.AutoApi.HttpMediator -Version 9.0.0-alfa-4
<PackageReference Include="MitMediator.AutoApi.HttpMediator" Version="9.0.0-alfa-4" />
<PackageVersion Include="MitMediator.AutoApi.HttpMediator" Version="9.0.0-alfa-4" />
<PackageReference Include="MitMediator.AutoApi.HttpMediator" />
paket add MitMediator.AutoApi.HttpMediator --version 9.0.0-alfa-4
#r "nuget: MitMediator.AutoApi.HttpMediator, 9.0.0-alfa-4"
#:package MitMediator.AutoApi.HttpMediator@9.0.0-alfa-4
#addin nuget:?package=MitMediator.AutoApi.HttpMediator&version=9.0.0-alfa-4&prerelease
#tool nuget:?package=MitMediator.AutoApi.HttpMediator&version=9.0.0-alfa-4&prerelease
MitMediator.AutoApi
Minimal API registration and http client for MitMediator
π Extension for MitMediator
π Installation
1. Add package
# for ASP.NET API projects
dotnet add package MitMediator.AutoApi -v 9.0.0-alfa-4
# for application layer
dotnet add package MitMediator.AutoApi.Abstractions -v 9.0.0-alfa-4
# for client application (MAUI, Blazor, UWP, etc.)
dotnet add package MitMediator.AutoApi.HttpMediator -v 9.0.0-alfa-4
2. Use extension for IEndpointRouteBuilder
var builder = WebApplication.CreateBuilder(args);
// Register handlers and IMediator.
builder.Services.AddMitMediator();
var app = builder.Build();
// Automatically maps endpoints based on IRequest
app.UseAutoApi();
app.Run();
To use base path "api", select assemblies to scan and disable antiforgery validation:
app.UseAutoApi("api", new []{typeof(GetQuery).Assembly}, disableAntiforgery: true);
3. Done! All public requests have endpoints
π§ͺ Examples
GET
endpoint
// Get - http method
// Books - main tag
// Api URL: GET /books?limit=1&offset=1&freeText=clara
public struct GetBooksQuery : IRequest<Book[]>
{
public int? Limit { get; init; }
public int? Offset { get; init; }
public string? FreeText { get; init; }
}
GET
endpoint with key in url
// Use IKeyRequest<> to set and get key from ur.
// Get - http method
// Book - main tag (books in url)
// Api URL: GET /books/123
public struct GetBookQuery : IRequest<Book>, IKeyRequest<int>
{
internal int BookId { get; private set; }
public void SetKey(int key)
{
BookId = key;
}
public int GetKey() => BookId;
}
GET
endpoint with suffix
// Get - http method
// Books - main tag
// Count - action suffix
// Api URL: GET /books/count?freeText=clara
public struct GetBooksCountQuery : IRequest<int>
{
public string? FreeText { get; init; }
}
POST
endpoint with 201 response
// Create - POST http method, return 201
// Book - main tag (books in url)
// Api URL: POST /books
public class CreateBookCommand : IRequest<Book>
{
public string Title { get; init; }
public int AuthorId { get; init; }
public string GenreName { get; init; }
}
PUT
endpoint with key in url
// Update - PUT http method
// Book - main tag (books in url)
// Api URL: PUT /books/123
public class UpdateBookCommand : IRequest<Book>, IKeyRequest<int>
{
internal int BookId { get; private set; }
public string Title { get; init; }
public int AuthorId { get; init; }
public string GenreName { get; init; }
public void SetKey(int key)
{
BookId = key;
}
public int GetKey() => BookId;
}
DELETE
endpoint with a key in url
// Delete - DELETE http method
// Book - main tag (books in url)
// Api URL: DELETE /books/123
public struct DeleteBookCommand : IRequest, IKeyRequest<int>
{
internal int BookId { get; private set; }
public void SetKey(int key)
{
BookId = key;
}
public int GetKey() => BookId;
}
GET
endpoint text file ("application/octet-stream")
// Get - GET http method
// Book - main tag (books in url)
// Text - action suffix
// Api URL: GET /books/text/123
public class GetBookTextQuery: IRequest<byte[]>, IKeyRequest<int>
{
internal int BookId { get; private set; }
public void SetKey(int key)
{
BookId = key;
}
public int GetKey() => BookId;
}
GET
endpoint png file ("image/png")
// Get - GET http method
// Book - main tag (books in url)
// Cover - action suffix
// Api URL: GET /books/Ρover/123
[AutoApi(customResponseContentType:"image/png")]
public class GetBookCoverQuery: IRequest<byte[]>, IKeyRequest<int>
{
internal int BookId { get; private set; }
public void SetKey(int key)
{
BookId = key;
}
public int GetKey() => BookId;
}
POST
upload and download file
// Import - POST http method
// Document - main tag (documents in url)
// Word - action suffix
// Api URL: POST /documents/words
public class ImportDocumentWordCommand : FileRequest, IRequest<FileResponse>
{
}
Change default mapping
Use the [AutoApi]
attribute for the request type to change default mapping
GET
endpoint with a version, custom tag and custom suffix
// Get - http method
// Books - main tag (books in url)
// API version: "v2"
// Api URL: GET v2/my-books/favorite?limit=1&offset=1&freeText=clara
[AutoApi("my-books", "v2", PatternSuffix = "favorite")]
public struct GetBooksQuery : IRequest<Book[]>
{
public int? Limit { get; init; }
public int? Offset { get; init; }
public string? FreeText { get; init; }
}
GET
endpoint with version, custom tag, URL pattern and specified HTTP method
// Auto-generated DELETE endpoint.
// Base tag: "books"
// API version: "v3"
// Custom URL pattern overrides base route: DELETE with-keys/{key1}/field/{key2}
[AutoApi("books", customPattern: "with-keys/{key1}/field/{key2}", version: "v3", httpMethodType:HttpMethodType.Delete)]
public class DoSomeWithBookAndDeleteCommand : IRequest<Book[]>, IKeyRequest<int, Guid>
{
internal int BookId { get; private set; }
internal Guid GuidId { get; private set; }
public void SetKey1(int key)
{
BookId = key;
}
public int GetKey1() => BookId;
public void SetKey2(Guid key)
{
GuidId = key;
}
public Guid GetKey2() => GuidId;
}
Default version is
v1
π« Ignore Request
You can disable automatic endpoint generation for a request if you prefer to implement the endpoint manually or exclude
it from the API surface.
To do so, apply the [AutoApiIgnore]
attribute to the request type:
[AutoApiIgnore]
public class MyCustomRequest : IRequest<MyResponse>
{
// This request will not be exposed via AutoAPI
}
π Upload and download files
For requests implementing IRequest<byte[]>
/IRequest<Stream>
, or IRequest<FileResponse>
/
IRequest<FileStreamResponse>
, the response will use "application/octet-stream"
by default. To specify a download
file name, use the FileResponse
or FileStreamResponse
response.
Use [AutoApi(customResponseContentType:"image/png")]
attribute for custom content type
When requests implementing IFileRequest
or inheriting from FileRequest
, the request will be bound using
[FromForm]
, and file parameters will be inferred via IFromFile
by default
π’ X-Total-Count
Header
To include the X-Total-Count
header in the HTTP response, implement the ITotalCount
interface in your response type.
This is useful for paginated endpoints or any scenario where the client needs to know the total number of items
available.
public class GetBooksResponse : ITotalCount
{
public Book[] Items { get; init; }
private int _totalCount;
public int GetTotalCount() => _totalCount;
public void SetTotalCount(int totalCount)
{
_totalCount = totalCount;
}
}
When this interface is implemented, MitMediator.AutoApi will automatically include the X-Total-Count
header in the
response, reflecting the value returned by GetTotalCount()
π Resource ID in Location
header for 201 Created
responses
To insert the correct ID into the Location header of a 201 Created response, implement the IResourceKey
interface in
your response type:
// Api URL: POST /books
public class CreateBookCommand : IRequest<CreatedBookResponse>
{
public string Title { get; init; }
}
// Location Header: /books/{BookId}
public class CreatedBookResponse : IResourceKey
{
public int BookId { get; private set; }
public string Title { get; private set; }
public string GetResourceKey() => BookId.ToString();
}
If you do not implement the IResourceKey
interface, the Location header will default to the format /books/{key}
,
where {key}
is a placeholder string
π― Use auto client: HttpMediator
You can reuse your IRequest
types to seamlessly send HTTP requests to a server-side API using HttpMediator
HttpMediator
supports IClientPipelineBehavior<TRequest, TResponse>
for middleware-like extensibility, and
IHttpHeaderInjector<TRequest, TResponse>
for injecting custom headers per request
π§ Sample usage:
var mediator = new HttpMediator(serviceProvider, baseUrl: "https://api.example.com");
var response = await mediator.SendAsync<MyRequest, MyResponse>(new MyRequest(), cancellationToken);
π§ More
var baseApiUrl = "api";
var httpClientName = "baseHttpClient";
var serviceCollection = new ServiceCollection();
serviceCollection.AddHttpClient(httpClientName, client => { client.BaseAddress = new Uri("https://localhost:7127/"); });
serviceCollection.AddScoped(typeof(IHttpHeaderInjector<,>), typeof(AuthorizationHeaderInjection<,>));
serviceCollection.AddScoped<IClientMediator, HttpMediator>(c => new HttpMediator(c, baseApiUrl, httpClientName));
var provider = serviceCollection.BuildServiceProvider();
var httpMediator = provider.GetRequiredService<IClientMediator>();
var query = new GetBookQuery();
query.SetKey(12);
var data = await httpMediator.SendAsync<GetBookQuery, Book>(query, CancellationToken.None);
public class AuthorizationHeaderInjection<TRequest, TResponse> : IHttpHeaderInjector<TRequest, TResponse> where TRequest : IRequest<TResponse>
{
public ValueTask<(string, string)?> GetHeadersAsync(CancellationToken cancellationToken)
{
var result = ("Authorization", "Bearer token");
return ValueTask.FromResult<(string, string)?>(result);
}
}
π See samples
βοΈ How It Works
- Scans all loaded assemblies for
IRequest
types - Dynamically generates and registers endpoints for each match
- Maps routes using
MapPost
,MapGet
,MapPut
, andMapDelete
, internally callingIMediator.SendAsync()
If you need to change the generated method, use the [AutoApi]
attribute for the request type
The HTTP method type is determined automatically according to the request name:
Request name start with | HTTP Method |
---|---|
get |
GET |
load |
GET |
download |
GET |
fetch |
GET |
update |
PUT |
change |
PUT |
edit |
PUT |
modify |
PUT |
put |
PUT |
post |
POST |
import |
POST |
upload |
POST |
add |
POST (201 response) |
create |
POST (201 response) |
delete |
DELETE |
remove |
DELETE |
drop |
DELETE |
The first word after the method will be the main tag. Second and other - suffix. For example:
GetBookCountQuery
- Get - http method GET, Book - main tag (books in url), Count - suffix (/count in url)
RemoveBookWithAuthorCommand
- Remove - http method DELETE, Book - main tag (books in url), WithAuthor - suffix (
/with-author in url)
Words command
, query
, and request
in the end of request type name will be deleted from url
π‘ Features
- Declarative routing via request class name or attributes
- Automatic tag and version grouping
- Built-in handling of
Unit
results (no payload responses) - Custom route patterns with up to 7 composite keys
- Key binding via IKeyRequest<TKey1, TKey2, ...> (pattern
{key1}/{key2}/.../{key7}
) - Supports custom patterns (
custom-route/my-route
,with-keys/{key1}/{key2}/field/{key3}
) - Auto client
HttpMediator
for clients applications - File response (
IRequest<byte[]>
orIRequest<FileResponse>
) - Upload file stream:
public class UploadCoverCommand: FileRequest {}
X-Total-Count
header (implementITotalCount
in response type)
π License
MIT
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net9.0
- Microsoft.Extensions.Http (>= 9.0.8)
- MitMediator.AutoApi.Abstractions (>= 9.0.0-alfa-4)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
Version | Downloads | Last Updated |
---|---|---|
9.0.0-alfa-4 | 138 | 8/29/2025 |
7.0.0-alfa-8 | 209 | 8/6/2025 |
9.0.0-alfa-4
Implemented streaming file upload and download support