Application services can be customized with authentication or provider logic through the event-driven application model of ASP.NET 3.5. The Authenticating and CreatingCookie events are both fired by the System.Web.ApplicationServices.AuthenticationService class. These events can be handled through the global.asax ASP.NET file, which creates the server-side application object. By handling the Authenticating event as shown in Example 6-16, you can provide custom authentication logic by using either a username/password combination or a custom authentication string that can be passed from the client and represent any string-serialized data from the user’s input. In addition to custom authentication logic, you can also choose a new provider based on the login name.
Example 6-16. The Authenticating event can be handled to provide custom authentication (Web/Global.asax).
void Application_Start(object sender, EventArgs e) { // Code that runs on application startup System.Web.ApplicationServices.AuthenticationService.Authenticating += new EventHandler<System.Web.ApplicationServices.AuthenticatingEventArgs> (AuthenticationService_Authenticating); } void AuthenticationService_Authenticating(object sender, System.Web. ApplicationServices.AuthenticatingEventArgs e) { string username = String.Empty; string password = String.Empty; // You could pass in custom credentials string[] credentials; if(e.CustomCredential != null) credentials = e.CustomCredential.Split(new char[] { ',' }); try { e.Authenticated = Membership.ValidateUser(e.UserName, e.Password); } catch { e.Authenticated = false; } e.AuthenticationIsComplete = true; }
The profile service also fires events that you can handle to provide custom validation. To perform data validation on the server before data is saved, handle the ValidatingProperties event. Example 6-17 demonstrates custom profile validation using this event.
Example 6-17. The ValidatingProperties event can be handled to provide custom server-side validation (Web/ Global.asax).
void Application_Start(object sender, EventArgs e) { // Code that runs on application startup System.Web.ApplicationServices.AuthenticationService.Authenticating += new EventHandler<System.Web.ApplicationServices.AuthenticatingEventArgs> (AuthenticationService_Authenticating); System.Web.ApplicationServices.ProfileService.ValidatingProperties += new EventHandler< System.Web.ApplicationServices.ValidatingPropertiesEventArgs>( ProfileService_ValidatingProperties); } void ProfileService_ValidatingProperties(object sender, System.Web.ApplicationServices.ValidatingPropertiesEventArgs e) { if (String.IsNullOrEmpty((string)e.Properties["startTopic"]) || ((string)e.Properties["startTopic"]).Contains(@"") ) { e.FailedProperties.Add("startTopic"); } }
Just as the authentication and profile services expose events to customize the service implementation, the role service can be configured using the SelectingProvider event. Example 6-18 demonstrates a customization that uses EmployeesRoleProvider for all Fabrikam employees and the default AspNetProvider for all other cases.
Example 6-18. The SelectingProvider event of the role service can be used to return alternative role providers (Web/Global.asax).
void Application_Start(object sender, EventArgs e) { // Code that runs on application startup System.Web.ApplicationServices.AuthenticationService.Authenticating += new EventHandler<System.Web.ApplicationServices.AuthenticatingEventArgs> (AuthenticationService_Authenticating); System.Web.ApplicationServices.ProfileService.ValidatingProperties += new EventHandler< System.Web.ApplicationServices.ValidatingPropertiesEventArgs>( ProfileService_ValidatingProperties); System.Web.ApplicationServices.RoleService.SelectingProvider += newEventHandler< System.Web.ApplicationServices.SelectingProviderEventArgs>( RoleService_SelectingProvider); } void RoleService_SelectingProvider(object sender, System.Web.ApplicationServices.SelectingProviderEventArgs e) { if (e.User.Identity.Name.IndexOf("@fabrikam.com") > 0) { e.ProviderName = "EmployeeRoleProvider"; } else { e.ProviderName = "AspNetProvider"; } }