The solution architecture is simplewrap the ASP.NET 2.0 providers with a Web service and expose the credentials management operations for remote clients. You can even add the missing functionality. Then, use a Windows Forms application to consume that Web service while providing a rich user interface and a comprehensive credentials management experience. The Web service configuration file will contain the directives pertaining to the credentials store. This does mean, however, that all applications managed by the Web service will share those directives.
|Wrap the ASP.NET 2.0 providers with a Web service and expose the credentials management operations for remote clients.|
While you can build the Web service bottom-up, that is, start with the static methods of Roles and Membership, wrap them and define the Web service that way, I prefer a contract-driven approach: start by designing what would be the best interfaces to perform the various operation, and only then worry about how to implement them. Doing it this way will ensure that the interfaces exposed by the Web service support all the required administration functionality, and will also decouple the client application from any implementation details (such as wrapping the providers).
|Editor's Note: For information about contract-first, see the July/Aug 2005 issue of CoDe Magazine.)
One of the nicer features of ASP.NET 2.0 is its support for Web service interfaces: you can define and have the Web service expose logical interfaces, just like classes do. To do so, you need to decorate your interfaces with the WebServiceBinding
attribute and expose the individual interface methods via the WebMethod
attribute. Then, you would have a class derive from the interface and implement it, and the compiler will insist you support all methods of the interface.
To manage and interact with the credentials store and the Web service configuration file I defined five interfaces. These are: IApplicationManager, IMembershipManager, IPasswordManager, IRoleManager, and IUserManager.
The IApplicationManager interface, shown in Listing 2
, allows the administrator to delete a specified application, that is, remove all references to it from the database and delete all its users and its roles. IApplicationManager allows deleting all applications from the store, and it can return a list of all the applications in the store. Note that the interface is defined as an internal interfacepublic or internal visibility modifiers have no meaning for Web service interfaces. Each method on the interface is decorated with the WebMethod
attribute with a short description of the method. In addition, all methods (in all interfaces in this architecture) that access the credentials store are configured to use transactions. This is so that two operations such as deleting an application and creating a user will execute in complete isolation from each other, and to ensure the atomicity of complex operations such as deleting all users. Web services in .NET 2.0 can only start a new transaction, and that is controlled via the TransactionOption
property of the WebMethod
attribute. In all subsequent code listings, both the description and the transaction support are omitted to save space, but they are in the accompanying source code. Last but not least is the use of the WebServiceBinding
attribute on the interface. This designates the interface as a Web service interface that clients and services can bind against, that is, implement or consume it. In order to expose the interface to the outside world as a WSDL contract, you need to use a shim class. The shim class is required because you cannot expose an interface as a Web service, nor can you apply the WebService
attribute on it. The shim class will also provide the namespace definition for the interface via the WebService
attribute. The code below shows the IApplicationManagerShim abstract class definition.
Description="IApplicationManager is used to manage
applications. This web service is only
the definition of the interface. You
cannot invoke method calls on it.")]
abstract class IApplicationManagerShim :
public abstract void DeleteApplication(
public abstract string GetApplications();
public abstract void DeleteAllApplications();
Because IApplicationManagerShim is a class, you can expose it as a Web service. Because it is an abstract class and all the methods are defined as abstract methods, there is no need to implement any of the methods (nor can you). To make it look just like the interface, IApplicationManagerShim sets the Name
property of the WebService
attribute to IApplicationManager (instead of the default class name). You can now expose the interface using the IApplicationManager.asmx
<%@ WebService Language="C#"
Now, if you browse to the IApplicationManager.asmx
page you will see the interface definition. You can use the /serverInterface
option of WSDL.exe
to import the interface definition to the client or to any other service that wants to bind to the interface definition.
The IMembershipManager interface (see Listing 3
) allows you to manage all aspects of user accounts: creating and deleting user accounts, updating user accounts, retrieving user account details, and retrieving all the users in an application.
The IRoleManager interface shown below allows you to manage all aspects of logical roles: creating and deleting roles, adding and removing users to and from roles, and retrieving all the roles in an application.
void CreateRole(string application,string role);
bool DeleteRole(string application,string role,
void AddUserToRole(string application,
string userName, string role);
void DeleteAllRoles(string application,
string GetAllRoles(string application);
string GetRolesForUser(string application,
string GetUsersInRole(string application,
void RemoveUserFromRole(string application,
string userName, string roleName);
This IPasswordManager interface provides mostly read-only information pertaining to the application password policy.
bool EnablePasswordReset(string application);
bool EnablePasswordRetrieval(string application);
string GeneratePassword(string application,
bool RequiresQuestionAndAnswer(string application);
string ResetPassword(string application,
string GetPassword(string application,
void ChangePassword(string application,
That policy is stored typically in the application's configuration file. The policy includes whether password reset and retrieval is enabled, password strength, and password answer policy. You can also use IPasswordManager to generate a new password that complies with the password strength policy. In addition, IPasswordManager is used to reset, change or retrieve a specified user's password.
The IUserManager interface allows validating user credentials, retrieving role membership, and getting all the roles a user is a member of. It is available for test and analysis purposes.
public interface IUserManager
bool Authenticate(string applicationName,
string userName, string password);
bool IsInRole(string applicationName,
string userName, string role);
string GetRoles(string applicationName,