FluentValidation Doesn't Work When Using WebApi [Route] Attribute
Asked Answered
C

1

7

I successfully implemented FluentValidation in my WebApi project controller that only had one HttpGet method. When I added another HttpGet method, I added route attribute to both methods. i.e. [Route("Method1")] and [Route("Method2")].

Now the ModelState comes back as true regardless of whether I enter any data or not.

Here is my code.

WebApiConfig

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {

        config.Filters.Add(new ValidateModelStateFilter());

        //FluentValidation
        FluentValidationModelValidatorProvider.Configure(config);

        // Web API routes
        config.MapHttpAttributeRoutes();

        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "{action}/{id}",
            defaults: new { controller = "Menu", id = RouteParameter.Optional}
        );


    }
}

ValidateModelStateFilter

public class ValidateModelStateFilter : ActionFilterAttribute
{
    public override void OnActionExecuting(HttpActionContext actionContext)
    {
        if (!actionContext.ModelState.IsValid)
        {
            actionContext.Response = actionContext.Request.CreateErrorResponse(HttpStatusCode.BadRequest, actionContext.ModelState);
        }
    }
}

Controller

[HttpGet]
[Route("Method1")]
public IHttpActionResult ReadAllMenusByApplication([FromUri] ReadAllMenusByApplicationInput input)
{
        var result = new List<ApplicationMenu>();
        ...
}

Input Object

using FluentValidation;
using FluentValidation.Attributes;

namespace MenuService.Models
{
[Validator(typeof(ReadAllMenusByApplicationInputValidator))]
public class ReadAllMenusByApplicationInput
{
    public ReadAllMenusByApplicationInput() {
        this.ApplicationName = string.Empty;
    }

    /// <summary>
    /// The MenuSystem name of the application
    /// </summary>
    public string ApplicationName { get; set; }
}

public class ReadAllMenusByApplicationInputValidator : AbstractValidator<ReadAllMenusByApplicationInput>
{
    public ReadAllMenusByApplicationInputValidator()
    {
        RuleFor(x => x.ApplicationName).NotEmpty();
    }
}

}

Causey answered 28/4, 2016 at 19:55 Comment(1)
Show the controller with both routes and also a sample of the request being sent.Ichthyic
I
0

Using this article for reference

Custom Validation in ASP.NET Web API with FluentValidation

You seem to have most of what is done in the referenced article.

Check your configuration order.

public static class WebApiConfig {
    public static void Register(HttpConfiguration config) {
        // Web API configuration and services
        config.Filters.Add(new ValidateModelStateFilter());

        // Web API routes
        config.MapHttpAttributeRoutes();

        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "{action}/{id}",
            defaults: new { controller = "Menu", id = RouteParameter.Optional}
        );

        //FluentValidation
        FluentValidationModelValidatorProvider.Configure(config);    
    }
}

FluentValidation automatically inserts its errors into the ModelState. You should include an error message.

public class ReadAllMenusByApplicationInputValidator : AbstractValidator<ReadAllMenusByApplicationInput> {
    public ReadAllMenusByApplicationInputValidator() {
        RuleFor(x => x.ApplicationName).NotEmpty()
            .WithMessage("The Application Name cannot be blank.");
    }
}

The article has some content that is outside of the scope of your question. mainly wrapping the responses but everything else should work for you.

Ichthyic answered 19/6, 2016 at 2:22 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.