-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathUseMiddlewareDemo.cs
More file actions
103 lines (90 loc) · 3.14 KB
/
UseMiddlewareDemo.cs
File metadata and controls
103 lines (90 loc) · 3.14 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using NSubstitute;
using System.Reflection;
using Xunit.Abstractions;
namespace MediatR.MiddlewareDemo;
public record BaseResponse
{
public string? ErrorMessage { get; init; }
}
public class BusinessException : Exception
{
public BusinessException(string? message) : base(message)
{
}
}
public class LogTryCatchMiddleware<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse>
where TRequest : IRequest<TResponse>
where TResponse : BaseResponse, new()
{
private readonly ILogger<TRequest> _logger;
public LogTryCatchMiddleware(ILogger<TRequest> logger)
{
_logger = logger;
}
public async Task<TResponse> Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate<TResponse> next)
{
var conversationId = Guid.NewGuid();
_logger.LogInformation("REQUEST {Request} {ConversationId}", request, conversationId);
try
{
TResponse response = await next();
_logger.LogInformation("RESPONSE {Response} {ConversationId}", response, conversationId);
return response;
}
catch (BusinessException businessEx)
{
var response = new TResponse()
{
ErrorMessage = businessEx.Message
};
_logger.LogWarning(businessEx, "RESPONSE Business Error {ConversationId}", conversationId);
return response;
}
catch (Exception ex)
{
_logger.LogError(ex, "CRASHED while consuming {Request} {ConversationId}", request, conversationId);
throw;
}
}
}
public record MyRequest : IRequest<MyResponse> { }
public record MyResponse : BaseResponse { }
public interface ISomeDependentService { }
public class MyConsumer : IRequestHandler<MyRequest, MyResponse>
{
public MyConsumer(ISomeDependentService someDependentService)
{
}
public Task<MyResponse> Handle(MyRequest request, CancellationToken cancellationToken)
{
throw new BusinessException("Business error");
return Task.FromResult(new MyResponse());
}
}
public class UseMiddlewareDemo
{
private readonly IServiceProvider _provider;
private readonly ITestOutputHelper _testOutput;
public UseMiddlewareDemo(ITestOutputHelper testOutput)
{
_testOutput = testOutput;
_provider = new ServiceCollection()
.AddMediatR(Assembly.GetExecutingAssembly())
.AddTransient(typeof(IPipelineBehavior<,>), typeof(LogTryCatchMiddleware<,>))
.AddLogging(cfg =>
{
cfg.AddXUnit(testOutput);
})
.AddSingleton(Substitute.For<ISomeDependentService>())
.BuildServiceProvider(new ServiceProviderOptions { ValidateOnBuild = true, ValidateScopes = true });
}
[Fact]
public async Task MyConsumerTestAsync()
{
var mediator = _provider.GetRequiredService<IMediator>();
var response = await mediator.Send(new MyRequest());
_testOutput.WriteLine($"Sender side successfully got a response: {response}");
}
}