Created
May 8, 2023 05:42
-
-
Save PureKrome/93ec506c7006a570025cd664e1bd38d9 to your computer and use it in GitHub Desktop.
MediatR behavior not working
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Needs these package in the csproj | |
<ItemGroup> | |
<PackageReference Include="CSharpFunctionalExtensions" Version="2.38.1" /> | |
<PackageReference Include="FluentValidation.DependencyInjectionExtensions" Version="11.5.2" /> | |
<PackageReference Include="MediatR" Version="12.0.1" /> | |
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="7.0.5" /> | |
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" /> | |
</ItemGroup> | |
*/ | |
using CSharpFunctionalExtensions; | |
using FluentValidation; | |
using FluentValidation.Results; | |
using MediatR; | |
var builder = WebApplication.CreateBuilder(args); | |
// Add services to the container. | |
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle | |
builder.Services.AddEndpointsApiExplorer(); | |
builder.Services.AddSwaggerGen(); | |
// Register our validators. | |
builder.Services.AddValidatorsFromAssemblyContaining<GetWeatherQuery.Validator>(); | |
// Register our Mediator Handlers and behaviors. | |
builder.Services.AddMediatR(configuration => | |
configuration | |
.RegisterServicesFromAssemblyContaining(typeof(Program)) | |
//.AddOpenBehavior(typeof(ValidationBehavior <,>)) | |
.AddBehavior< | |
IPipelineBehavior<GetWeatherQuery.Query, Result<GetWeatherQuery.Response, ValidationFailed>>, | |
ValidationBehavior<GetWeatherQuery.Query, GetWeatherQuery.Response>>() | |
); | |
var app = builder.Build(); | |
// Configure the HTTP request pipeline. | |
if (app.Environment.IsDevelopment()) | |
{ | |
app.UseSwagger(); | |
app.UseSwaggerUI(); | |
} | |
app.UseHttpsRedirection(); | |
var summaries = new[] | |
{ | |
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" | |
}; | |
app.MapGet("/weatherforecast", () => | |
{ | |
var forecast = Enumerable.Range(1, 5).Select(index => | |
new WeatherForecast | |
( | |
DateOnly.FromDateTime(DateTime.Now.AddDays(index)), | |
Random.Shared.Next(-20, 55), | |
summaries[Random.Shared.Next(summaries.Length)] | |
)) | |
.ToArray(); | |
return forecast; | |
}) | |
.WithName("GetWeatherForecast") | |
.WithOpenApi(); | |
app.MapGet("/weatherforecast/{city:required}", async ( | |
string city, | |
IMediator mediator, | |
CancellationToken cancellationToken) => | |
{ | |
var query = new GetWeatherQuery.Query(city); | |
var result = await mediator.Send(query, cancellationToken); | |
return TypedResults.Ok(result); | |
}) | |
.WithOpenApi(); | |
app.Run(); | |
internal record WeatherForecast(DateOnly Date, int TemperatureC, string? Summary) | |
{ | |
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); | |
} | |
public class GetWeatherQuery | |
{ | |
public record Query(string City) : IRequest<Response>; | |
public record Response(string City, int Temp, DateTime SomeDate); | |
public class Handler : IRequestHandler<Query, Response> | |
{ | |
public Task<Response> Handle(Query request, CancellationToken cancellationToken) | |
{ | |
var response = new Response("New York", 20, DateTime.Now); | |
return Task.FromResult(response); | |
} | |
} | |
public class Validator : AbstractValidator<Query> | |
{ | |
public Validator() | |
{ | |
RuleFor(x => x.City) | |
.NotEmpty() | |
.MinimumLength(5) | |
.WithMessage("City must be more than 5 characters."); | |
} | |
} | |
} | |
public record ValidationFailed | |
{ | |
public IDictionary<string, string[]> Errors { get; } | |
public ValidationFailed(ValidationResult validationResult) | |
{ | |
Errors = validationResult.ToDictionary(); | |
} | |
} | |
public class ValidationBehavior<TRequest, TResult> : | |
IPipelineBehavior<TRequest, Result<TResult, ValidationFailed>> where TRequest : notnull | |
{ | |
private readonly IValidator<TRequest> _validator; | |
public ValidationBehavior(IValidator<TRequest> validator) | |
{ | |
_validator = validator; | |
} | |
public async Task<Result<TResult, ValidationFailed>> Handle( | |
TRequest request, | |
RequestHandlerDelegate<Result<TResult, ValidationFailed>> next, | |
CancellationToken cancellationToken) | |
{ | |
var validationResult = await _validator.ValidateAsync(request, cancellationToken); | |
if (!validationResult.IsValid) | |
{ | |
return new ValidationFailed(validationResult); | |
} | |
return await next(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment