-
Notifications
You must be signed in to change notification settings - Fork 2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feature/build error type response #12
Changes from all commits
78e668e
25155ad
4d842ef
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
using FluentValidation; | ||
using Microsoft.AspNetCore.Mvc; | ||
using System.Linq; | ||
|
||
namespace JSM.FluentValidation.AspNet.AsyncFilter | ||
{ | ||
/// <summary> | ||
/// Extension to override error code with prefix and type. | ||
/// </summary> | ||
public static class RuleTypeBuilderExtensions | ||
{ | ||
/// <summary> | ||
/// Overrides the error code associated with this rule with prefix and type | ||
/// </summary> | ||
/// <typeparam name="T"></typeparam> | ||
/// <typeparam name="TProperty"></typeparam> | ||
/// <param name="rule">The current rule</param> | ||
/// <param name="type">The type used to override error code</param> | ||
/// <returns></returns> | ||
public static IRuleBuilderOptions<T, TProperty> WithRuleType<T, TProperty>(this IRuleBuilderOptions<T, TProperty> rule, string type) | ||
{ | ||
string propertyName = ""; | ||
|
||
var options = rule.Configure(x => propertyName = x.GetDisplayName(null)); | ||
|
||
if (!string.IsNullOrEmpty(propertyName)) | ||
options.WithName(propertyName); | ||
|
||
options.WithErrorCode($"{RuleTypeConst.Prefix}.{type}"); | ||
|
||
return options; | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
namespace JSM.FluentValidation.AspNet.AsyncFilter | ||
{ | ||
/// <summary> | ||
/// Const used do configure method WithRuleType. | ||
/// </summary> | ||
public static class RuleTypeConst | ||
{ | ||
/// <summary> | ||
/// Prefix used to override property name. | ||
/// </summary> | ||
public const string Prefix = "_RuleType"; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. question: maybe I'm missing something here, but is this prefix really required? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @luizhlelis this prefix is important to set correctly type in response. |
||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
using FluentAssertions; | ||
using JSM.FluentValidation.AspNet.AsyncFilter.Tests.Support; | ||
using JSM.FluentValidation.AspNet.AsyncFilter.Tests.Support.Models; | ||
using JSM.FluentValidation.AspNet.AsyncFilter.Tests.Support.Startups; | ||
using Microsoft.AspNetCore.Mvc; | ||
using System.Collections.Generic; | ||
using System.Net.Http; | ||
using System.Net.Http.Json; | ||
using System.Threading.Tasks; | ||
using Xunit; | ||
|
||
namespace JSM.FluentValidation.AspNet.AsyncFilter.Tests | ||
{ | ||
public class ModelValidationAsyncActionFilterWithRuleTypeTests : WebAppFixture<StartupWithDefaultOptions> | ||
{ | ||
private const string ControllerWithRuleTypeEndpoint = "WithRuleType"; | ||
private HttpClient Client { get; } | ||
|
||
public ModelValidationAsyncActionFilterWithRuleTypeTests() => Client = CreateClient(); | ||
|
||
[Fact(DisplayName = "Should return OK when payload is valid")] | ||
public async Task OnActionExecutionAsync_PayloadIsValid_ReturnOk() | ||
{ | ||
// Arrange | ||
var payload = new TestPayloadWithRuleType { Text = "Test" }; | ||
|
||
// Act | ||
var response = await Client.PostAsJsonAsync($"{ControllerWithRuleTypeEndpoint}/test-validator", payload); | ||
|
||
// Assert | ||
response.Should().Be200Ok(); | ||
} | ||
|
||
[Fact(DisplayName = "Should return bad request when payload is invalid")] | ||
public async Task OnActionExecutionAsync_PayloadIsInvalid_ReturnBadRequest() | ||
{ | ||
// Arrange | ||
var payload = new TestPayloadWithRuleType { Text = "" }; | ||
|
||
// Act | ||
var response = await Client.PostAsJsonAsync($"{ControllerWithRuleTypeEndpoint}/test-validator", payload); | ||
|
||
// Assert | ||
response.Should().Be400BadRequest(); | ||
var responseDetails = await response.Content.ReadFromJsonAsync<ValidationProblemDetails>(); | ||
responseDetails.Title.Should().Be("One or more validation errors occurred."); | ||
responseDetails.Errors.Should().BeEquivalentTo(new Dictionary<string, string[]> | ||
{ | ||
{ $"{RuleTypeConst.Prefix}.SOME_RULE.Text", new[] { "Text can't be null" } } | ||
}); | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
using JSM.FluentValidation.AspNet.AsyncFilter.Tests.Support.Models; | ||
using Microsoft.AspNetCore.Mvc; | ||
using System; | ||
|
||
namespace JSM.FluentValidation.AspNet.AsyncFilter.Tests.Support.Controllers | ||
{ | ||
[ApiController, Route("[controller]")] | ||
public class WithRuleTypeController : ControllerBase | ||
{ | ||
[HttpPost("test-validator")] | ||
public IActionResult Post([FromBody] TestPayloadWithRuleType request) => Ok(); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
using FluentValidation; | ||
|
||
namespace JSM.FluentValidation.AspNet.AsyncFilter.Tests.Support.Models | ||
{ | ||
public class TestPayloadWithRuleType | ||
{ | ||
public string Text { get; set; } | ||
} | ||
|
||
public class TestPayloadWithRuleTypeValidator : AbstractValidator<TestPayloadWithRuleType> | ||
{ | ||
public TestPayloadWithRuleTypeValidator() | ||
{ | ||
RuleFor(x => x.Text) | ||
.NotEmpty() | ||
.WithMessage("Text can't be null") | ||
.WithRuleType("SOME_RULE"); | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thought: we're gonna need to use the same extension method
WithErrorCode
in #8, but I think we can use it in both scenarios. We can set some predefined words as ErrorCodes to change the response status code.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice @luizhlelis, make sense.
We can use a new Enum.ErrorsStatusCode in this lib, creating a new method like "WithStatusCode(Enum.ErrorsStatusCode)".