Skip to content

Instantly share code, notes, and snippets.

@karbyninc
Last active March 1, 2016 15:47
Show Gist options
  • Save karbyninc/c69b568b42ba91ff4946 to your computer and use it in GitHub Desktop.
Save karbyninc/c69b568b42ba91ff4946 to your computer and use it in GitHub Desktop.
public class CustomerValidator: AbstractValidator
{
public CustomerValidator()
{
RuleFor(customer => customer.Surname).NotEmpty();
RuleFor(customer => customer.Forename).NotEmpty().WithMessage("Please specify a first name");
RuleFor(customer => customer.Discount).NotEqual(0).When(customer => customer.HasDiscount);
RuleFor(customer => customer.Address).Length(20, 250);
RuleFor(customer => customer.Postcode).Must(BeAValidPostcode).WithMessage("Please specify a valid postcode");
}
private bool BeAValidPostcode(string postcode)
{
// custom postcode validating logic goes here
}
}
Customer customer = new Customer();
CustomerValidator validator = new CustomerValidator();
ValidationResult results = validator.Validate(customer);
bool validationSucceeded = results.IsValid;
IList failures = results.Errors;
using System.Collections.Generic;
using FluentValidation.Validators;
public class ListMustContainFewerThanTenItemsValidator : PropertyValidator
{
public ListMustContainFewerThanTenItemsValidator()
: base("Property {PropertyName} contains more than 10 items!")
{
}
protected override bool IsValid(PropertyValidatorContext context)
{
var list = context.PropertyValue as IList;
if(list != null && list.Count >= 10)
{
return false;
}
return true;
}
public static class MyValidatorExtensions
{
public static IRuleBuilderOptions<T, IList> MustContainFewerThanTenItems<T, TElement>(this IRuleBuilder<T, IList> ruleBuilder)
{
return ruleBuilder.SetValidator(new ListMustContainFewerThanTenItemsValidator());
}
}
This can then fit into the standard "RuleFor" chaining, i.e.:
public class PersonValidator : AbstractValidator
{
public PersonValidator() {
RuleFor(person => person.Pets).MustContainFewerThanTenItems();
}
}
//Configuration for Fluent Validation
Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
builder.RegisterAssemblyTypes(assemblies).AsClosedTypesOf(typeof(AbstractValidator<>));
public class ValidateModelAttribute : ActionFilterAttribute
{
/// <summary>
/// Validate the model before control passes to the controller's action
/// </summary>
/// <param name="actionContext"></param>
public override void OnActionExecuting(HttpActionContext actionContext)
{
//Validate the model with traditional data annotations specified
if (!actionContext.ModelState.IsValid)
throw new HttpResponseException(actionContext.Request.CreateErrorResponse(HttpStatusCode.BadRequest, actionContext.ModelState));
//Iterate through each parameter in the controller to identify the first DTO/Entity
foreach (var nvp in actionContext.ActionArguments)
{
if (nvp.Value != null)
{
Type t = nvp.Value.GetType();
//If one of our parameters is a class, perform validation on it if it has any validators associated with it
if (t.IsClass)
{
//Determine if there are any validators associated with this entity type
IValidator validator = (IValidator)actionContext.Request.GetDependencyScope().GetService(typeof(AbstractValidator<>).MakeGenericType(t));
if (validator != null) //if there was a validator
{
var validationResult = validator.Validate(nvp.Value); //Validate based upon the Fluent rules registered
if (!validationResult.IsValid) //If there was an error, return it to the front end
throw new HttpResponseException(actionContext.Request.CreateErrorResponse(HttpStatusCode.BadRequest, String.Join(",", (validationResult.Errors.Select(err => err.ErrorMessage)))));
}
}
}
}
}
//Validate the model with traditional data annotations specified
if (!actionContext.ModelState.IsValid)
throw new HttpResponseException(actionContext.Request.CreateErrorResponse(HttpStatusCode.BadRequest, actionContext.ModelState));
//Iterate through each parameter in the controller to identify the first DTO/Entity
foreach (var nvp in actionContext.ActionArguments)
{
if (nvp.Value != null)
{
Type t = nvp.Value.GetType();
//If one of our parameters is a class, perform validation on it if it has any validators associated with it
if (t.IsClass)
{
...
}
}
}
//Determine if there are any validators associated with this entity type
IValidator validator = (IValidator)actionContext.Request.GetDependencyScope().GetService(typeof(AbstractValidator<>).MakeGenericType(t));
if (validator != null) //if there was a validator
{
var validationResult = validator.Validate(nvp.Value); //Validate based upon the Fluent rules registered
if (!validationResult.IsValid) //If there was an error, return it to the front end
throw new HttpResponseException(actionContext.Request.CreateErrorResponse(HttpStatusCode.BadRequest, String.Join(",", (validationResult.Errors.Select(err => err.ErrorMessage)))));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment