Quantcast
Channel: Fluent Validation for .NET
Viewing all 1917 articles
Browse latest View live

Updated Wiki: Customising

$
0
0

Overriding the Default Error

You can override the default error message for a validator by calling the WithMessage method on a validator definition:

RuleFor(customer => customer.Surname).NotNull().WithMessage("Please ensure that you have entered your Surname");


Note that custom error messages can contain placeholders for special values such as the name of the property being validated. This means the above error message could be re-written as:

RuleFor(customer => customer.Surname).NotNull().WithMessage("Please ensure you have entered your {PropertyName}");


...and the value 'Surname' will be inserted. For a complete list of error message placeholders see the Validators page.

It is also possible to use your own custom arguments in the validation message. These can either be static values or references to other properties on the object being validated:

//Using static values in a custom message:
RuleFor(customer => x.Surname).NotNull().WithMessage("This message references some static values: {0} {1}", "hello", 5);
//Result would be "This message references some static values: hello 5"

//Referencing other property values:
RuleFor(customer => customer.Surname)
  .NotNull()
  .WithMesasge("This message references some other properties: Forename: {0} Discount: {1}", 
    customer => customer.Forename, 
    customer => customer.Discount
  );
//Result would be: "This message references some other properties: Forename: Jeremy Discount: 100"


If you want to override all of FluentValidation's default error messages, check out FluentValidation's support for Localization

Overriding the Default Property Name

The default validation error messages contain the property name being validated. For example, if you were to define a validator like this:

RuleFor(customer => customer.Surname).NotNull();


...then the default error message would be 'Surname' must not be empty. Although you can override the entire error message by calling WithMessage, you can also replace just the property name by calling WithName:

RuleFor(customer => customer.Surname).NotNull().WithName("Last name");


Now the error message would be 'Last name' must not be empty.

Note that this only replaces the name of the property in the error message. When you inspect the Errors collection on the ValidationResult, this error will still be associated with a property called "Surname". If you want to completely rename the property, you can use the WithPropertyName method instead.

Property name resolution is also pluggable. By default, the name of the property extracted from the MemberExpression passed to RuleFor. If you want change this logic, you can set the PropertyNameResolver property on the ValidatorOptions class:

ValidatorOptions.PropertyNameResolver = (type, member) => {
  if(member != null) {
     return member.Name + "Foo";
  }
  return null;
};


This is not a realistic example as it changes all properties to have the suffix "Foo", but hopefully illustrates the point.

Specifying a condition with When/Unless

The When and Unless methods can be used to specify conditions that control when the rule should execute. For example, this rule on the CustomerDiscount property will only execute when IsPreferredCustomer is true:

RuleFor(customer => customer.CustomerDiscount).GreaterThan(0).When(customer => customer.IsPreferredCustomer);


The Unless method is simply the opposite of When.

If you need to specify the same condition for multiple rules then you can call the top-level When method instead of chaining the When call at the end of the rule:

When(customer => customer.IsPreferred, () => {
   RuleFor(customer => customer.CustomerDiscount).GreaterThan(0);
   RuleFor(customer => customer.CreditCardNumber).NotNull();
});


This time, the condition will be applied to both rules.

Setting the Cascade mode

You can set the cascade mode to customise how FluentValidation executes chained validators when a particular validator in the chain fails.

Imagine you have two validators defined as part of a single rule definition, a NotNull validator and a NotEqual validator:

RuleFor(x => x.Surname).NotNull().NotEqual("foo");


This will first check whether the Surname property is not null and then will check if it's not equal to the string "foo". If the first validator (NotNull) fails, then the call to NotEqual will still be invoked. This can be changed by specifying a cascade mode of StopOnFirstFailure:

RuleFor(x => x.Surname).Cascade(CascadeMode.StopOnFirstFailure).NotNull().NotEqual("foo");


Now, if the NotNull validator fails then the NotEqual validator will not be executed. This is particularly useful if you have a complex chain where each validator depends on the previous validator to succeed.

The two cascade modes are:
  • Continue (the default) - always invokes all validators in a rule definition
  • StopOnFirstFailure - stops executing a rule as soon as a validator fails

As well as being set at the rule level, the cascade mode can also be set globally for all validators, or for all the rules in a particular validator class.

To set the cascade mode globally, you can set the CascadeMode property on the static ValidatorOptions class during your application's startup routine:

ValidatorOptions.CascadeMode = CascadeMode.StopOnFirstFailure;


This can then be overriden by individual validator classes or by individual rules.

To set the cascade mode for all rules inside a single validator class, set the CascadeMode property on AbstractValidator:

public class PersonValidator : AbstractValidator<Person> {
  public PersonValidator() {
    
    // First set the cascade mode
    CascadeMode = CascadeMode.StopOnFirstFailure;
    
    // Rule definitions follow
    RuleFor(...) 
    RuleFor(...)

   }
}

New Post: Documentation: DisplayNameAttribute

$
0
0
I accidentally discovered this trying to create a PropertyNameResolver, but FluentValidation already check for System.ComponentModel.DisplayNameAttribute in properties and use that in error messages.

The documentation has no mention of this anywhere.

I think this should be documented as one of the simplest ways of customizing the PropertyName in error messages.

Updated Wiki: Customising

$
0
0

Overriding the Default Error

You can override the default error message for a validator by calling the WithMessage method on a validator definition:

RuleFor(customer => customer.Surname).NotNull().WithMessage("Please ensure that you have entered your Surname");


Note that custom error messages can contain placeholders for special values such as the name of the property being validated. This means the above error message could be re-written as:

RuleFor(customer => customer.Surname).NotNull().WithMessage("Please ensure you have entered your {PropertyName}");


...and the value 'Surname' will be inserted. For a complete list of error message placeholders see the Validators page.

It is also possible to use your own custom arguments in the validation message. These can either be static values or references to other properties on the object being validated:

//Using static values in a custom message:
RuleFor(customer => x.Surname).NotNull().WithMessage("This message references some static values: {0} {1}", "hello", 5);
//Result would be "This message references some static values: hello 5"

//Referencing other property values:
RuleFor(customer => customer.Surname)
  .NotNull()
  .WithMesasge("This message references some other properties: Forename: {0} Discount: {1}", 
    customer => customer.Forename, 
    customer => customer.Discount
  );
//Result would be: "This message references some other properties: Forename: Jeremy Discount: 100"


If you want to override all of FluentValidation's default error messages, check out FluentValidation's support for Localization

Overriding the Default Property Name

The default validation error messages contain the property name being validated. For example, if you were to define a validator like this:

RuleFor(customer => customer.Surname).NotNull();


...then the default error message would be 'Surname' must not be empty. Although you can override the entire error message by calling WithMessage, you can also replace just the property name by calling WithName:

RuleFor(customer => customer.Surname).NotNull().WithName("Last name");


Now the error message would be 'Last name' must not be empty.

Note that this only replaces the name of the property in the error message. When you inspect the Errors collection on the ValidationResult, this error will still be associated with a property called "Surname". If you want to completely rename the property, you can use the WithPropertyName method instead.

Property name resolution is also pluggable. By default, the name of the property extracted from the MemberExpression passed to RuleFor. If you want change this logic, you can set the PropertyNameResolver property on the ValidatorOptions class:

ValidatorOptions.PropertyNameResolver = (type, member) => {
  if(member != null) {
     return member.Name + "Foo";
  }
  return null;
};


This is not a realistic example as it changes all properties to have the suffix "Foo", but hopefully illustrates the point.

Additionally, FluentValidation will respect the use of the DisplayName and Display attributes for generating the property's name within error messages.

Specifying a condition with When/Unless

The When and Unless methods can be used to specify conditions that control when the rule should execute. For example, this rule on the CustomerDiscount property will only execute when IsPreferredCustomer is true:

RuleFor(customer => customer.CustomerDiscount).GreaterThan(0).When(customer => customer.IsPreferredCustomer);


The Unless method is simply the opposite of When.

If you need to specify the same condition for multiple rules then you can call the top-level When method instead of chaining the When call at the end of the rule:

When(customer => customer.IsPreferred, () => {
   RuleFor(customer => customer.CustomerDiscount).GreaterThan(0);
   RuleFor(customer => customer.CreditCardNumber).NotNull();
});


This time, the condition will be applied to both rules.

Setting the Cascade mode

You can set the cascade mode to customise how FluentValidation executes chained validators when a particular validator in the chain fails.

Imagine you have two validators defined as part of a single rule definition, a NotNull validator and a NotEqual validator:

RuleFor(x => x.Surname).NotNull().NotEqual("foo");


This will first check whether the Surname property is not null and then will check if it's not equal to the string "foo". If the first validator (NotNull) fails, then the call to NotEqual will still be invoked. This can be changed by specifying a cascade mode of StopOnFirstFailure:

RuleFor(x => x.Surname).Cascade(CascadeMode.StopOnFirstFailure).NotNull().NotEqual("foo");


Now, if the NotNull validator fails then the NotEqual validator will not be executed. This is particularly useful if you have a complex chain where each validator depends on the previous validator to succeed.

The two cascade modes are:
  • Continue (the default) - always invokes all validators in a rule definition
  • StopOnFirstFailure - stops executing a rule as soon as a validator fails

As well as being set at the rule level, the cascade mode can also be set globally for all validators, or for all the rules in a particular validator class.

To set the cascade mode globally, you can set the CascadeMode property on the static ValidatorOptions class during your application's startup routine:

ValidatorOptions.CascadeMode = CascadeMode.StopOnFirstFailure;


This can then be overriden by individual validator classes or by individual rules.

To set the cascade mode for all rules inside a single validator class, set the CascadeMode property on AbstractValidator:

public class PersonValidator : AbstractValidator<Person> {
  public PersonValidator() {
    
    // First set the cascade mode
    CascadeMode = CascadeMode.StopOnFirstFailure;
    
    // Rule definitions follow
    RuleFor(...) 
    RuleFor(...)

   }
}

New Post: Documentation: DisplayNameAttribute

$
0
0
I've added this to the docs. Thanks for the suggestion.

Updated Wiki: Customising

$
0
0

Overriding the Default Error

You can override the default error message for a validator by calling the WithMessage method on a validator definition:

RuleFor(customer => customer.Surname).NotNull().WithMessage("Please ensure that you have entered your Surname");


Note that custom error messages can contain placeholders for special values such as the name of the property being validated. This means the above error message could be re-written as:

RuleFor(customer => customer.Surname).NotNull().WithMessage("Please ensure you have entered your {PropertyName}");


...and the value 'Surname' will be inserted. For a complete list of error message placeholders see the Validators page.

It is also possible to use your own custom arguments in the validation message. These can either be static values or references to other properties on the object being validated:

//Using static values in a custom message:
RuleFor(customer => x.Surname).NotNull().WithMessage("This message references some static values: {0} {1}", "hello", 5);
//Result would be "This message references some static values: hello 5"

//Referencing other property values:
RuleFor(customer => customer.Surname)
  .NotNull()
  .WithMesasge("This message references some other properties: Forename: {0} Discount: {1}", 
    customer => customer.Forename, 
    customer => customer.Discount
  );
//Result would be: "This message references some other properties: Forename: Jeremy Discount: 100"


If you want to override all of FluentValidation's default error messages, check out FluentValidation's support for Localization

Overriding the Default Property Name

The default validation error messages contain the property name being validated. For example, if you were to define a validator like this:

RuleFor(customer => customer.Surname).NotNull();


...then the default error message would be 'Surname' must not be empty. Although you can override the entire error message by calling WithMessage, you can also replace just the property name by calling WithName:

RuleFor(customer => customer.Surname).NotNull().WithName("Last name");


Now the error message would be 'Last name' must not be empty.

Note that this only replaces the name of the property in the error message. When you inspect the Errors collection on the ValidationResult, this error will still be associated with a property called "Surname". If you want to completely rename the property, you can use the WithPropertyName method instead.

Property name resolution is also pluggable. By default, the name of the property extracted from the MemberExpression passed to RuleFor. If you want change this logic, you can set the PropertyNameResolver property on the ValidatorOptions class:

ValidatorOptions.PropertyNameResolver = (type, member) => {
  if(member != null) {
     return member.Name + "Foo";
  }
  return null;
};


This is not a realistic example as it changes all properties to have the suffix "Foo", but hopefully illustrates the point.

Additionally, FluentValidation will respect the use of the DisplayName and Display attributes for generating the property's name within error messages:

{{
public class Person {
[Display(Name="Last name")]
public string Surname { get; set; }
}

Specifying a condition with When/Unless

The *When* and *Unless* methods can be used to specify conditions that control when the rule should execute. For example, this rule on the CustomerDiscount property will only execute when IsPreferredCustomer is true:

RuleFor(customer => customer.CustomerDiscount).GreaterThan(0).When(customer => customer.IsPreferredCustomer);


The Unless method is simply the opposite of When.

If you need to specify the same condition for multiple rules then you can call the top-level When method instead of chaining the When call at the end of the rule:

When(customer => customer.IsPreferred, () => {
   RuleFor(customer => customer.CustomerDiscount).GreaterThan(0);
   RuleFor(customer => customer.CreditCardNumber).NotNull();
});


This time, the condition will be applied to both rules.

Setting the Cascade mode

You can set the cascade mode to customise how FluentValidation executes chained validators when a particular validator in the chain fails.

Imagine you have two validators defined as part of a single rule definition, a NotNull validator and a NotEqual validator:

RuleFor(x => x.Surname).NotNull().NotEqual("foo");


This will first check whether the Surname property is not null and then will check if it's not equal to the string "foo". If the first validator (NotNull) fails, then the call to NotEqual will still be invoked. This can be changed by specifying a cascade mode of StopOnFirstFailure:

RuleFor(x => x.Surname).Cascade(CascadeMode.StopOnFirstFailure).NotNull().NotEqual("foo");


Now, if the NotNull validator fails then the NotEqual validator will not be executed. This is particularly useful if you have a complex chain where each validator depends on the previous validator to succeed.

The two cascade modes are:
  • Continue (the default) - always invokes all validators in a rule definition
  • StopOnFirstFailure - stops executing a rule as soon as a validator fails

As well as being set at the rule level, the cascade mode can also be set globally for all validators, or for all the rules in a particular validator class.

To set the cascade mode globally, you can set the CascadeMode property on the static ValidatorOptions class during your application's startup routine:

ValidatorOptions.CascadeMode = CascadeMode.StopOnFirstFailure;


This can then be overriden by individual validator classes or by individual rules.

To set the cascade mode for all rules inside a single validator class, set the CascadeMode property on AbstractValidator:

public class PersonValidator : AbstractValidator<Person> {
  public PersonValidator() {
    
    // First set the cascade mode
    CascadeMode = CascadeMode.StopOnFirstFailure;
    
    // Rule definitions follow
    RuleFor(...) 
    RuleFor(...)

   }
}

Updated Wiki: Customising

$
0
0

Overriding the Default Error

You can override the default error message for a validator by calling the WithMessage method on a validator definition:

RuleFor(customer => customer.Surname).NotNull().WithMessage("Please ensure that you have entered your Surname");


Note that custom error messages can contain placeholders for special values such as the name of the property being validated. This means the above error message could be re-written as:

RuleFor(customer => customer.Surname).NotNull().WithMessage("Please ensure you have entered your {PropertyName}");


...and the value 'Surname' will be inserted. For a complete list of error message placeholders see the Validators page.

It is also possible to use your own custom arguments in the validation message. These can either be static values or references to other properties on the object being validated:

//Using static values in a custom message:
RuleFor(customer => x.Surname).NotNull().WithMessage("This message references some static values: {0} {1}", "hello", 5);
//Result would be "This message references some static values: hello 5"

//Referencing other property values:
RuleFor(customer => customer.Surname)
  .NotNull()
  .WithMesasge("This message references some other properties: Forename: {0} Discount: {1}", 
    customer => customer.Forename, 
    customer => customer.Discount
  );
//Result would be: "This message references some other properties: Forename: Jeremy Discount: 100"


If you want to override all of FluentValidation's default error messages, check out FluentValidation's support for Localization

Overriding the Default Property Name

The default validation error messages contain the property name being validated. For example, if you were to define a validator like this:

RuleFor(customer => customer.Surname).NotNull();


...then the default error message would be 'Surname' must not be empty. Although you can override the entire error message by calling WithMessage, you can also replace just the property name by calling WithName:

RuleFor(customer => customer.Surname).NotNull().WithName("Last name");


Now the error message would be 'Last name' must not be empty.

Note that this only replaces the name of the property in the error message. When you inspect the Errors collection on the ValidationResult, this error will still be associated with a property called "Surname". If you want to completely rename the property, you can use the WithPropertyName method instead.

Property name resolution is also pluggable. By default, the name of the property extracted from the MemberExpression passed to RuleFor. If you want change this logic, you can set the PropertyNameResolver property on the ValidatorOptions class:

ValidatorOptions.PropertyNameResolver = (type, member) => {
  if(member != null) {
     return member.Name + "Foo";
  }
  return null;
};


This is not a realistic example as it changes all properties to have the suffix "Foo", but hopefully illustrates the point.

Additionally, FluentValidation will respect the use of the DisplayName and Display attributes for generating the property's name within error messages:

public class Person {
  [Display(Name="Last name")]
  public string Surname { get; set; }
}

Specifying a condition with When/Unless

The When and Unless methods can be used to specify conditions that control when the rule should execute. For example, this rule on the CustomerDiscount property will only execute when IsPreferredCustomer is true:

RuleFor(customer => customer.CustomerDiscount).GreaterThan(0).When(customer => customer.IsPreferredCustomer);


The Unless method is simply the opposite of When.

If you need to specify the same condition for multiple rules then you can call the top-level When method instead of chaining the When call at the end of the rule:

When(customer => customer.IsPreferred, () => {
   RuleFor(customer => customer.CustomerDiscount).GreaterThan(0);
   RuleFor(customer => customer.CreditCardNumber).NotNull();
});


This time, the condition will be applied to both rules.

Setting the Cascade mode

You can set the cascade mode to customise how FluentValidation executes chained validators when a particular validator in the chain fails.

Imagine you have two validators defined as part of a single rule definition, a NotNull validator and a NotEqual validator:

RuleFor(x => x.Surname).NotNull().NotEqual("foo");


This will first check whether the Surname property is not null and then will check if it's not equal to the string "foo". If the first validator (NotNull) fails, then the call to NotEqual will still be invoked. This can be changed by specifying a cascade mode of StopOnFirstFailure:

RuleFor(x => x.Surname).Cascade(CascadeMode.StopOnFirstFailure).NotNull().NotEqual("foo");


Now, if the NotNull validator fails then the NotEqual validator will not be executed. This is particularly useful if you have a complex chain where each validator depends on the previous validator to succeed.

The two cascade modes are:
  • Continue (the default) - always invokes all validators in a rule definition
  • StopOnFirstFailure - stops executing a rule as soon as a validator fails

As well as being set at the rule level, the cascade mode can also be set globally for all validators, or for all the rules in a particular validator class.

To set the cascade mode globally, you can set the CascadeMode property on the static ValidatorOptions class during your application's startup routine:

ValidatorOptions.CascadeMode = CascadeMode.StopOnFirstFailure;


This can then be overriden by individual validator classes or by individual rules.

To set the cascade mode for all rules inside a single validator class, set the CascadeMode property on AbstractValidator:

public class PersonValidator : AbstractValidator<Person> {
  public PersonValidator() {
    
    // First set the cascade mode
    CascadeMode = CascadeMode.StopOnFirstFailure;
    
    // Rule definitions follow
    RuleFor(...) 
    RuleFor(...)

   }
}

New Post: Count invalid items in a model

$
0
0
Simple validation, loops over all the boxes and makes sure you enter something into at least one of them.
            RuleFor(model => model.AnyInvoicesEntered)
                .NotEmpty()
                .When(AtLeastOneValueEntered)
                .WithMessage("No Invoices entered");

        private bool AtLeastOneValueEntered(PaymentViewModel model)
        {
            int countOfInvocies = model.InvoiceViewModels.Count(x => x.Number != null);

            if (countOfInvocies == 0)
            {
                return true;
            }
            return false;
        }
Problem is if you enter an invalid number in the box, the validation does not count it as something being entered and throws the error saying there is nothing entered. I need to get it to only show the one error.

See the full code and screen shot with both errors:
namespace WS.App.Internet.ViewModels
{
    [Validator(typeof(PaymentValidator))]
    public class PaymentViewModel
    {
        public string AnyInvoicesEntered { get; set; }

        [DisplayName("Payment Method")]
        public int? PaymentMethod { get; set; }

        [DisplayName("Confirmation Email Address")]
        [Email]
        public string ConformationEmailAddress { get; set; }

        [DisplayFormat(DataFormatString = "{0:F2}", ApplyFormatInEditMode = true)]
        [DisplayName("Sub-Total")]
        public Decimal SubTotal { get; set; }

        [DisplayFormat(DataFormatString = "{0:F2}", ApplyFormatInEditMode = true)]
        [DisplayName("Tax")]
        public Decimal TaxTotal { get; set; }

        [DisplayFormat(DataFormatString = "{0:F2}", ApplyFormatInEditMode = true)]
        [DisplayName("Total Payment")]
        public Decimal? PaymentTotal { get; set; }

        public List<InvoiceViewModel> InvoiceViewModels { get; set; }
        public IEnumerable<SelectListItem> PaymentMethods { get; set; }
    }

    public class PaymentValidator : AbstractValidator<PaymentViewModel>
    {
        public PaymentValidator()
        {
            RuleFor(model => model.ConformationEmailAddress)
                .NotEmpty()
                .When(model => model.PaymentTotal > 0)
                .WithMessage("Confirmation Email Address is required");
            RuleFor(model => model.PaymentMethod)
                .NotEmpty()
                .When(model => model.PaymentTotal > 0)
                .WithMessage("Payment Method is required");
            RuleFor(model => model.PaymentTotal)
                .NotEqual(0)
                .WithMessage("Total Payment must be greater than $0.00");
            RuleFor(model => model.AnyInvoicesEntered)
                .NotEmpty()
                .When(AtLeastOneValueEntered)
                .WithMessage("No Invoices entered");
        }

        private bool AtLeastOneValueEntered(PaymentViewModel model)
        {
            int countOfInvocies = model.InvoiceViewModels.Count(x => x.Number != null);

            if (countOfInvocies == 0)
            {
                return true;
            }
            return false;
        }
    }
}
In case the image doesn't show, it is here:

https://www.dropbox.com/sh/4dzsm56os5dlkba/PWH18VZt11

Image

New Post: Validating Object Graphs

$
0
0
I see how you can re-use a validator for Complex Properties and Collections, but how will it work when the reference is bi-directional? Will the example below produce an infinite loop, and if so what is the best way to handle this?
public class Customer {
  public string Name { get; set; }
  public Address Address { get; set; }
}

public class Address {
  public string Line1 { get; set; }
  public string Line2 { get; set; }
  public string Town { get; set; }
  public string County { get; set; }
  public string Postcode { get; set; }
  public Customer Customer { get; set; }
}

public class AddressValidator : AbstractValidator<Address> {
  public AddressValidator() {
    RuleFor(address => address.Postcode).NotNull();
    RuleFor(address => address.Customer).SetValidator(new CustomerValidator());
    //etc
  }
}

public class CustomerValidator : AbstractValidator<Customer> {
  public CustomerValidator() {
    RuleFor(customer => customer.Name).NotNull();
    RuleFor(customer => customer.Address).SetValidator(new AddressValidator());
  }
} 

New Post: Idea for integration

$
0
0
You could probably use T4 templates to generate your validation classes. Look at the Reverse Engineer Code First in Entity Framework Power Tools. It gives you the option to generate your model, mappings, and context from the DB. It also gives you the option to customize the T4 templates. I am actually using this to generate my models, mappings, and context - and I was able to copy a lot of the mapping functionality and translate it into FluentValidation syntax.
namespace <#= code.EscapeNamespace(efHost.Namespace) #>.Validation
{
    public partial class <#= efHost.EntityType.Name #>Validator : AbstractValidator<<#= efHost.EntityType.Name #>>
    {
        public <#= efHost.EntityType.Name #>Validator()
        {
<#
foreach (var prop in efHost.EntityType.Properties)
{
    var isKey = efHost.EntityType.KeyMembers.Contains(prop);

    if (!isKey)
    {
        var validationLines = new List<string>();
        var formattedPropertyName = System.Text.RegularExpressions.Regex.Replace(prop.Name, "((?<=[a-z])[A-Z]|[A-Z](?=[a-z]))", " $1").Trim();

        if (!prop.Nullable)
        {
            validationLines.Add(String.Format(".NotNull().WithMessage(\"{0} cannot be empty.\")", formattedPropertyName));
        }

        var isString = prop.TypeUsage.ToString().Equals("Edm.String");

        if (!prop.Nullable && isString)
        {
            validationLines.Add(String.Format(".NotEmpty().WithMessage(\"{0} cannot be empty.\")", formattedPropertyName));
        }

        var maxLengthFacet = (Facet)prop.TypeUsage.Facets.SingleOrDefault(f => f.Name == "MaxLength");
        if (maxLengthFacet != null && !maxLengthFacet.IsUnbounded)
        {
            validationLines.Add(string.Format(".Length(0, {0}).WithMessage(\"{1} cannot be over {0} characters in length.\")", maxLengthFacet.Value, formattedPropertyName));
        }


        if (validationLines.Any())
        {
#>
            RuleFor(m => m.<#= prop.Name #>)
                <#= string.Join("\r\n                ", validationLines) #>;

<#
        }
    }
}
#>
        }
    }
}

New Post: Validating Object Graphs

$
0
0
Update: I just tried this and got a StackOverflow exception like I expected. Is there a feature/setting that I'm missing that makes this work? Maybe by using the When method? It seems like a person would need to keep track of what has been validated and use the When method to not validate a 2nd time. However, I'm not sure how one would capture what has already been validated. It's almost as if a "When Validating" event needs to be available.

New Post: Validating Object Graphs

$
0
0
Hi

Yes, this will indeed cause a stackoverflow. Your best bet is either to remove one of the calls to SetValidator, and perform the validation manually when necessary or put one of the SetValidator calls inside a RuleSet and then explicitly choose when you want to execute it.

Jeremy

New Post: Count invalid items in a model

$
0
0
Hi

This message isn't coming from FluentValidation, but rather from MVC itself. Before ASP.NET MVC invokes validation, it will first check to see if the property can be set to the value. If it can't, then this error is generated, so this is happening before the value even gets to FluentValidation.

As far as I'm aware, this isn't something that can be overridden. Your best bet is to add some client-side logic to ensure that the value being entered isn't too long for the type of the property.

New Post: Validating Object Graphs

$
0
0
It appears the StackOverflow is happening in the constructor while wiring up the validators instead of in the validators themselves.

Is it possible to mark an entity as validated so it doesn't wire up the validator a second time? Then I could wrap all the validators in a When condition?

Just some context: I'm generating my POCOs from Entity Framework and I'm also generating the Validation classes. In my case I can't really remove one of the calls from SetValidator. In a perfect world the validation would walk the entire object graph but not validate the same instance more than once.

New Post: Reuse rule set validator

$
0
0
Did you figure out if this worked?

New Post: Passing an object while validating

$
0
0
Hi Jeremy,

Thanks for this wonderful library. I have been using it extensively for my project. I have a query which I have been not able to resolve.

I have a requirement, where I am editing an object "schedule". Validation of the new schedule is dependent on older schedule that why I need to pass the old value of schedule as past validation. Is there a way out?

Thanks again

Regards,
Amit

New Post: Validation Rule for overall model

$
0
0
I just ran into a need for this as well. I'm trying to perform validation that determines if a record has been entered twice. It needs to checks if three properties match the same three properties of another record.

New Post: Passing an object while validating

$
0
0
Hi Amit

FluentValidation isn't really designed to work this way - all the context should be driven by properties on the object you're validating, not by passing in anything extra. The best way to do this would be to create a class that holds both schedules as properties, and define your validator for this class instead rather than for the schedule directly.

Jeremy

New Post: Validating Object Graphs

$
0
0
Hmm yes, so this does happen in the validator's constructor, not actually at the time of validation, so marking the entity itself as already validated won't actually help. Essentially your validator definitions are doing this:
class Validator() {
  public Validator() {
    new OtherValidator();
  }
  
  public void Validate() { }
}


class OtherValidator() {
  public OtherValidator() {
    new Validator();
  }
}
I'll have a think about how this can be solved, but I would personally explicitly define the validators rather than generating them - this gives you a lot better control of what you're actually validating.

New Post: Validation of object hierarchy

$
0
0
I have this object hierarchy: Tab -> LayoutContainer -> PropertyField
where LayoutContainer and PropertyField is abstract classes.

I would like to create validator's for LayoutContainer and PropertyField.

public class BasePropertyFieldValidator<T> : AbstractValidator<T> where T: PropertyField

public class BaseLayoutContainerValidator<T> : BasePropertyFieldValidator<T> where T : LayoutContainer

But I can not get it to work only for object that has PropertyField as baseclass. What is the right way to do this.

New Post: Non-property oriented validation

$
0
0
I have a requirement to make a validation that is not connected with any particular property but depends for example... on the state of the whole application/object etc.
Is FluentValidation supplying any mechanisms for such cases?

I only achieved a workaround using the Custom() method from AbstractValidatior<T>. Sample that allways makes an ValidationFailure for the object (propertName = ""):
fluentValidator.Custom(x => new ValidationFailure("", "TEST OBJECT ERROR"));
Is there any other 'cleaner' possibility?
Viewing all 1917 articles
Browse latest View live


<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>