Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
211 views
in Technique[技术] by (71.8m points)

FluentValidation failure not returning BadRequest

I have wired up FluentValidation as per instructions, and when debuging test I can see that model is invalid based on the test setup, but exception is not thrown, but rather method on the controller is being executed. This is on 3.1 with EndPoint routing enabled. Is there anything else one needs to do to get this to work and throw. What happens is that validation obviously runs; it shows as ModelState invalid and correct InstallmentId is invalid, but it keeps processing in Controller instead of throwing exception.

services.AddMvc(
                    options =>
                    {
                         options.EnableEndpointRouting = true;
                         //// options.Filters.Add<ExceptionFilter>();
                         //// options.Filters.Add<CustomerRequestFilter>();
                     })
                    .AddFluentValidation(
                         config =>
                         {
                            config.RegisterValidatorsFromAssemblyContaining<Startup>();
                         })

Command and Validator

     public class ProcessManualPayment
        {
            public class Command
                : CustomerRequest<Result?>
            {
                public Guid PaymentPlanId { get; set; }
    
                public Guid InstallmentId { get; set; }
    
                public Guid PaymentCardId { get; set; }
            }
    
          
            public class Validator : AbstractValidator<Command>
            {
                public Validator()
                {
                    this.RuleFor(x => x.CustomerId)
                        .IsValidGuid();
    
                    this.RuleFor(x => x.PaymentPlanId)
                        .IsValidGuid();
    
                    this.RuleFor(x => x.InstallmentId)
                        .IsValidGuid();
    
                    this.RuleFor(x => x.PaymentCardId)
                        .IsValidGuid();
                }
            }

Controller

    [Authorize]
    [HttpPost]
    [Route("payments")]
    [ProducesResponseType(StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status400BadRequest)]
    public async Task<IActionResult> ProcessManualPayment(
           [FromBody]
            ProcessManualPayment.Command command)
    {

Test

            [Fact]
            public async Task When_Command_Has_Invalid_Payload_Should_Fail()
            {
                var client = this.factory.CreateClient();

                // Arrange
                var validCmd = new ProcessManualPayment.Command()
                {
                    CustomerId = Guid.NewGuid(),
                    PaymentPlanId = Guid.NewGuid(),
                    InstallmentId = Guid.NewGuid(),
                    PaymentCardId = Guid.NewGuid(),
                };

                var validCmdJson = JsonConvert.SerializeObject(validCmd, Formatting.None);

                var jObject = JObject.Parse(validCmdJson);

                jObject["installmentId"] = "asdf";

                var payload = jObject.ToString(Formatting.None);

                // Act
                var content = new StringContent(payload, Encoding.UTF8, MediaTypeNames.Application.Json);

                var response = await client.PostAsync(MakePaymentUrl, content);

                var returned = await response.Content.ReadAsStringAsync();

                response.StatusCode.ShouldBe(HttpStatusCode.BadRequest);
            }

            [Fact]
            public async Task When_Payload_Is_Null_Should_Fail()
            {
                // Arrange
                var client = this.factory.CreateClient();

                // Act
                var response = await client.PostAsJsonAsync(MakePaymentUrl, null);

                // Assert
                response.StatusCode.ShouldBe(HttpStatusCode.BadRequest);
            }

GuidValidator

    public class GuidValidator : PropertyValidator
    {
        public GuidValidator()
            : base("'{PropertyName}' value {AttemptedValue} is not a valid Guid.")
        {
        }

        protected override bool IsValid(PropertyValidatorContext context)
        {
            context.MessageFormatter.AppendArgument("AttemptedValue", context.PropertyValue ?? "'null'");

            if (context.PropertyValue == null)
            {
                return false;
            }

            Guid.TryParse(context.PropertyValue.ToString(), out var value);

            return IsValid(value);
        }

        private static bool IsValid(Guid? value) =>
            value.HasValue
            && !value.Equals(Guid.Empty);
    }

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Mystery solved, I was missing [ApiController] attribute on the controller.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...