Simple validation of property values, redux.

Stefan Forsberg wrote an excellent post on validating page data with Data Annotations, his solution is by far a more elegant way of validating data on a property than my ugly hack. So I rewrote my PageType validation hack to fit into his model instead. I converted my very specific code into a more generic ValidationAttribute. Works like a charm, and makes sure that the PageReference actually points to a page of the type you want, or nothing at all.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ComponentModel.DataAnnotations;
using EPiServer.Core;
using PageTypeBuilder;

namespace Development {

    ///
    /// Specifies the allowed type of pages selected in the property.
    ///
    [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false)]
    public sealed class AllowedPageTypeAttribute : ValidationAttribute {

        ///
        /// The allowed types of pages.
        ///
        public Type[] AllowedPageTypes {
            get;
            set;
        }

        public AllowedPageTypeAttribute(Type[] allowedPageTypes)
            : base() {
            this.AllowedPageTypes = allowedPageTypes;
        }

        public override bool IsValid(object value) {
            var reference = value as PageReference;
            // Check if the property ReferenceContainer has a value
            if (PageReference.IsNullOrEmpty(reference))
                return true;

            var page = reference.GetPage();
            if (page == null)
                return false;

            var pageType = page.GetType();

            foreach (Type t in AllowedPageTypes) {
                if (pageType.IsAssignableFrom(t) || t.IsAssignableFrom(pageType) )
                    return true;
            }
            return false;
        }
    }
}

And it's simply implemented on the Page property thus:

///
/// Name: Office
/// Description: The office associated with this container.
///
[AllowedPageType(new[] { typeof(OfficePage) }, ErrorMessage = "/errors/OfficePagePageType")]
[PageTypeProperty(
EditCaption = "Office",
HelpText = "The office associated with this container.",
Searchable = false,
UniqueValuePerLanguage = true,
Type = typeof(PropertyPageReference),
SortOrder = 15,
Required=true)]
public virtual PageReference OfficePage {
        get {
                var value = this.GetPropertyValue(page => page.OfficePage);
                return value ?? PageReference.EmptyReference;
            }
        }
}

It's also very easy to do e-mail validation etc. on properties. Like this for example.

[RegularExpression(@"^\b[\w\.-]+@[\w\.-]+\.\w{2,4}\b$", ErrorMessage = "/errors/EmailFormat")]

It's so simple it almost hurts.

blog comments powered by Disqus