Validation Framework in .NET that can do edits between fields

醉酒当歌 提交于 2019-12-18 05:06:11

问题


From my experience many validation frameworks in .NET allow you to validate a single field at a time for doing things like ensuring a field is a postal code or email address for instance. I usually call these within-field edits.

In my project we often have to do between-field-edits though. For instance, if you have a class like this:

public class Range
{
    public int Min { get; set; }
    public int Max { get; set; }
}

you might want to ensure that Max is greater than Min. You might also want to do some validation against an external object. For instance given you have a class like this:

public class Person
{
    public string PostalCode { get; set; }
}

and for whatever reason you want to ensure that Postal Code exists in a database or a file provided to you. I have more complex examples like where a user provides a data dictionary and you want to validate your object against that data dictionary.

My question is: can we use any of the existing validation frameworks (TNValidate, NHibernate Validator) for .NET or do we need to use a rules engine or what?? How do you people in the real world deal with this situation? :-)


回答1:


There's only one validation framework that I know well and that is Enterprise Library Validation Application Block, or VAB for short. I will answer your questions from the context of the VAB.

First question: Can you do state (between-field) validation in VAB?

Yes you can. There are multiple ways to do this. You can choose for the self validation mechanism, as follows:

[HasSelfValidation]
public class Range
{
    public int Min { get; set; }
    public int Max { get; set; }

    [SelfValidation]
    public void ValidateRange(ValidationResults results)
    {
        if (this.Max < this.Min)
        {
            results.AddResult(
                new ValidationResult("Max less than min", this, "", "", null));
        }
    }
}

I must say I personally don't like this type of validations, especially when validating my domain entities, because I like to keep my validations separate from the validation logic (and keep my domain logic free from references to any validation framework). However, they need considerably less code than the alternative, which is writing a custom validator class. Here's an example:

[ConfigurationElementType(typeof(CustomValidatorData))]
public sealed class RangeValidator : Validator
{
    public RangeValidator(NameValueCollection attributes)
        : base(string.Empty, string.Empty) { }

    protected override string DefaultMessageTemplate
    {
        get { throw new NotImplementedException(); }
    }

    protected override void DoValidate(object objectToValidate,
        object currentTarget, string key, ValidationResults results)
    {
        Range range = (Range)currentTarget;

        if (range.Max < range.Min)
        {
            this.LogValidationResult(results,
                "Max less than min", currentTarget, key);
        }
    }
}

After writing this class you can hook this class up in your validation configuration file like this:

<validation>
  <type name="Range" defaultRuleset="Default" assemblyName="[Range Assembly]">
    <ruleset name="Default">
      <validator type="[Namespace].RangeValidator, [Validator Assembly]"
        name="Range Validator" />
    </ruleset>
  </type>
</validation> 

Second question: How to do complex validations with possible interaction a database (with VAB).

The examples I give for the first question are also usable for this. You can use the same techniques: self validation and custom validator. Your scenario where you want to check a value in a database is actually a simple one, because the validity of your object is not based on its context. You can simply check the state of the object against the database. It gets more complicated when the context in which an object lives gets important (but it is possible with VAB). Imagine for instance that you want to write a validation that ensures that every customer, at a given moment in time, has no more than two unshipped orders. This not only means that you have to check the database, but perhaps new orders that are added or orders are deleted within that same context. This problem is not VAB specific, you will have the same problems with every framework you choose. I've written an article that describes the complexities we're facing with in these situations (read and shiver).

Third question: How do you people in the real world deal with this situation?

I do these types of validation with the VAB in production code. It works great, but VAB is not very easy to learn. Still, I love what we can do with VAB, and it will only get better when v5.0 comes out. When you want to learn it, start with reading the ValidationHOL.pdf document that you can found in the Hands-On Labs download.

I hope this helps.




回答2:


I build custom validation controls when I need anything that's not included out of the box. The nice thing here is that these custom validators are re-usable and they can act on multiple fields. Here's an example I posted to CodeProject of an AtLeastOneOf validator that lets you require that at least one field in a group has a value:

http://www.codeproject.com/KB/validation/AtLeastOneOfValidator.aspx

The code included in the download should work as an easy to follow sample of how you could go about it. The downside here is that Validation controls included with ASP.Net don't often work well with asp.net-ajax.



来源:https://stackoverflow.com/questions/2258513/validation-framework-in-net-that-can-do-edits-between-fields

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!