Programming Microsoft ASP.NET 4 - Dino Esposito [425]
PasswordStrengthRegularExpression
Returns the regular expression that the password must comply with.
RequiresQuestionAndAnswer
Indicates whether the provider requires a question/answer challenge to enable password changes.
RequiresUniqueEmail
Indicates whether the provider is configured to require a unique e-mail address for each user name.
Extending the Provider’s Interface
The provider can also store additional information with each user. For example, you can derive a custom class from MembershipUser, add any extra members, and return an instance of that class via the standard GetUser method of the membership API.
To use the new class, you cast the object returned by GetUser to the proper type, as shown here:
var user = Membership.GetUser(name) as MyCompanyUser;
In addition to the members listed in Table 19-10 and Table 19-11, a custom membership provider can add new methods and properties. These are defined outside the official schema of the provider base class and are therefore available only to applications aware of this custom provider.
var provider = Membership.Provider as MyCompanyProvider;
Note
The Providers collection property allows you to use a dynamically selected provider:
var prov = Membership.Providers["ProviderName"];
This feature allows applications to support multiple providers simultaneously. For example, you can design your application to support a legacy database of users through a custom provider, while storing new users in a standard SQL Server table. In this case, you use different membership providers for different users.
A Custom Provider for Legacy Code
Unless you’re building an ASP.NET application entirely from scratch with total freedom to decide where and how to store settings and data, you have some legacy code or schema to deal with. A savvy strategy, then, is creating a custom membership provider to provide access to legacy data via a canonical programming interface. I would even say that almost any ASP.NET application needs its own membership provider. Here’s some sample code:
public class MyMembershipProvider : MembershipProvider
{
public MyMembershipProvider()
{
}
public override bool ChangePassword(string username,
string oldPassword, string newPassword)
{
// If you don't intend to support a given method
// just throw an exception
throw new NotSupportedException();
}
...
public override bool ValidateUser(string username, string password)
{
return AuthenticateUser(username, password);
}
private bool AuthenticateUser(string username, string pswd)
{
// Place here any code that would use the existing API/schema
// and authenticate against the provided credentials
}
}
You define a new class derived from MembershipProvider. In this class definition, you have to override all the members in Table 19-10 and Table 19-11. If you don’t intend to support a given method or property, for that method just throw a NotSupportedException exception. For the methods you do plan to support—which for the previous example included only ValidateUser—you write the supporting code. At this point, nothing prevents you from reusing code from your old application. There are two key benefits with this approach: you reuse most of your code (perhaps with a little bit of refactoring), and your application now fully embraces the membership model of ASP.NET.
Generally speaking, when writing providers, there are three key issues to look at: the lifetime of the provider, thread-safety, and atomicity. The provider is instantiated as soon as it proves necessary, but only once per ASP.NET application. This fact gives the provider the status of a stateful component, but it does so at the price of protecting that state from cross-thread access. A provider is not thread-safe, and it will be your responsibility to guarantee that any critical data is locked before use. Finally, some functions in a provider can be made of multiple steps.