Implementing a Role Provider

ASP.NET role management enables you to easily use a number of different providers for your ASP.NET applications. You can use the supplied profile providers that are included with the .NET Framework, or you can implement your own provider.

There are two primary reasons for creating a custom role provider.

  • You need to store role information in a data source that is not supported by the role providers included with the .NET Framework, such as a FoxPro database, an Oracle database, or other data source.

  • You need to manage role information using a database schema that is different from the database schema used by the providers that ship with the .NET Framework. A common example of this would be authorization data that already exists in a SQL Server database for a company or Web site.

Required Classes

To implement a role provider, you create a class that inherits the RoleProvider abstract class from the System.Web.Security namespace. The RoleProvider abstract class inherits the ProviderBase abstract class from the System.Configuration.Provider namespace. As a result, you must implement the required members of the ProviderBase class as well. The following tables list the required properties and methods that you must implement from the ProviderBase and RoleProvider abstract classes and a description of each. To review an implementation of each member, see the code supplied for the Sample Role-Provider Implementation.

ProviderBase Members

Member

Description

Initialize method

Takes as input the name of the provider and a NameValueCollection of configuration settings. Used to set property values for the provider instance including implementation-specific values and options specified in the configuration file (Machine.config or Web.config).

RoleProvider Members

Member

Description

ApplicationName property

The name of the application using the role information specified in the configuration file (Web.config). The ApplicationName is stored in the data source with related user information and used when querying for user information. See the section on the ApplicationName later in this topic for more information.

This property is read-write and defaults to the ApplicationPath if not specified explicitly.

AddUsersToRoles method

Takes as input a list of user names and a list of role names, and associates the specified users with the specified roles at the data source for the configured ApplicationName.

You should throw a ProviderException if any of the role names or user names specified do not exist for the configured ApplicationName.

You should throw an ArgumentException if any of the specified user names or role names is an empty string and an ArgumentNullException if any of the specified user names or role names is null (Nothing in Visual Basic).

If your data source supports transactions, you should include each add operation in a transaction and roll back the transaction and throw an exception if any add operation fails.

CreateRole method

Takes as input the name of a role and adds the specified role to the data source for the configured ApplicationName.

You should throw a ProviderException if the specified role name already exists for the configured ApplicationName.

You should throw an ArgumentException if the specified role name is an empty string, contains a comma, or exceeds the maximum length allowed by the data source, and an ArgumentNullException if the specified role name is null (Nothing in Visual Basic).

DeleteRole method

Takes as input the name of a role and a Boolean value that indicates whether to throw an exception if there are still users associated with the role. The DeleteRole deletes the specified role from the data source for the configured ApplicationName.

If the throwOnPopulatedRole parameter is true, and the role identified by the role name parameter has one or more members, throw a ProviderException and do not delete the role. If the throwOnPopulatedRole parameter is false, then delete the role whether it is empty or not.

When you delete a role from the data source, ensure that you also delete any associations between a user name and the deleted role for the configured ApplicationName.

You should throw an ArgumentException if the specified role name does not exist, or is an empty string. You should throw an ArgumentNullException if the specified role name is null (Nothing in Visual Basic).

FindUsersInRole method

Takes a role name and a string value and returns a collection of user names in the role that contain the provided string value. Wildcard support is included based on the data source. Users are returned in alphabetical order by user name.

It is recommended that you throw a ProviderException if the role name specified does not exist in the data source.

GetAllRoles method

Returns a list of role names from the data source. Only the roles for the specified ApplicationName are retrieved.

If no roles exist for the configured ApplicationName, you should return a string array with no elements.

GetRolesForUser method

Takes as input a user name and returns the role names that the specified user is associated with, from the data source. Only the roles for the configured ApplicationName are retrieved.

If no roles exist for the specified user for the configured ApplicationName, you should return a string array with no elements.

You should throw an ArgumentException if the specified user name is an empty string. You should throw an ArgumentNullException if the specified user name is null (Nothing in Visual Basic).

GetUsersInRole method

Takes as input a role name and returns the user names associated with a role from the data source. Only the roles for the configured ApplicationName are retrieved.

If the specified role name does not exist for the configured ApplicationName, you should throw a ProviderException.

If no users are associated with the specified role for the configured ApplicationName, you should return a string array with no elements.

You should throw an ArgumentException if the specified role name is an empty string, contains a comma, or exceeds the maximum length for a role name allowed by your data source. You should throw an ArgumentNullException if the specified role name is null (Nothing in Visual Basic).

IsUserInRole method

Takes as input a user name and a role name and determines whether the specified user is associated with a role from the data source for the configured ApplicationName.

You should throw a ProviderException if the role name or user name specified does not exist for the configured ApplicationName.

You should throw an ArgumentException if the specified user name or role name is an empty string and an ArgumentNullException if the specified user name or role name is null (Nothing in Visual Basic).

RemoveUsersFromRoles method

Takes as input a list of user names and a list of role names and removes the association for the specified users from the specified roles at the data source for the configured ApplicationName.

You should throw a ProviderException if any of the role names or user names specified does not exist for the configured ApplicationName.

You should throw an ArgumentException if any of the specified user names or role names is an empty string and an ArgumentNullException if any of the specified user names or role names is null (Nothing in Visual Basic).

If your data source supports transactions, you should include each remove operation in a transaction and roll back the transaction and throw an exception if any remove operation fails.

RoleExists method

Takes as input a role name and determines whether the role name exists in the data source for the configured ApplicationName.

You should throw an ArgumentException if the specified role name is an empty string. It is recommended that you throw an ArgumentNullException if the specified role name is null (Nothing in Visual Basic).

ApplicationName

Role providers store role information uniquely for each application. This enables multiple ASP.NET applications to use the same data source without running into a conflict if duplicate user names are used. Alternatively, multiple ASP.NET applications can use the same role data source by specifying the same ApplicationName.

Because role providers store role information uniquely for each application, you will need to ensure that your data schema includes the application name and that queries and updates also include the application name. For example, the following command is used to retrieve a role name from a database and ensures that the ApplicationName is included in the query.

SELECT Rolename FROM Roles 
  WHERE Rolename = 'Administrators' AND ApplicationName = 'MyApplication'

Thread Safety

For each role provider specified in the configuration for an application, ASP.NET instantiates a single role-provider instance that is used for all of the requests served by an HttpApplication object. As a result, you can have multiple requests executing concurrently. ASP.NET does not ensure the thread safety of calls to your provider. You will need to write your provider code to be thread safe. For example, creating a connection to a database or opening a file for editing should be done within the member that is called, such as AddUsersToRoles , rather than opening a file or database connection when the Initialize method is called.

See Also

Concepts

Sample Role-Provider Implementation

Securing Roles

Other Resources

Managing Authorization Using Roles