Reputation: 377
I want to disable a model validation on a specific Action method in a Controller. I have this scenario :
public class SomeDto
{
public string Name { get; set; }
}
public class SomeDtoValidator : AbstractValidator<SomeDto>, ISomeDtoValidator
{
public SomeDtoValidator ()
{
RuleFor(someDto=> someDto.Name).NotNull().WithMessage("Name property can't be null.");
}
}
I have ISomeDtoValidator because I register all my validators in my own way :
public class Startup
{
// .... constructor ....
public void ConfigureServices(IServiceCollection services)
{
services.AddOptions();
services.AddMvc(setup => {
//...others setups...
}).AddFluentValidation();
services.RegisterTypes(Configuration)
.RegisterFluentValidation()
.RegisterMappingsWithAutomapper()
.RegisterMvcConfigurations();
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env, IConfiguration configuration)
{
// ...
}
}
I have this Action Method inside a Controller :
[DisableFormValueModelBinding]
public async Task<IActionResult> CreateSome(Guid someId, SomeDto someDto)
{
//..... Manually binding someDto...
var validator = new SomeValidator();
validator.Validate(someDto);
// Doing something more ........
return Ok();
}
I disabled the modelBinding's MVC because I want to do something before binding SomeDto and, therefore, I don't want to apply any validator on SomeDto either. So, there is any way to achieve that ?? For example, something like this :
[DisableValidator] // Or [DisableValidator(typeof(SomeDtoValidator))] whatever
[DisableFormValueModelBinding]
public async Task<IActionResult> CreateSome(Guid someId, SomeDto someDto)
{
//..... Manually binding someDto...
var validator = new SomeValidator();
validator.Validate(someDto);
// Doing something more ........
return Ok();
}
Upvotes: 8
Views: 8997
Reputation: 1775
You can skip validation by adding the following attribute to your action methods parameter:
public ActionResult Save([CustomizeValidator(Skip = true)] Customer model) {
// ...
}
This is described in the docs here: https://docs.fluentvalidation.net/en/latest/aspnet.html#validator-customization
Upvotes: 8
Reputation: 1734
You can use RuleSets.
see: https://fluentvalidation.net/start#rulesets
usage: https://fluentvalidation.net/aspnet#validator-customization
public class CustomerValidator : AbstractValidator<Customer>
{
public CustomerValidator()
{
RuleFor(customer => customer.Surname).NotEmpty();
RuleFor(customer => customer.Forename).NotEmpty().WithMessage("Please specify a first name");
RuleFor(customer => customer.Address).Length(20, 250);
RuleSet("Names", () =>
{
RuleFor(x => x.Surname).NotNull();
RuleFor(x => x.Forename).NotNull();
});
RuleSet("Empty", () =>
{
});
}
}
Test code:
Customer customer = new Customer();
var validator = new CustomerValidator();
var validationResult = validator.Validate(customer, ruleSet: "Names");
// 2 errors: Surname and Forname
validationResult = validator.Validate(customer, ruleSet: "Empty");
// no errors
You can configure RuleSet in controller:
public ActionResult SaveNoValidate([CustomizeValidator(RuleSet="Empty")] Customer customer) {
// ...
}
public ActionResult SaveValidateNames([CustomizeValidator(RuleSet="Names")] Customer customer ) {
// ...
}
Upvotes: 3
Reputation: 377
I reached my goal with @Alexey.Petriashev's help, putting only a RuleSet in the validator. When pipeline calls the validator, it doesn't make a validation because the pipeline calls are without RuleSet. Bellow is an example of how I solved the issue:
public class CustomerValidator : AbstractValidator<Customer>
{
public CustomerValidator()
{
RuleSet("Manually", () =>
{
RuleFor(x => x.Surname).NotNull();
RuleFor(x => x.Forename).NotNull();
});
}
}
public ActionResult ActionWithoutValidationExecuted(Customer customer)
{
//..... Manually binding customer...
var validator = new CustomerValidator();
var validResult = validator.Validate(customer, ruleSet: "Manually");
// Doing something more ........
return Ok();
}
Upvotes: 2