This project is a work in progress. And will likely recieve many API changes before v1.0.0
please keep this in mind when using, there will be breaking changes often.
This library is targeted at Blazor WebAssembly and will allow you to send Mediatr requests over http without needing to add any extra boilerplate/controllers. Requests from your frontend are sent to an endpoint on your server which handles all of the Mediatr logic without any controllers.
In the default blazor wasm hosted template, there is a weather forecast controller that has a Get
endpoint that looks like this:
[HttpGet]
public IEnumerable<WeatherForecast> Get()
{
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = DateTime.Now.AddDays(index),
TemperatureC = Random.Shared.Next(-20, 55),
Summary = Summaries[Random.Shared.Next(Summaries.Length)]
})
.ToArray();
}
Then in FetchData.razor
page we are sending an http request to get our data:
forecasts = await Http.GetFromJsonAsync<WeatherForecast[]>("WeatherForecast");
First we define our request:
public record WeatherForecastQuery() : IClientRequest<IEnumerable<WeatherForecast>>;
- Here we use
IClientRequest
instead ofIRequest
this is to help distinguish which requests can be called from the client.
Then we setup a handler for this request:
public class WeatherForecastQueryHandler : IRequestHandler<WeatherForecastQuery, IEnumerable<WeatherForecast>>
{
private static readonly string[] Summaries = new[]
{
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};
public Task<IEnumerable<WeatherForecast>> Handle(WeatherForecastQuery request, CancellationToken cancellationToken)
{
return Task.FromResult(
Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = DateTime.Now.AddDays(index),
TemperatureC = Random.Shared.Next(-20, 55),
Summary = Summaries[Random.Shared.Next(Summaries.Length)]
})
);
}
}
Lastly we just need to swap out our call in FetchData.razor
with a call to the Mediator:
forecasts = await Mediator.Send(new WeatherForecastQuery());
This allows us to skip the controller all together.
There is a custom exception type ClientRequestException
that you can throw from your handler that will be rethrown on the client, you can use this for returning any sorts of errors.
Any other exceptions will return a 500 error and will be rethrown on the client as an ApplicationException
.
Authorization works the exact same way as it does with controllers & actions.
You can apply the Authorize
attribute to the request definition (IClientRequest
) and it will work the same as it does for controllers/actions.
You can also set PerformAuthorizationByDefault
to true
and this will perform auth on all requests that do not have AllowAnonymous
attribute.
- Add library references
- In your client/frontend project add a nuget reference to
RemoteMediatr.Client
- In your server/backend project add a nuget reference to
RemoteMediatr.Server
- In your client/frontend project add a nuget reference to
- Add
builder.Services.AddRemoteMediatr(opt => { opt.BaseAddress = new Uri(builder.HostEnvironment.BaseAddress); });
to your client startup - Add
app.MapRemoteMediatrListener(typeof(DemoApp.Shared.Requests).Assembly);
to your server startupservices.AddMediatR
should be called before this