
This article is part of a series called Apizr:
- Apizr – Part 1: A Refit based web api client, but resilient
- Apizr – Part 2: Resilient core features
- Apizr – Part 3: More advanced features
- Apizr – Part 4: Requesting with Mediator pattern (this one)
- Apizr – Part 5: Requesting with Optional pattern
public class MyViewModel { private readonly IApizrManager<IReqResService> _reqResManager; public MyViewModel(IApizrManager<IReqResService> reqResManager) { _reqResManager = reqResManager; } private async Task<List<User>> GetUsersAsync() { try { var userList = await _reqResManager.ExecuteAsync(api => api.GetUsersAsync()); return userList?.Data; } catch (ApizrException<UserList> e) { return e.CachedResult?.Data; } } }
And the same with CRUD apis:
public class MyViewModel { private readonly IApizrManager<ICrudApi<User, int, PagedResult<User>, IDictionary<string, object>>> _userCrudManager; public MyViewModel(IApizrManager<ICrudApi<User, int, PagedResult<User>, IDictionary<string, object>>> userCrudManager) { _userCrudManager = userCrudManager; } private async Task<List<User>> GetUsersAsync() { try { var pagedUsers = await _userCrudManager.ExecuteAsync(api => api.ReadAll()); return pagedUsers?.Data?.ToList(); } catch (ApizrException<PagedResult<User>> e) { return e.CachedResult?.Data?.ToList(); } } }
After MediatR:
Now classic apis with MediatR:
public class MyViewModel { private readonly IMediator _mediator; public MyViewModel(IMediator mediator) { _mediator = mediator; } private async Task<List<User>> GetUsersAsync() { try { var userList = await _mediator.Send(new ExecuteRequest<IReqResService, UserList>(api => api.GetUsersAsync())); return userList?.Data; } catch (ApizrException<UserList> e) { return e.CachedResult?.Data; } } }
And the same with CRUD apis:
public class MyViewModel { private readonly IMediator _mediator; public MyViewModel(IMediator mediator) { _mediator = mediator; } private async Task<List<User>> GetUsersAsync() { try { var pagedUsers = await _mediator.Send(new ReadAllQuery<PagedResult<User>>(), CancellationToken.None); return pagedUsers?.Data?.ToList(); } catch (ApizrException<PagedResult<User>> e) { return e.CachedResult?.Data?.ToList(); } } }
I told you, IMediator could rule them all.
You don’t have to resolve/inject each dedicated api interface anymore.
Just send your request with IMediator and it will be intercepted, handled, and you’ll get your result sent right back to you.
In order to use it, please install its dedicated NuGet package called Apizr.Integrations.MediatR.
Then tell it to Apizr by calling:
builder => builder.WithMediation()
and don’t forget to register MediatR itself as usual:
services.AddMediatR(typeof(Startup));
Everything you need to do is sending your request calling:
var result = await _mediator.Send(YOUR_REQUEST_HERE);
Where YOUR_REQUEST_HERE could be:
Classic apis:
ExecuteRequest<TWebApi>
: execute any method from TWebApiExecuteRequest<TWebApi, TApiResponse>
: execute any method from TWebApi with a TApiResponse resultExecuteRequest<TWebApi, TModelResponse, TApiResponse>
: execute any method from TWebApi with a TApiResponse mapped* to a TModelResponse result
* mapped means data mapped with AutoMapper. Please refer to Part 2 blog post.
witch ends to something like:
var userList = await _mediator.Send(new ExecuteRequest<IReqResService, UserList>(api => api.GetUsersAsync()));
CRUD apis:
ReadQuery<T>
: get the T entity with intReadQuery<T, TKey>
: get the T entity with TKeyReadAllQuery<TReadAllResult>
: get TReadAllResult with IDictionary<string, object> optional query parametersReadAllQuery<TReadAllParams, TReadAllResult>
: get TReadAllResult with TReadAllParams optional query parametersCreateCommand<T>
: create a T entityUpdateCommand<T>
: update the T entity with intUpdateCommand<TKey, T>
: update the T entity with TKeyDeleteCommand<T>
: delete the T entity with intDeleteCommand<T, TKey>
: delete the T entity with TKey
witch ends to something like:
var pagedUsers = await _mediator.Send(new ReadAllQuery<PagedResult<User>>());
There’s also a typed mediator available for each api interface (classic or CRUD), to help you write things shorter.
With classic apis, resolving/injecting IMediator<TWebApi> gives you access to:
SendFor
: send an ExecuteRequest<TWebApi> for youSendFor<TApiResponse>
: send an ExecuteRequest<TWebApi, TApiResponse> for youSendFor<TModelResponse, TApiResponse>
: send an ExecuteRequest<TWebApi, TModelResponse, TApiResponse> for you
witch ends to something as shorter as:
var userList = await _reqResMediator.SendFor(api => api.GetUsersAsync());
With CRUD apis, resolving/injecting ICrudMediator<TApiEntity, TApiEntityKey, TReadAllResult, TReadAllParams> gives you access to:
SendReadQuery(TApiEntityKey key)
: send a ReadQuery<TApiEntity, TApiEntityKey> for youSendReadQuery<TModelEntity>(TApiEntityKey key)
: send a ReadQuery<TModelEntity, TApiEntityKey> for you, with TModelEntity mapped with TApiEntitySendReadAllQuery()
: send a ReadAllQuery<TReadAllResult> for youSendReadAllQuery<TModelEntityReadAllResult>()
: send a ReadAllQuery<TModelEntityReadAllResult> for you, with TModelEntityReadAllResult mapped with TReadAllResultSendCreateCommand(TApiEntity payload)
: send a CreateCommand<TApiEntity> for youSendCreateCommand<TModelEntity>(TModelEntity payload)
: send a CreateCommand<TModelEntity> for you, with TModelEntity mapped* with TApiEntitySendUpdateCommand(TApiEntityKey key, TApiEntity payload)
: send an UpdateCommand<TApiEntityKey, TApiEntity> for youSendUpdateCommand<TModelEntity>(TApiEntityKey key, TModelEntity payload)
: send an UpdateCommand<TApiEntityKey, TModelEntity> for you, with TModelEntity mapped* with TApiEntitySendDeleteCommand(TApiEntityKey key)
: send a DeleteCommand<TApiEntity, TApiEntityKey> for you
* mapped means data mapped with AutoMapper. Please refer to Part 2 blog post.
witch ends to something as shorter as:
var pagedUsers = await _userMediator.SendReadAllQuery();
public class MyViewModel { private readonly IMediator _mediator; private readonly IMediator<IReqResService> _reqResMediator; private readonly ICrudMediator<User, int, PagedResult<User>, IDictionary<string, object>> _userMediator; public MyViewModel(IMediator mediator, IMediator<IReqResService> reqResMediator, ICrudMediator<User, int, PagedResult<User>, IDictionary<string, object>> userMediator) { _mediator = mediator; _reqResMediator = reqResMediator; _userMediator = userMediator; } public ObservableCollection<User>? Users { get; set; } // This is a dummy example presenting all the ways to play with MediatR // You should choose one of it obviously private async Task GetUsersAsync() { IList<User>? users; try { // The classic api interface way var userList = await _mediator.Send(new ExecuteRequest<IReqResService, UserList>(api => api.GetUsersAsync())); users = userList.Data; // The classic api interface way with typed mediator var userList = await _reqResMediator.SendFor(api => api.GetUsersAsync()); users = userList.Data; // The crud api interface way var pagedUsers = await _mediator.Send(new ReadAllQuery<PagedResult<User>>()); users = pagedUsers.Data?.ToList(); // The crud api interface way with typed mediator var pagedUsers = await _userMediator.SendReadAllQuery(); users = pagedUsers.Data?.ToList(); } catch (ApizrException<UserList> e) { return e.CachedResult?.Data; } catch (ApizrException<PagedResult<User>> e) { users = e.CachedResult?.Data; } if(users != null) Users = new ObservableCollection<User>(users); } }