Chapter 6. AJAX Application Services with Sys.Services

After completing this chapter, you will

  • Understand authentication, roles, and security in an ASP.NET AJAX application.

  • Understand ASP.NET AJAX application services.

  • Be able to integrate ASP.NET AJAX application services in a JavaScript application.

  • Be able to extend and enhance application services with custom service implementations.

In Chapter 1, Chapter 2, and Chapter 3, I described how to use a service-oriented style of programming to develop service-based applications against services exposed through an AJAX-enabled Web binding. In Chapter 4 and Chapter 5, I covered the client runtime that utilizes the Microsoft AJAX Library, a robust application platform for client-side programming with JavaScript. In this chapter, I’ll build on those foundations by describing how to add application services to the client application. These services supplement your application’s API to provide AJAX functionality for authentication, authorization, and preferences.

More Information

More Information

Application services are integrated on top of the ASP.NET provider model. For more information about ASP.NET providers, I recommend Dino Esposito’s book Programming Microsoft ASP.NET 3.5 (Microsoft Press, 2008).

Figure 6.1 illustrates the role of application services in Microsoft’s AJAX application architecture. Application services are implemented in ASP.NET and exposed through Web services and integrated JavaScript proxies built into the AJAX library’s MicrosoftAjax.js file. Application services are also integrated into the client runtime through the ScriptManager control, which recognizes the server-side authentication status on the initial page load, although the client-side authentication status can be updated throughout the lifetime of the page.

The role of application services in the AJAX application architecture.

Figure 6.1. The role of application services in the AJAX application architecture.

ASP.NET AJAX Application Services with Sys.Services

ASP.NET AJAX includes the JavaScript namespace Sys.Services to provide application service functionality to the local Web application. The application services defined in Sys.Services are more than pure service proxies; they also contain logic used to incorporate initial state during server page loading and wrapper methods that add functionality to the application service proxies. While most proxy scripts are used only as proxies for Web services, application service proxies actually maintain application state. Rather than returning an object that encapsulates the application state returned from the Web services, the proxies themselves are the JavaScript objects that maintain their application state through the page’s lifetime. This means that when you load values from authentication, roles, or profile services, the data is accessible at any time through methods of the proxy. You do not have to load it from the server or write your own wrapper object.

In the code samples in this chapter, I’ll use the Forms Authentication provider for authentication, roles, and profiles. For a refresher on configuring forms-based authentication using ASP.NET, see the following sidebar "Enabling Forms-Based Authentication for ASP.NET." The chapter’s code samples work equally well with Windows-authenticated applications or custom providers. You must still use aspnet_regsql.exe to configure the ASP.NET database for profiles, which is described in detail in the MSDN topic "Creating the Application Services Database for SQL Server" at http://msdn.microsoft.com/library/x28wfk74.aspx.

ASP.NET AJAX Script Initialization and Sys.Services

The ScriptManager server control is used to instantiate initial values for the core Sys.Services objects. It also provides initial state for authentication, role, and profile data during page loading through a technique I call ASP.NET AJAX script initialization. ASP.NET script initialization is used to set initial values from the server in a client-side framework. These values establish the initial state of known objects and cut down on the time required to initialize the page in the client. For application state such as authentication or profile data, this technique does away with the need for an initial Web service call to determine state that is already known when the script runtime is loaded.

In ASP.NET AJAX, the ScriptManager uses script initialization to tie authentication, role, and profile status to JavaScript Sys.Services objects without requiring an initial service call. During the lifetime of the page, the values can change and can be loaded from Web services as needed.

To utilize script initialization in your own code, use the ClientScriptManager class, which is exposed to ASP.NET server controls and pages as the property Page.ClientScript. The ClientScriptManager method RegisterClientScriptBlock is used to register startup scripts that run when the page is loaded. The following C# code demonstrates a simple script initialization technique you can use within the server code of the ASP.NET Page or Control classes in your application.

// Override the OnPreRender method of System.Web.UI.Control to initialize script values
protected override void OnPreRender(EventArgs e)
{
    base.OnPreRender(e);
    StringBuilder script = null;
    if (this.Page.User.Identity.IsAuthenticated) {
        // Perform any script initialization here
        script = new StringBuilder();
        script.Append(" Sys.Debug.trace('Authenticated script initialization'), ");
    }

    if (script != null && script.Length > 0)
    {
        this.Page.ClientScript.RegisterClientScriptBlock(
            this.GetType(), "Sys.Initialization", script.ToString(), true);
    }
}

With this technique, you can write initial script values that are set in JavaScript before the Sys.Application init or load client-side events are raised. When scripts initialized through the RegisterClientScriptBlock method are run on the client, all ScriptManager registered scripts will have been loaded by the JavaScript application.

The ScriptManager class uses a private method named ConfigureApplicationServices to perform ASP.NET AJAX script initialization for application services configured through the ScriptManager. This method is called during execution of the server-side PreRenderComplete event handler and initializes the state for the profile service, authentication service, and role service by writing JavaScript during the ASP.NET page execution. Example 6-1 demonstrates the ScriptManager’s implementation of script initialization. By looking at the method implementation, you can see that scripts for profiles, authentication, and roles are all rendered to the page by way of the ClientScript instance of the Page. (The type IPage in the ScriptManager source code is just an internal wrapper for the Page class.) The service manager classes AuthenticationServiceManager, ProfileServiceManager, and RoleServiceManager all handle their own script initialization by appending to a StringBuilder instance that contains initial script values. The script initialization of these objects is configured through properties of the ScriptManager, which I’ll discuss throughout the rest of the chapter.

Tip

Tip

Code for this book is available online at http://www.microsoft.com/mspress/companion/9780735625914. The code for this chapter is in the file Chapter 6.zip. For authentication purposes, a demo user that ships with the example database has been configured with the username "user" and the password "password".

Example 6-1. The ScriptManager injects script for initial authentication, profile, and role states in its private method ConfigureApplicationServices (from System.Web.Extensions.dll).

// private method implementation from System.Web.UI.ScriptManager
private void ConfigureApplicationServices()
{
    StringBuilder sb = null;
    ProfileServiceManager.ConfigureProfileService(ref sb, this.Context, this,
        this._proxies);
    AuthenticationServiceManager.ConfigureAuthenticationService(ref sb,
        this.Context, this, this._proxies);

    RoleServiceManager.ConfigureRoleService(ref sb, this.Context, this,
        this._proxies);

    if ((sb != null) && (sb.Length > 0))
    {
        this.IPage.ClientScript.RegisterClientScriptBlock(typeof(ScriptManager),
            "AppServicesConfig", sb.ToString(), true);
    }
}

The internal methods ProfileServiceManager.ConfigureProfileService, AuthenticationServiceManager.ConfigureAuthenticationService, and RoleServiceManager.ConfigureRoleService are all used by ASP.NET AJAX to instantiate initial values for Sys.Services objects. The scripts generated by these methods are registered in a client script block with the page’s ClientScript object. If the user is logged in, the ASP.NET AJAX runtime writes initialization script into the page, setting the AuthenticationService logged-in status to true. As the page loads, the ScriptManager renders the following script inline in the ASPX page. The method Sys.Services. AuthenticationService._setAuthenticated sets the application service proxy’s initial state to authenticated.

<script type="text/javascript">
    if (typeof(Sys) === 'undefined')
        throw new Error('ASP.NET Ajax client-side framework failed to load.'),
    Sys.Services._ProfileService.DefaultWebServicePath = 'Profile_JSON_AppService.axd';
    Sys.Services._AuthenticationService.DefaultWebServicePath =
        'Authentication_JSON_AppService.axd';
    Sys.Services.AuthenticationService._setAuthenticated(true);
    Sys.Services._RoleService.DefaultWebServicePath = 'Role_JSON_AppService.axd';
</script>

The authentication, profile, and role services for the JavaScript Sys.Services namespace are exposed through built-in HTTP handlers generated by the AJAX framework. To enable the built-in authentication, role, and profile application services used by Sys.Services, you must configure the web.extensions/scripting/webServices element in web.config. Here is an example configuration:

<system.web.extensions>
    <scripting>
      <webServices>
        <authenticationService enabled="true" />
        <profileService enabled="true"/>
        <roleService enabled="true"/>
      </webServices>
    </scripting>
  </system.web.extensions>

With this configuration, the HTTP handlers are exposed through the following application-relative endpoints:

  • ~/Authentication_JSON_AppService.axd

  • ~/Role_JSON_AppService.axd

  • ~/Profile_JSON_AppService.axd

Keep in mind that these services are the internal implementations of application services defined in the System.Web.Extensions assembly. They are not meant to be called from remote services. Remote application services use the Windows Communication Foundation (WCF) classes defined in System.Web.ApplicationServices, which are not all fully compatible with the Microsoft AJAX Script Library version 3.5. In most cases, you do not need to use custom services for the main application services implementations, but you can create your own endpoints that adhere to the interface and are JSON-compatible, and you can set the paths to your services through properties of the ScriptManager.

The built-in ASP.NET AJAX application services respond only to the content-type "application/json" with the POST verb, so you cannot load these services over a GET call using a Web browser. The corresponding services in System.Web.Extensions are internal, sealed classes and aren’t configurable or extendable by the user. As an alternative, you might want to use the services defined in System.Web.ApplicationServices. These services are designed with a more service-oriented nature in mind. I’ll discuss these services at the end of this chapter. However, with the default application services that integrate with Sys.Services, no server programming is involved because the ASP.NET AJAX framework takes care of the implementation for you. In most cases, this might be all that you need to implement application services for AJAX, and you can use alternative authentication methods for remote clients.

Tip

Tip

In NewsGator’s commercial applications, we deploy AJAX services in the ASP.NET Web application and configure the same services with alternative authentication schemes for external access. The strategy of deploying a service endpoint in multiple locations with alternative authentication schemes helps you develop services for the service-oriented architecture (SOA) platform and lets you reuse the same services for local AJAX applications.

JavaScript Authentication with Sys.Services

Sys.Services.AuthenticationService provides a JavaScript interface to ASP.NET authentication functionality. You can use the authentication service for an application that allows anonymous access but has enhanced functionality for logged-in users. In our sample application, I’ll implement read-only wiki content for anonymous users, but logged-in users will have collaboration tools and can edit content. The AuthenticationService class extends the JavaScript proxy with basic authentication functionality for the JavaScript application and is integrated with the ScriptManager through script initialization during page loading.

The default authentication service works with ASP.NET forms-based authentication and is not an endpoint that is accessible over non-AJAX Web services. It is tightly coupled to the AJAX runtime and is not compatible with newer WCF System.Web.ApplicationServices endpoints discussed later in the chapter. However, you can provide your own endpoint that conforms to the interface, with a Login and a Logout method that are available over a JSON-enabled Web service accepting a POST command to Login and Logout.

Tip

Tip

You can provide a custom authentication service as long as it accepts the same JSON-formatted message as the Sys.Services.AuthenticationService proxy. To create your own authentication service, configure it to accept a JSON-formatted message and use the following JSON data structure. It should also set the authentication cookie on success.

{ userName: username, password: password, createPersistentCookie: isPersistent }

To set the custom endpoint that the Sys.Services.AuthenticationService should invoke, set the path in the ScriptManager or ScriptManagerProxy tag as follows:

<asp:ScriptManagerProxy runat="server"
    AuthenticationService-Path="services/Login.svc" />

The following code sample demonstrates a function for showing a login control for an anonymous user and a logout control for the logged-in user. This code could be called from the JavaScript page load event or during the client-side page’s life cycle in response to the user logging in or out.

function showHideLogin(){
    var isLoggedIn = Sys.Services.AuthenticationService.get_isLoggedIn();
    var logincontrol = $get('loginControl'),
    var logoutcontrol = $get('logoutControl'),

    if (!isLoggedIn){
        // show the login UI
        logoutcontrol.style.display='none';
        logincontrol.style.display='';
    } else { // show the logout UI.
        logoutcontrol.style.display='';
        logincontrol.style.display='none';
    }
}

To log in, you can use the authentication service just like any other AJAX-enabled Web service. The following function can be assigned to a login button’s onclick event:

function OnClickLogin(domEvent) {
    var username = $get('usernameInput').value;
    var password = $get('passwordInput').value;
    Sys.Services.AuthenticationService.login(username,
        password, false,null,null,OnLoginCompleted,OnFailed,null);
}

A complete code sample that uses the authentication service to implement AJAX authentication functionality is shown in Example 6-2 and Example 6-3.

Example 6-2. Login controls can be implemented by HTML on the page. The controls call JavaScript methods for implementation (Web/AuthenticationDemo.aspx).

<%@ Page Language="C#" MasterPageFile="basic.master" %>

<asp:Content runat="server" ContentPlaceHolderID="MainMasterBody">
    <asp:ScriptManagerProxy runat="server">
        <Scripts>
            <asp:ScriptReference Path="AuthenticationDemo.js" />
        </Scripts>
    </asp:ScriptManagerProxy>

    <div style="display: none;" id="loginControl" class="loginControl">
        <div class="widgetTitle">Login</div>
        <div class="lightPadding">
            Username <br />
            <input type="text" id="usernameInput" /><br /><br />

            Password <br />
            <input type="text" id="passwordInput" /><br /><br />

            <button id="ButtonLogin" value="Login" type="button"
             title="Login">Login</button>
            <div id="loginFeedbackDiv">
            </div>
        </div>
    </div>

    <div id="logoutcontrol" class="loginControl" style="display: none;" >
        <button id="buttonlogout" type="button" value="Logout"
            title="Logout">Logout</button>
    </div>

</asp:Content>

Example 6-3. To implement login functionality with Sys.Services.AuthenticationService, use the login and logout instance methods and implement custom callback handlers (Web/AuthenticationDemo.js).

/// <reference name="MicrosoftAjax.js"/>
// Provides the example client runtime for the authentication demo page

function pageLoad(){
    Sys.UI.DomEvent.addHandler($get('ButtonLogin'), 'click', OnClickLogin);
    Sys.UI.DomEvent.addHandler($get('ButtonLogout'), 'click', OnClickLogout);
    showHideLogin();
}

function showHideLogin(){
    var isLoggedIn = Sys.Services.AuthenticationService.get_isLoggedIn();
    var logincontrol = $get('loginControl'),
    var logoutcontrol = $get('logoutControl'),

    if (!isLoggedIn){   // show the login UI
         logoutcontrol.style.display='none';
         logincontrol.style.display='';
     } else {            // show the logout UI.
        logoutcontrol.style.display='';
        logincontrol.style.display='none';
    }
}

function OnClickLogin(domEvent) {
    if (domEvent == null){domEvent = new Sys.UI.DomEvent(null);
        throw Error.argumentNull;}

    var username = $get('usernameInput').value;
    var password = $get('passwordInput').value;
    Sys.Services.AuthenticationService.login(username,
        password, false, null, null, OnLoginCompleted, OnFailed, null);
}

function OnClickLogout(domEvent){
   Sys.Services.AuthenticationService.logout(
      null, OnLogoutCompleted, OnFailed, null);
}

// This is the callback function called if the authentication fails.
function OnFailed(error, userContext, methodName) {
    var err = error.get_message();
    var timedOut = error.get_timedOut();
    var statusCode = error.get_statusCode();
    alert(err);
}

// The callback function called if the authentication completed successfully.
function OnLoginCompleted(isLoggedIn, userContext, methodName) {
    showHideLogin();
    $get('passwordInput').value = '';
    if (!isLoggedIn)
        $get('loginFeedbackDiv').innerHTML = 'Unable to log in.';
    else
        $get('loginFeedbackDiv').innerHTML = '';
}

// This is the callback function called if the user logged out successfully.
function OnLogoutCompleted(result) {
    showHideLogin();
}

Sys.Application.notifyScriptLoaded();

Upon logout, the authentication service always redirects the user after processing the custom OnLogoutCompleted handler. The following JavaScript is implemented by ASP.NET AJAX in the internal _onLogoutComplete handler:

// ASP.NET AJAX _onLogoutComplete implementation: always redirect when logging out
if (!redirectUrl) {
    window.location.reload();
}
else {
    window.location.href = redirectUrl;
}

However, because objects and methods in JavaScript are dynamic, you can assign a new function to the Microsoft AJAX Library’s Sys.Services.AuthenticationService._onLogout-Complete method with your own implementation. To implement custom logout functionality without redirecting or reloading, you can implement the JavaScript code shown in Example 6-4. This code assigns the fixup_onLogoutComplete method to the _onLogoutComplete method of Sys.Services.AuthenticationService:

Example 6-4. A custom implementation of the Microsoft AJAX Library’s logout handler can be assigned at run time (Web/AuthenticationDemo.js).

// An instance method assigned to AuthenticationService:
//     Sys.Services.AuthenticationService._onLogoutComplete
fixup_onLogoutComplete = function(result, context, methodName) {
    var redirectUrl = context[0];
    var userContext = context[3] || this.get_defaultUserContext();
    var callback = context[1] || this.get_defaultLogoutCompletedCallback()
        || this.get_defaultSucceededCallback();
    this._authenticated = false;
    if (callback) {
        callback(null, userContext, "Sys.Services.AuthenticationService.logout");
    }
    if(redirectUrl) {
        window.location.href = redirectUrl;
    }
}

function fixup(){
    Sys.Services.AuthenticationService._onLogoutComplete = fixup_onLogoutComplete;
}
Sys.Application.add_init(fixup);

JavaScript Profile Data with Sys.Services

ASP.NET profiles are used to store user information and can be used to encapsulate user preferences. A profile should not be used to store security settings or critical business data because it is configured through the web.config file and isn’t the most reliable form of data storage. To define a profile you must specify the provider and define the properties in web.config. Example 6-5 demonstrates a simple profile definition in web.config. This profile defines the startTopic preference and the Wiki.editorType preference, which keep track of the user’s startup topic and preferred editor.

Example 6-5. A profile is configured in web.config.

<profile enabled="true">
  <providers>
    <!-- Tip: use the strong name for the provider type! -->
    <add name="AspNetSqlProfileProvider"
         connectionStringName="LocalSqlServer"
         applicationName="/"
         type="System.Web.Profile.SqlProfileProvider, System.Web"/>
  </providers>
  <properties>
    <add name="startTopic" type="String" allowAnonymous="false" />
    <group name="Wiki">
      <add name="editorType" type="String" allowAnonymous="false" />
    </group>
  </properties>
</profile>

Sys.Services.ProfileService provides a JavaScript interface to ASP.NET profile functionality. Profile data can be loaded or saved through the profile service as needed. Building on the earlier example of the authentication service, the profile service can be called after a successful logon to get the current authentication principal’s application preferences. Example 6-6 demonstrates the profile loading logic, with the profile service’s load method called after authentication. In the sample code, you can load the wiki application with the preferred starting page from the start topic last saved by the user.

Example 6-6. A profile is loaded through Sys.Services.ProfileService.

// The callback function called if the authentication completed successfully.
function OnLoginCompleted(isLoggedIn, userContext, methodName) {
     showHideLogin();
     $get('passwordInput').value = '';
    if (!isLoggedIn)
        $get('loginFeedbackDiv').innerHTML = 'Unable to log in.';
    else{
        $get('loginFeedbackDiv').innerHTML = '';
        Sys.Services.ProfileService.load(null, OnProfileLoaded,
               OnProfileFailed, null);
    }
}

function OnProfileLoaded(propertiesLoaded){
    if (propertiesLoaded == 0) return;
    var topicDiv = $get('Topic'),
    topicDiv.innerHTML = Sys.Services.ProfileService.properties.startTopic;
    // TO DO: Load wiki with the preferred topic.
}

function OnProfileFailed(err, userContext, method){
    var error = err.get_exceptionType() + "-- " + err.get_message();
    alert(error);
}

To provide initial profile values in the server-side page load through script initialization, use the ProfileService-LoadProperties property in the ScriptManager through the ScriptManager or ScriptManagerProxy control, as in Example 6-7.

Example 6-7. Script initialization is used to render initial profile values from the server on page loading when specified with the ProfileService-LoadProperties property.

<asp:ScriptManagerProxy runat="server"
        ProfileService-LoadProperties="startTopic,Wiki.editorType">
    <Scripts>
        <asp:ScriptReference Path="Sys.AuthenticationService.js" />
    </Scripts>
</asp:ScriptManagerProxy>

To save profile data, you can simply call the save method of Sys.Services.ProfileService. The callback handlers aren’t required, and they aren’t desirable in most cases because the user will not be waiting for the call to be completed and is unaware that the profile data is being saved. The following example saves the given topic to the profile’s startTopic preference using the save method:

function saveStartTopic(topic){
    Sys.Services.ProfileService.properties.startTopic = topic;
    Sys.Services.ProfileService.save(['startTopic']);
}

Application Roles and Sys.Services.RoleService

Application roles are used in ASP.NET to aggregate permissions and to simplify security programming. Roles do not directly control security; they are only string-based attributes for a user that must be handled by application code. For example, before showing links to create new topics, you might check that a user has the contributor role, which includes the permissions read and write. Examples of roles in our wiki application are a dministrator, contributor, and moderator. The simplest way to configure roles with ASP.NET is to use the Web Site Administration Tool (WSAT). The WSAT for role management is shown in Figure 6-2.

The Web Site Administration Tool can be used to easily manage Web site roles from within Visual Studio.

Figure 6-2. The Web Site Administration Tool can be used to easily manage Web site roles from within Visual Studio.

In server-side code, roles can be checked by using the IPrincipal interface, which is exposed through the User property of the Page, Control, or HttpContext instances. The User object in ASP.NET is defined as a type of the IPrincipal interface, which can be a generic user defined by any authentication provider or a Windows security principal using the Active Directory security principal of the calling user. Use the IPrincipal method IsUserInRole to determine whether a user has a given role.

In server-side code, you can use IsInRole to load optimized script libraries for application roles. For example, you might have a lightweight script library that is used for seventy percent of the users of your application, who are either anonymous Internet users or do not have contributor rights. The editing capabilities of the wiki could be exposed through a library that is defined in the contribute.js JavaScript file, and these capabilities could be rendered only if the user has the contributor role. The following C# code can be used on the server to determine whether a user is in the application role contributor. The code adds the wikiEditor.js file only if the user is a contributor.

<script runat="server">
// Example OnPreRender server-side Page method
protected override void OnPreRender(EventArgs e)
{
    base.OnPreRender(e);
    if (this.User.IsInRole("contributor"))
    {
        this.ScriptManagerProxy.Scripts.Add( new ScriptReference("wikiEditor.js") );
    }
}
</script>

Note

Note

Roles can also be programmed on the server by using the static class Roles. The Roles class contains utility methods for working with the configured ASP.NET role provider.

Sys.Services.RoleService provides a JavaScript interface to roles application service. These roles are used to security trim the JavaScript user interface. On the server, roles are used to enforce security, but on the client, roles are used to configure the user interface. Security is always enforced on the server in the service implementation, as discussed in Chapter 2 and Chapter 3.

Tip

Tip

With the role service, a user can see indirectly all roles that she is a member of. Remember that all JavaScript methods and AJAX actions are exposed to the user and can be viewed through client-side debugging tools just like the ones you use to debug the application.

To load initial roles into the browser runtime during page load, set the ScriptManager’s property RoleService-LoadRoles to true through the ScriptManager or ScriptManagerProxy control, as the following code demonstrates:

<asp:ScriptManagerProxy ID="ScriptManagerProxy" runat="server"
        RoleService-LoadRoles="true" >
    <Scripts>
        <asp:ScriptReference Path="Sys.RoleService.js" />
    </Scripts>
</asp:ScriptManagerProxy>

When RoleService-LoadRoles is set to true, the ScriptManager initializes the roles to the page through the ScriptManager’s ConfigureApplicationServices method, mentioned earlier in the chapter. The following script is generated for a user with the contributor and moderator roles:

Sys.Services.RoleService._roles = Sys.Serialization.JavaScriptSerializer.deserialize(
    '["contributor","moderator"]'),

Tip

Tip

Application roles are not case sensitive.

You can use the isUserInRole method to determine the status of a user’s role at any time through JavaScript. The following code sample demonstrates a simple check on a user’s membership in the contributor role:

var isContrib = Sys.Services.RoleService.isUserInRole('contributor'),

The RoleService class differs from typical Web service proxies in that it saves the roles as an internal array, and it can be used to check role membership at any time without invoking a Web service call. In your JavaScript application code, you must know whether the ScriptManager has initialized the user’s roles during page loading and that the user has not logged in or out since either the page was loaded or the last occurrence of the role service’s load method. The role service knows only about the roles since the last time it was called. Therefore, you might want to load new role values after certain events occur, such as a successful login event, or after a certain time interval. While cached roles might be invalid, roles don’t change very often—they only change when an administrator grants a greater degree of access or the user completes a specific operation, such as authentication.

To load new role values at any time in the client life cycle, call the load method of the Sys.Services.RoleService proxy class. The load method is not a direct call to the Web service endpoint, but a call to a wrapper method that lets the AJAX library persist the values of the call in the RoleService instance. Because load returns null, the parameters of the method include a callback handler, an exception handler, and the user-context object. Building on the earlier examples of authentication, Example 6-8 demonstrates integrating the role service into the OnLoginCompleted JavaScript method.

Example 6-8. On successful login, you might want to load new role information for the current user before initializing the user interface for the logged-in user.

// The callback function called if the authentication completed successfully.
function OnLoginCompleted(isLoggedIn, userContext, methodName) {
    showHideLogin();
     $get('passwordInput').value = '';
     if (!isLoggedIn)
         $get('loginFeedbackDiv').innerHTML = 'Unable to log in.';
     else {
         $get('loginFeedbackDiv').innerHTML = '';
         Sys.Services.RoleService.load(rolesCompleted, rolesFailed, null);
     }
}

function rolesCompleted() {
    if (Sys.Services.RoleService.isUserInRole('contributor')) {
        //instantiate contributor controls on page
    }
    if (Sys.Services.RoleService.isUserInRole('moderator')) {
        //instantiate moderator controls on page
    }
}
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset