As a follow-up to my post on DataAnnotations in ASP.NET Web Forms, I’d like to demonstrate yet another custom attribute. Although ASP.NET offers a CreateUserWizard, if your custom membership provider is way more complicated, you will probably be better off creating a control from scratch. If you go this route, you’ll have to provide some of the functionality from the CreateUserWizard. Here is a simple attribute which checks *only* password complexity and builds an ErrorMessage without ever calling the CreateUser method.
This attribute can be added to a password property and validate against the *Default* Membership Provider.
Here is the code:
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false)]
public class MembershipPasswordRequiredAttribute : ValidationAttribute
{
public override bool IsValid(object value)
{
if (value == null || !(value is string) || string.IsNullOrEmpty(value.ToString()))
{
return false;
}
MembershipSection membershipConfig = (MembershipSection)WebConfigurationManager
.GetSection("system.web/membership");
var providerSettings = membershipConfig.Providers[membershipConfig.DefaultProvider];
string minLength = providerSettings.Parameters["minRequiredPasswordLength"];
string minAlpha = providerSettings.Parameters["minRequiredNonalphanumericCharacters"];
if (string.IsNullOrEmpty(this.ErrorMessage) && !string.IsNullOrEmpty(minLength))
{
string message = String.Empty;
message = String.Format("Password must be at least {0} characters in length", minLength);
if (!string.IsNullOrEmpty(minAlpha))
{
message = String.Format("{0} and contain at least {1} special character", message, minAlpha);
}
this.ErrorMessage = message;
}
/* Validate against your provider and return true or false */
}
}
Usage:
[MembershipPasswordRequired]
internal string Password {get;set;}
The cool thing about this attribute is that you can decorate a property without specifying the ErrorMessage and it will build one dynamically from your default membership. Of course, you can change this up if you’re using multiple providers by getting the key of the current provider. But, the project I’m working on will always only have one provider, so this is how I’ll leave it.
A caveat: You can only set the ErrorMessage property once. If you try to assign to it more than once, you will receive an exception telling you this.
I won’t post the code for validating against the provider, because there are a number of ways to do this. Probably the safest way to do so is to use regex validation and pull that property from the provider’s parameters and just return whether the regex matches the string or not.
Anyway, I thought this was a pretty cool usage of DataAnnotations, and hooking it up on a custom CreateUser control was trivial with the DataAnnotation validator (from a few posts ago).