by Jeff Handley via Jeff Handley on 9/26/2010 6:12:46 AM
In our last installment, we learned about the standard validators that ship in the System.ComponentModel.DataAnnotations assembly. RequiredAttribute, RangeAttribute, StringLengthAttribute, and RegularExpressionAttribute all derive from ValidationAttribute and cover many common validation scenarios. Every system has its own business rules though, and therefore it’s imperative that RIA Services allows you to create custom validators to implement your own logic. Moreover, your custom error messages must plug into the same framework that powers the standard validators. To address this requirement, we added CustomValidationAttribute.
System.ComponentModel.DataAnnotations.CustomValidationAttribute allows you to easily redirect a validator to a method you’ve defined in your code using a ValidatorType and Method name. Like the standard validation attributes, it also allows you to specify an ErrorMessage or an ErrorMessageResourceType/ErrorMessageResourceName pair, but let’s focus on the ValidatorType and Method properties. It’s actually quite straight-forward: you create a method that can perform validation for a value and you point a [CustomValidation] attribute to that method. This can be done either at the property-level or at the entity-level. Here’s a sample custom validation method that we will be applying to our Meeting entity:
using System;using System.ComponentModel.DataAnnotations;using RudeValidation.Web.Models; namespace RudeValidation.Web.Validators{ /// <summary> /// Custom validators that apply to meetings. /// </summary> public static class MeetingValidators { /// <summary> /// Ensure that meetings aren't scheduled to start too early. /// </summary> /// <param name="meetingStartTime"> /// The time the meeting it set to start. /// </param> /// <param name="validationContext"> /// The context for the validation being performed. /// </param> /// <returns> /// A <see cref="ValidationResult"/> with an error or <see cref="ValidationResult.Success"/>. /// </returns> public static ValidationResult NoEarlyMeetings( DateTime meetingStartTime, ValidationContext validationContext) { if (meetingStartTime.TimeOfDay.Hours < 9) { return new ValidationResult( "While you may be an early bird, it's not fair to schedule a meeting before 9:00 AM." , new[] { validationContext.MemberName }); } return ValidationResult.Success; } }}
Here’s how we then apply this validation method to our entity, in this case to the meeting’s start time property, with the added line highlighted.
using System;using System.ComponentModel.DataAnnotations;using RudeValidation.Web.Resources;using RudeValidation.Web.Validators; namespace RudeValidation.Web.Models{ public partial class Meeting { [Key] public int MeetingId { get; set; } [Required] [CustomValidation(typeof(MeetingValidators), "NoEarlyMeetings")] public DateTime Start { get; set; } [Required] public DateTime End { get; set; } [Required] [StringLength(80, MinimumLength = 5, ErrorMessageResourceType = typeof(ValidationErrorResources), ErrorMessageResourceName = "TitleStringLengthErrorMessage")] // {0} must be at least {2} characters and no more than {1}. public string Title { get; set; } public string Details { get; set; } [Required] [RegularExpression(@"\d{1,3}/\d{4}", ErrorMessage = "{0} must be in the format of 'Building/Room'")] public string Location { get; set; } [Range(2, 100)] [Display(Name = "Minimum Attendees")] public int MinimumAttendees { get; set; } [Range(2, 100)] [Display(Name = "Maximum Attendees")] public int MaximumAttendees { get; set; } }}
The MeetingValidators class was created in a file named MeetingValidators.shared.cs. By using the .shared.cs (or .shared.vb) convention on the file name, RIA Services will automatically copy this class to your Silverlight project, making this validation method available on the client as well as on the server. Because this file will get automatically copied (and compiled into) your Silverlight project behind-the-scenes, it’s important to remove any using statements that aren’t needed, as they may refer to namespaces that don’t exist in Silverlight, like System.Web.
Now, let’s take a look at the result we get in the UI:
There, now no one can schedule meetings before 9:00am!
Let’s recap what was involved in getting this custom validator implemented, end to end:
That’s it! I don’t know if it could be much simpler. This custom validation logic will now be executed on both the client and the server.
I will continue digging deeper into RIA Services Validation. In future posts, we’ll be exploring how RIA Services actually propagates your validators to the client, how you can create custom, reusable validators by deriving from ValidationAttribute directly, as well as when/how RIA Services will invoke each kind of validator, and much more!
Original Post: RIA Services Validation: Custom Validation Methods
The content of the postings is owned by the respective author. Silverlight Feeds is not responsible for the contents of the postings. This site is automatically generated and cannot be reviewed for abusive content. If you find abusive content on Silverlight Feeds, please contact us. Designated trademarks and brands are the property of their respective owners. All rights reserved.