CustomValidationAttribute.Method Property

CustomValidationAttribute.Method Property (System.ComponentModel.DataAnnotations) | Microsoft Learn

Remarks

The custom method specified by this property must be public and static, and it must return a Boolean value. It must also take at least one input parameter that specifies the object to validate. This parameter can be strongly typed. If a process passes a value of a different type, type conversion will be attempted.

The specified method should return true if a given object is valid. Otherwise it should return false.

The custom method can also take parameters that specify a ValidationContext input value and a ValidationResult output value. The ValidationContext parameter provides additional context information that the method can use to determine the context that it is used in. The ValidationResult output parameter enables the method to return an error message.

If the method returns null for the ValidationResult parameter or if it returns an empty value for the ErrorMessage property, the default FormatErrorMessage method will be called to compose the error message.

 

'Peter and the case of the ASP.NET developer' - The CustomValidationAttribute

.net 4 introduces the CustomValidationAttribute, a member of System.ComponentModel.DataAnnotations that supports validation of your business logic. Until now, validation rules were limited based on the available attributes (required, stringlength, regex, and range) plus those you created by subclassing System.ComponentModel.DataAnnotations.ValidationAttribute. CustomValidationAttribute lets you define new validation rules directly on your Entity class (or the class of your choice) without having to subclass from ValidationAttribute.

Unfortunately at this time, the documentation on this attribute is limited. This posting is an attempt to document it better.

The CustomValidationAttribute can validate an individual property or the complete object (the Entity instance). This is an example using the Category table from Northwind DB and LINQ to SQL.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ComponentModel.DataAnnotations;
using System.Text.RegularExpressions;

[MetadataType(typeof(CategoryMetadata))]
[CustomValidation(typeof(Category), "FinalCheck")]
public partial class Category
{
   public class CategoryMetadata
   {
      [CustomValidation(typeof(Category), "TestCategoryName")]
      public object CategoryName { get; set; }
   }

   // method defined by LINQ to SQL on every Entity class.
   partial void OnValidate(System.Data.Linq.ChangeAction action)
   {
      List<ValidationResult> vErrors = new List<ValidationResult>();

      // validate class-level attributes
      // When the last parameter is true, it also evaluates all ValidationAttributes on this entity's properties
      Validator.TryValidateObject(this, new ValidationContext(this, null, null), vErrors, true);

      // handle errors
      if (vErrors.Count > 0)
         throw new ValidationException(vErrors[0], null, this);

   }

   public static ValidationResult FinalCheck(Category pCategory, ValidationContext pValidationContext)
   {
      if (pCategory.Description.Length < 10)
         return new ValidationResult("Description must be at least 10 characters.", new List<string> { "Description" });
      return ValidationResult.Success;
   }

   public static ValidationResult TestCategoryName(string pNewName, ValidationContext pValidationContext)
   {
      if (Regex.IsMatch(pNewName, @"^\d")) // cannot start with a digit
         return new ValidationResult("Cannot start with a digit", new List<string> { "CategoryName" });
      return ValidationResult.Success;
   }
}

 

Understanding the CustomValidatorAttribute definition

  • It can be placed on the class or property definition. Both are shown above.
  • The class that contains your validation method must always be declared, even if the method is in the same class this attribute is assigned.
  • You may want to create a separate class for all validation rules of your entity, such as “class CategoryValidation”.
  • The method name property must be a case sensitive match your method name.

Understanding the method definition

  • The method itself must be static and public.
  • The first parameter is the value to evaluate.
    • When the method is associated with the class, it will be passed an instance of the Entity. It can be typed to match the class of the Entity, such as it is with “Category” above. It can also be typed to “object”.
    • When the method is associated with a property, it will be passed the value of the property. It can be typed to match the type of the property, such as it is with “string” above. It can also be typed to “object”.
  • The second parameter, ValidationContext, describes other details about the activity. It’s more important when validating a property since it supplies the instance of the Entity (ObjectInstance property) and the property name (MemberName property). It’s also possible that this parameter will be null, but that generally occurs when using .net 3.5 libraries. So test for that.
  • Always return an instance of System.ComponentModel.DataAnnotations.ValidationResult. When there is no error, just return the static property ValidationResult.Success, as shown above. Otherwise return a description and optionally the property name(s) with errors.

Invoking Validation

Your CustomValidation methods are not called automatically (despite what the documentation presently says in the “Remarks” section). ASP.NET Dynamic Data knows to evaluate the property-based ValidationAttributes when there is a DynamicValidator control on the page. But since your Entity class may be reused, do not assume that Dynamic Data has done the job. Create a method on your Entity class to validate both class and property-level CustomValidationAttributes. Use System.ComponentModel.DataAnnotations.Validator.TryValidateObject() to do the job, as is shown above. Always pass true as the last parameter to insure the properties are validated. (If you pass false or omit the parameter, it will only validate the RequiredAttributes on properties.)

The OnValidate() method above is part of LINQ to SQL. Each Entity class has a partial method called OnValidate(). You create the other partial method in your code and LINQ to SQL will call it automatically. If you are using Entity Framework or another system, you must create and invoke your own “OnValidate()” method.

Communicating Errors to the User Interface

Your error messages from the ValidationResult class somehow have to be shown in the user interface. A method like OnValidate() has no direct way to pass up the list of ValidationResults. Instead, it throws a System.ComponentModel.DataAnnotations.ValidationException. (Unfortunately, it does not pass the list of ValidationResults in that exception class. You may want to build another Exception class to deliver them.)

The user interface should catch the exception and route the messages to its error display. When using ASP.NET with Dynamic Data, make sure you have a ValidationSummary and DynamicValidator control on the page, and Dynamic Data will take care of the rest. The Page Templates are setup this way.


<asp:ValidationSummary ID="ValidationSummary1" runat="server" 
    HeaderText="List of validation errors" />
<asp:DynamicValidator runat="server" ID="DetailsViewValidator" 
    ControlToValidate="FormView1" Display="None" />
<asp:FormView runat="server" ID="FormView1" >

Suppose you are creating a new Category and enter a name starting with a digit. Your validation rules will report an error like this:

 

作者:Chuck Lu    GitHub    
posted @   ChuckLu  阅读(22)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
历史上的今天:
2022-03-09 jQuery if checkbox is checked
2021-03-09 Using AntiXss As The Default Encoder For ASP.NET
2021-03-09 What is the difference between AntiXss.HtmlEncode and HttpUtility.HtmlEncode?
2021-03-09 Should I use .done() and .fail() for new jQuery AJAX code instead of success and error
2019-03-09 Inversion of Control Containers and the Dependency Injection pattern
2019-03-09 82. Remove Duplicates from Sorted List II
2019-03-09 83. Remove Duplicates from Sorted List
点击右上角即可分享
微信分享提示