From b49729e8e0aa0373c5b7a9620b3d0846684cc9b1 Mon Sep 17 00:00:00 2001 From: ZhengJie Date: Sat, 19 Oct 2024 17:28:58 +0800 Subject: [PATCH 1/4] =?UTF-8?q?Adjust=20KnownExceptionValidationBehavior?= =?UTF-8?q?=20=E4=BD=BF=E7=94=A8=20ValidateAsync=20=E4=BB=A5=E6=94=AF?= =?UTF-8?q?=E6=8C=81=E5=BC=82=E6=AD=A5=E9=AA=8C=E8=AF=81=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Validation/KnownExceptionValidationBehavior.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/AspNetCore/Validation/KnownExceptionValidationBehavior.cs b/src/AspNetCore/Validation/KnownExceptionValidationBehavior.cs index 2a4aed6..98cffc5 100644 --- a/src/AspNetCore/Validation/KnownExceptionValidationBehavior.cs +++ b/src/AspNetCore/Validation/KnownExceptionValidationBehavior.cs @@ -19,8 +19,9 @@ public async Task Handle(TRequest request, RequestHandlerDelegate(request); - var errorsDictionary = _validators - .Select(x => x.Validate(context)) + var errorsDictionary = (await Task.WhenAll( + _validators.Select(x => x.ValidateAsync(context, cancellationToken))) + ) .SelectMany(x => x.Errors) .Where(x => x != null).ToList(); if (errorsDictionary.Any()) @@ -28,7 +29,7 @@ public async Task Handle(TRequest request, RequestHandlerDelegate new { errorCode = p.ErrorCode, errorMessage = p.ErrorMessage, propertyName = p.PropertyName } - ).ToArray()); + ).ToArray()); } return await next(); From 66bd6e926ee377528fd4e506a1c17d20db42d8ca Mon Sep 17 00:00:00 2001 From: ZhengJie Date: Mon, 28 Oct 2024 19:56:21 +0800 Subject: [PATCH 2/4] =?UTF-8?q?=E6=B7=BB=E5=8A=A0CreateOrderRequest?= =?UTF-8?q?=E6=9B=BF=E6=8D=A2CreateOrderCommand=E4=BD=9C=E4=B8=BA=E8=AF=B7?= =?UTF-8?q?=E6=B1=82=E5=8F=82=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/NetCorePal.Web.UnitTests/ProgramTests.cs | 7 ++++--- test/NetCorePal.Web/Controllers/OrderController.cs | 11 ++++++----- .../Controllers/Request/CreateOrderRequest.cs | 4 ++++ 3 files changed, 14 insertions(+), 8 deletions(-) create mode 100644 test/NetCorePal.Web/Controllers/Request/CreateOrderRequest.cs diff --git a/test/NetCorePal.Web.UnitTests/ProgramTests.cs b/test/NetCorePal.Web.UnitTests/ProgramTests.cs index 73d5cca..ee08d42 100644 --- a/test/NetCorePal.Web.UnitTests/ProgramTests.cs +++ b/test/NetCorePal.Web.UnitTests/ProgramTests.cs @@ -12,6 +12,7 @@ using NetCorePal.SkyApm.Diagnostics; using NetCorePal.Web.Application.IntegrationEventHandlers; using NetCorePal.Web.Application.Queries; +using NetCorePal.Web.Controllers.Request; namespace NetCorePal.Web.UnitTests { @@ -122,7 +123,7 @@ public async Task ServiceUnknownExceptionTest() public async Task PostTest() { var client = factory.CreateClient(); - var response = await client.PostAsJsonAsync("/api/order", new CreateOrderCommand("na", 55, 14), JsonOption); + var response = await client.PostAsJsonAsync("/api/order", new CreateOrderRequest("na", 55, 14), JsonOption); Assert.True(response.IsSuccessStatusCode); var data = await response.Content.ReadFromJsonAsync(JsonOption); Assert.NotNull(data); @@ -145,7 +146,7 @@ public async Task PostTest() public async Task SetPaidTest() { var client = factory.CreateClient(); - var response = await client.PostAsJsonAsync("/api/order", new CreateOrderCommand("na", 55, 14), JsonOption); + var response = await client.PostAsJsonAsync("/api/order", new CreateOrderRequest("na", 55, 14), JsonOption); Assert.True(response.IsSuccessStatusCode); var data = await response.Content.ReadFromJsonAsync(JsonOption); Assert.NotNull(data); @@ -181,7 +182,7 @@ public async Task SetPaidTest() public async Task SetOrderItemNameTest() { var client = factory.CreateClient(); - var response = await client.PostAsJsonAsync("/api/order", new CreateOrderCommand("na", 55, 14), JsonOption); + var response = await client.PostAsJsonAsync("/api/order", new CreateOrderRequest("na", 55, 14), JsonOption); Assert.True(response.IsSuccessStatusCode); var data = await response.Content.ReadFromJsonAsync(JsonOption); Assert.NotNull(data); diff --git a/test/NetCorePal.Web/Controllers/OrderController.cs b/test/NetCorePal.Web/Controllers/OrderController.cs index e23b483..10e6eb7 100644 --- a/test/NetCorePal.Web/Controllers/OrderController.cs +++ b/test/NetCorePal.Web/Controllers/OrderController.cs @@ -8,6 +8,7 @@ using NetCorePal.Web.Application.IntegrationEventHandlers; using NetCorePal.Web.Application.Queries; using NetCorePal.Web.Application.Sagas; +using NetCorePal.Web.Controllers.Request; using SkyApm.Tracing; namespace NetCorePal.Web.Controllers @@ -40,12 +41,12 @@ public IActionResult Get() /// /// /// - /// + /// /// [HttpPost] - public async Task Post([FromBody] CreateOrderCommand command) + public async Task Post([FromBody] CreateOrderRequest request) { - var id = await mediator.Send(command, HttpContext.RequestAborted); + var id = await mediator.Send(new CreateOrderCommand(request.Name, request.Price, request.Count), HttpContext.RequestAborted); return id; } @@ -75,7 +76,7 @@ public async Task SetPaid(OrderId id) await mediator.Send(new OrderPaidCommand(id), HttpContext.RequestAborted); return true.AsResponseData(); } - + /// /// /// @@ -84,7 +85,7 @@ public async Task SetPaid(OrderId id) /// [HttpPost] [Route("/setorderItemName")] - public async Task SetOrderItemName([FromQuery]long id, [FromQuery]string name) + public async Task SetOrderItemName([FromQuery] long id, [FromQuery] string name) { await mediator.Send(new SetOrderItemNameCommand(new OrderId(id), name), HttpContext.RequestAborted); return true.AsResponseData(); diff --git a/test/NetCorePal.Web/Controllers/Request/CreateOrderRequest.cs b/test/NetCorePal.Web/Controllers/Request/CreateOrderRequest.cs new file mode 100644 index 0000000..91fa7b2 --- /dev/null +++ b/test/NetCorePal.Web/Controllers/Request/CreateOrderRequest.cs @@ -0,0 +1,4 @@ +namespace NetCorePal.Web.Controllers.Request +{ + public record CreateOrderRequest(string Name, int Price, int Count); +} From 01f5a426cc031ef2510b54cc1a20bcb6451f7e49 Mon Sep 17 00:00:00 2001 From: ZhengJie Date: Mon, 28 Oct 2024 20:43:13 +0800 Subject: [PATCH 3/4] =?UTF-8?q?test:=E5=90=91=E4=B8=AD=E4=BB=8B=E8=80=85?= =?UTF-8?q?=E7=AE=A1=E9=81=93=E4=B8=AD=E6=B7=BB=E5=8A=A0=E9=AA=8C=E8=AF=81?= =?UTF-8?q?=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../HostedServices/CreateOrderCommandBackgroundService.cs | 2 +- test/NetCorePal.Web/Program.cs | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/test/NetCorePal.Web/HostedServices/CreateOrderCommandBackgroundService.cs b/test/NetCorePal.Web/HostedServices/CreateOrderCommandBackgroundService.cs index eba6775..1203e7c 100644 --- a/test/NetCorePal.Web/HostedServices/CreateOrderCommandBackgroundService.cs +++ b/test/NetCorePal.Web/HostedServices/CreateOrderCommandBackgroundService.cs @@ -27,7 +27,7 @@ protected override async Task ExecuteAsync(CancellationToken stoppingToken) { await using (handler) { - var command = new CreateOrderCommand("abc", 10, 20); + var command = new CreateOrderCommand("abc", 20, 20); await mediator.Send(command, stoppingToken); await Task.Delay(100, stoppingToken); } diff --git a/test/NetCorePal.Web/Program.cs b/test/NetCorePal.Web/Program.cs index 62f4ccf..39164e6 100644 --- a/test/NetCorePal.Web/Program.cs +++ b/test/NetCorePal.Web/Program.cs @@ -139,7 +139,8 @@ builder.Services.AddContext().AddEnvContext().AddCapContextProcessor(); builder.Services.AddMediatR(cfg => - cfg.RegisterServicesFromAssemblies(Assembly.GetExecutingAssembly()).AddUnitOfWorkBehaviors()); + cfg.RegisterServicesFromAssemblies(Assembly.GetExecutingAssembly()).AddUnitOfWorkBehaviors() + .AddKnownExceptionValidationBehavior()); builder.Services.AddRepositories(typeof(ApplicationDbContext).Assembly); builder.Services.AddDbContext(options => { From e842b626ed98ef8e777c12f56054f6250b97b238 Mon Sep 17 00:00:00 2001 From: ZhengJie Date: Mon, 28 Oct 2024 20:44:52 +0800 Subject: [PATCH 4/4] =?UTF-8?q?test:=20=E6=B7=BB=E5=8A=A0=E6=B5=8B?= =?UTF-8?q?=E8=AF=95=EF=BC=8C=E5=9C=A8CreateOrderCommandValidator=E4=B8=AD?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E4=B8=80=E4=B8=AA=E5=BC=82=E6=AD=A5=E7=9A=84?= =?UTF-8?q?case=EF=BC=8C=E4=BB=A5=E7=A1=AE=E5=AE=9A=E9=AA=8C=E8=AF=81?= =?UTF-8?q?=E5=99=A8=E4=B8=8E=E5=BC=82=E5=B8=B8=E5=A4=84=E7=90=86=E5=99=A8?= =?UTF-8?q?=E5=B7=A5=E4=BD=9C=E7=AC=A6=E5=90=88=E9=A2=84=E6=9C=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/NetCorePal.Web.UnitTests/ProgramTests.cs | 19 +++++++++++++++++++ .../Commands/CreateOrderCommandValidator.cs | 4 ++++ 2 files changed, 23 insertions(+) diff --git a/test/NetCorePal.Web.UnitTests/ProgramTests.cs b/test/NetCorePal.Web.UnitTests/ProgramTests.cs index ee08d42..af39342 100644 --- a/test/NetCorePal.Web.UnitTests/ProgramTests.cs +++ b/test/NetCorePal.Web.UnitTests/ProgramTests.cs @@ -217,5 +217,24 @@ public async Task Int64StronglyTypedId_FromRoute_Should_Work_Test() Assert.True(data.Success); Assert.Equal(id, data.Data.Id); } + + [Fact] + public async Task CreateOrderValidator_Should_ValidateWithAsync_WhenPosting() + { + var client = factory.CreateClient(); + var response = await client.PostAsJsonAsync("/api/order", new CreateOrderRequest("na", 55, 14), JsonOption); + Assert.True(response.IsSuccessStatusCode); + var data = await response.Content.ReadFromJsonAsync(JsonOption); + Assert.NotNull(data); + + + response = await client.PostAsJsonAsync("/api/order", new CreateOrderRequest("na", 55, -1), JsonOption); + Assert.True(response.IsSuccessStatusCode); + var errData = await response.Content.ReadFromJsonAsync(); + Assert.NotNull(errData); + Assert.Contains("Count", errData.Message); + Assert.Equal(400, errData.Code); + Assert.False(errData.Success); + } } } \ No newline at end of file diff --git a/test/NetCorePal.Web/Application/Commands/CreateOrderCommandValidator.cs b/test/NetCorePal.Web/Application/Commands/CreateOrderCommandValidator.cs index a676038..828c970 100644 --- a/test/NetCorePal.Web/Application/Commands/CreateOrderCommandValidator.cs +++ b/test/NetCorePal.Web/Application/Commands/CreateOrderCommandValidator.cs @@ -14,6 +14,10 @@ public CreateOrderCommandValidator() { RuleFor(x => x.Name).NotEmpty().MaximumLength(10); RuleFor(x => x.Price).InclusiveBetween(18, 60); + RuleFor(x => x.Count).MustAsync(async (c, ct) => { + await Task.CompletedTask; + return c > 0; + } ); } } }