Share via


Exercise 1: Using the Azure ASP.NET Providers

In this exercise, you configure a sample shopping cart application implemented with ASP.NET MVC to run in Windows Azure and modify it to use the ASP.NET providers from the Windows Azure samples. You start by adding authentication to the site using the membership provider. Next, you implement the role provider to classify users and customize the products that the application offers. Finally, you configure the session state provider to store the contents of the shopping cart.

Task 1 – Configuring the Application to Run in Windows Azure

The Azure Store is a standard ASP.NET MVC sample that mimics a simple commerce application. It presents a list of products that users can select and add to their shopping cart.

Before you begin, you may wish to build and run the solution and become acquainted with its operation. In its initial state, the application runs outside the compute emulator.

In this task, you create a Cloud Service project to configure the application to run in Windows Azure.

  1. Open Visual Studio in elevated administrator mode from Start | All Programs | Microsoft Visual Studio 2010 by right clicking the Microsoft Visual Studio 2010 shortcut and choosing Run as administrator.
  2. If the User Account Control dialog appears, click Continue.
  3. In the File menu, choose Open and then Project/Solution. In the Open Project dialog, browse to Ex1-UsingAzureProviders\Begin in the Source folder of the lab, select Begin.sln in the folder for the language of your preference (Visual C# or Visual Basic) and click Open.
  4. Next, create a new cloud service project and add it to the solution. In the File menu, point to Add and select New Project. In the New Project dialog, expand the language of your preference (Visual C# or Visual Basic) in the Installed Templates list and select Cloud. Choose the Windows Azure Cloud Service template, set the Name of the project to AzureStoreService and accept the proposed location in the folder of the solution. Click OK to create the project.

    Figure 1

    Configuring the application to run as a Cloud Service

  5. In the New Cloud Service Project dialog, click OK without adding new roles to the solution because you will use the existing application as a Web role.

    Figure 2

    No additional roles are required

  6. Associate the ASP.NET MVC project to the cloud project. In Solution Explorer, right-click the Roles node in the AzureStoreService project, point to Add and select Web Role Project in solution.

    Figure 3

    Associating the Web Role project

  7. In the Associate with Role Project dialog, select the MVCAzureStore project and click OK.

    Figure 4

    Associating the Web Role project

    Note:
    When you associate a new role, Visual Studio updates the ServiceDefinition.csdef and the ServiceConfiguration.cscfg files. If either of these files is currently open, make sure that you save it to preserve these changes.

  8. Add a reference to the assemblies required to support the Azure environment. In Solution Explorer, right-click the MVCAzureStore project, select Add Reference, click the .NET tab, select the Microsoft.WindowsAzure.Diagnostics, Microsoft.WindowsAzure.ServiceRuntime, and Microsoft.WindowsAzure.StorageClient components and click OK.

    Figure 5

    Adding a reference to the Windows Azure components

  9. Configure a TraceListener to enable diagnostics logging for the application. To do this, open the Web.config file of the MVCAzureStore project and insert a system.diagnostics section as shown (highlighted) below.

    (Code Snippet – Building MVC Applications with Windows Azure - Ex01 DiagnosticMonitorTraceListener)

    <configuration>
    ...
    <system.diagnostics>
    <trace autoflush="false" indentsize="4">
    <listeners>
    <add name="AzureDiagnostics" type="Microsoft.WindowsAzure.Diagnostics.DiagnosticMonitorTraceListener, Microsoft.WindowsAzure.Diagnostics, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
    </listeners>
    </trace>
    </system.diagnostics>

    </configuration>

    Note:
    These settings in the system.diagnostics section configure a trace listener specific to Windows Azure that allows the application to trace code execution using the classes and methods available in the System.Diagnostics.Trace class.

    This step is usually unnecessary for roles created in Visual Studio because they already include the necessary settings in their role templates.

  10. Add an entry point class to the Web role. In Solution Explorer, right-click the MVCAzureStore project, point to Add and select Class. In the Add New Item dialog, set the Name to WebRole.cs (for Visual C# projects) or WebRole.vb for (for Visual Basic projects) and click Add.
  11. In the WebRole.cs or WebRole.vb file, declare the following namespaces.

    (Code Snippet – Building MVC Applications with Windows Azure - Ex01 Azure Namespaces - C#)

    using Microsoft.WindowsAzure;
    using Microsoft.WindowsAzure.Diagnostics;
    using Microsoft.WindowsAzure.ServiceRuntime;

    (Code Snippet – Building MVC Applications with Windows Azure - Ex01 Azure Namespaces - VB)

    Imports Microsoft.WindowsAzure
    Imports Microsoft.WindowsAzure.Diagnostics
    Imports Microsoft.WindowsAzure.ServiceRuntime

  12. Update the declaration of the WebRole class to inherit the RoleEntryPoint class.namespace MVCAzureStore
    {
    public class WebRole
    : RoleEntryPoint
    {
    }
    }

    Public Class WebRole
    Inherits RoleEntryPoint
    End Class

  13. Add an OnStart method to set a role environment changing event.

    (Code Snippet – Building MVC Applications with Windows Azure - Ex01 WebRole OnStart - C#)

    public override bool OnStart()
    {
    return base.OnStart();
    }

    (Code Snippet – Building MVC Applications with Windows Azure - Ex01 WebRole OnStart - VB)

    Public Overrides Function OnStart() As Boolean
    Return MyBase.OnStart()
    End Function

    Note:
    The WebRole class is the entry point of the role. It contains methods that Windows Azure calls at various stages during its lifetime.

    Here, you override the OnStart method. Windows Azure invokes OnStart when the role starts. Typically, you use this method to execute initialization code for the application. Alternatively, web roles can place their initialization code in the ASP.NET Application_Start method.

  14. In the Global.asax file from the Web role, declare the following namespaces. using Microsoft.WindowsAzure;
    using Microsoft.WindowsAzure.ServiceRuntime;

    Imports Microsoft.WindowsAzure
    Imports Microsoft.WindowsAzure.ServiceRuntime

  15. Find the Application_Start method and initialize the configuration settings publisher.

    (Code Snippet – Building MVC Applications with Windows Azure - Ex01 SetConfigurationSettingPublisher – C#)

    void Application_Start(object sender, EventArgs e)
    {
    Microsoft.WindowsAzure.CloudStorageAccount.SetConfigurationSettingPublisher((configName, configSetter) =>
    {
    configSetter(RoleEnvironment.GetConfigurationSettingValue(configName));
    });
    ...
    }

    (Code Snippet – Building MVC Applications with Windows Azure - Ex01 SetConfigurationSettingPublisher - VB)

    Sub Application_Start(ByVal sender As Object, ByVal e As EventArgs)
    CloudStorageAccount.SetConfigurationSettingPublisher(Function(configName, configSetter) configSetter(RoleEnvironment.GetConfigurationSettingValue(configName)))
    ...
    End Sub

  16. Ensure that the System.Web.MVC assembly is included in the service package that you deploy to Windows Azure. To do this, for a Visual C# project, expand the References node in Solution Explorer for the MVCAzureStore project, right-click the System.Web.MVC assembly and select Properties. For a Visual Basic project, right-click the MVCAzureStore project and select Properties. In the Project Properties window, switch to the References tab, select the System.Web.MVC assembly, and press F4.

    To add the assembly to the service package, in the Properties window for the System.Web.Mvc assembly, change the value of the Copy Local setting to True.

    Figure 6

    Including assemblies in the service package deployed to Windows Azure

    Note:
    In general, you need to set Copy Local = True for any assembly that is not installed by default in the Windows Azure VMs to ensure that it is deployed with your application.

Task 2 – Configuring Authenticated Access to the Application

In this task, you configure authenticated access to the controller that handles store actions.

  1. Open the HomeController.cs file (for a Visual C# project) or the HomeController.vb file (for a Visual Basic project) in the Controllers folder and decorate the class with an Authorize attribute. This configures the application to require authenticated access for every available action on this controller.[HandleError]
    [Authorize]
    public class HomeController : HomeController
    {
    ...
    }

    <HandleError()> _
    <Authorize()> _
    Public Class HomeController
    Inherits System.Web.Mvc.Controller
    ...
    End Class

  2. Save the HomeController.cs or HomeController.vb file.

Task 3 – Configuring Membership Support Using the Azure TableStorageMembershipProvider

In this task, you add and configure the Azure ASP.NET providers for membership, role, and session.

  1. Add the Windows Azure ASP.NET Providers project to the solution. In Solution Explorer, right-click the Begin solution, point to Add and select Existing Project. Browse to Assets\AspProviders in the Source folder of the lab, select the AspProviders.csproj project and click Open.

    Note:
    The AspProviders project is available as a sample. It is included as part of this training kit for your convenience and is based on the original source code found in the MSDN Code Gallery. The project contains the implementation of ASP.NET application providers for membership, role, profile, and session state.

  2. Add a reference in the Web role to the AspProviders project. In Solution Explorer, right-click the MVCAzureStore project node and click Add Reference. In the Add Reference dialog, switch to the Projects tab, select the AspProviders project and click OK.

    Figure 7

    Adding a reference to the sample Azure ASP.NET Providers project

  3. Update the service configuration to include a connection string to the Azure Storage account where the data will be stored. In the AzureStoreService project, expand the Roles node and double-click the MvcAzureStore node to open the properties window for this role.
  4. In the MVCAzureStore[Role] properties window, select the Settings tab and click Add Setting. Set the Name of the new setting to DataConnectionString and change the Type to ConnectionString. Then, in the Value column, click the button labeled with an ellipsis.

    Figure 8

    Creating a new configuration setting for the role

  5. In the Storage Connection String dialog, choose the option labeled Use the Windows Azure storage emulator and click OK.

    Figure 9

    Configuring a storage connection string

  6. Press CTRL + S to save your changes to the role configuration.
  7. Open the Web.config file located in the root folder of the MVCAzureStore project.
  8. (Optional) Configure the storage account information required by the ASP.NET providers in the application configuration file. To do this, locate the <appSettings> element, which should be empty, and replace it with the following configuration block. If the appSettings element is missing, insert it as a direct child of the <configuration> element.

    Note:
    In addition to the service configuration file, you can also configure the Azure providers in the Web.config file of the application. This allows you to host the application outside the Azure fabric and still take advantage of the Azure ASP.NET providers and Azure storage. However, when the application runs in the Windows Azure environment, configuration settings in the service configuration file for the ASP.NET providers override those in the Web.config file. By using the Windows Azure settings, you can avoid redeploying the application when changing provider settings.

    (Code Snippet – Building MVC Applications with Windows Azure - Ex01 DataConnectionString)

    <configuration>
    ...
    <appSettings>
    <add key="DataConnectionString" value="UseDevelopmentStorage=true"/>
    </appSettings>
    ...
    </configuration>

  9. Configure the application to use the membership provider in the AspProviders project. To do this, replace the existing <membership> configuration section with the following (highlighted) configuration block.

    Note:
    The default ASP.NET MVC template in Visual Studio creates the configuration settings for the AspNetSqlMembershipProvider, which uses SQL Server for storage.

    (Code Snippet – Building MVC Applications with Windows Azure - Ex01 TableStorageMembershipProvider)

    <configuration>
    ...
    <system.web>
    ...
    <!-- Membership Provider Configuration -->
    <membership defaultProvider="TableStorageMembershipProvider" userIsOnlineTimeWindow="20">
    <providers>
    <clear/>
    <add name="TableStorageMembershipProvider"
    type="Microsoft.Samples.ServiceHosting.AspProviders.TableStorageMembershipProvider"
    description="Membership provider using table storage"
    applicationName="MVCAzureStore"
    enablePasswordRetrieval="false"
    enablePasswordReset="true"
    requiresQuestionAndAnswer="false"
    minRequiredPasswordLength="1"
    minRequiredNonalphanumericCharacters="0"
    requiresUniqueEmail="true"
    passwordFormat="Hashed"/>
    </providers>
    </membership>

    </system.web>
    ...
    </configuration>

    Note:
    Important: Before you execute the solution, make sure that the start up project is set. For MVC projects, the start page must be left blank.

    To set the start up project, in Solution Explorer, right-click the AzureStoreService project and select Set as StartUp Project.

    To set the start page, in Solution Explorer, right-click the MVCAzureStore project and select Properties. In the Properties window, select the Web tab and in the Start Action, select Specific Page. Leave the value of this field blank.

  10. Press F5 to build and run the application. An initialization procedure may be required the first time you execute an application that uses storage in your development environment. If this happens, wait until the procedure is complete and review its status. Click OK to continue.

    Figure 10

    Development storage initialization procedure status

  11. Notice that the application redirects you to the log in page when it starts because the authorization settings now require authenticated access to the Home controller. The membership database is initially empty, so you first need to create an account before you can proceed. In the log in page, click Register to access the user registration form.

    Figure 11

    Log in form indicating that authentication is required to proceed

  12. Fill in the registration form and click Create User to register your account.

    Figure 12

    Creating a new user account

  13. After successfully creating your account, the system automatically logs you in and displays the products page. Notice your user name displayed in the upper right corner of the window.

    Figure 13

    Products page displaying the current user

  14. Close the browser window to stop the running application.

Task 4 – Configuring Role Support Using the Azure TableStorageRoleProvider

In this task, you add role support to the application using the Azure role provider. This requires updating the registration process to capture the role of the user and configuring the settings for the role provider. To demonstrate the use of roles, you update the products page to filter the list of products based on the type of user.

  1. Add code to the role start-up routine to initialize the roles supported by the application. The code creates two roles, Home and Enterprise, which the application uses to classify different types of users. Open the Global.asax.cs (for Visual C# projects) or Global.asax.vb (for Visual Basic projects) file of the MVCAzureStore project and insert the following (highlighted) code into the Application_Start method.

    (Code Snippet – Building MVC Applications with Windows Azure - Ex01 Initialize Roles - C#)

    protected void Application_Start()
    {
    RegisterRoutes(RouteTable.Routes);
    LoadProducts();

    // Initialize the application roles
    if (!System.Web.Security.Roles.RoleExists("Home"))
    {
    System.Web.Security.Roles.CreateRole("Home");
    }

    if (!System.Web.Security.Roles.RoleExists("Enterprise"))
    {
    System.Web.Security.Roles.CreateRole("Enterprise");
    }
    }

    (Code Snippet – Building MVC Applications with Windows Azure - Ex01 Initialize Roles - VB)

    Sub Application_Start()
    RegisterRoutes(RouteTable.Routes)
    LoadProducts()

    ' Initialize the application roles
    If (Not System.Web.Security.Roles.RoleExists("Home")) Then
    System.Web.Security.Roles.CreateRole("Home")
    End If

    If (Not System.Web.Security.Roles.RoleExists("Enterprise")) Then
    System.Web.Security.Roles.CreateRole("Enterprise")
    End If
    End Sub

    Note:
    Although you could use the OnStart method of the web role to initialize the application roles, by using the ASP.NET Application_Start method the application remains host-environment agnostic and allows you to run the unmodified application outside Azure, leaving the OnStart method dedicated to Azure specific initialization.

    Note that you may need to remove the DiagnosticMonitorTraceListener in the system.diagnostics section of the configuration file in order to run the application outside the Azure environment.

  2. Change the Index action to filter the list of products based on the type of user. In the Controllers folder, open the HomeController.cs file (for a Visual C# project) or the HomeController.vb file (for a Visual Basic project) and insert the following (highlighted) code into the Index method immediately below the line that declares and initializes the filteredProducts variable.

    (Code Snippet – Building MVC Applications with Windows Azure - Ex01 Filter Products - C#)

    public ActionResult Index()
    {
    var products = this.HttpContext.Application["Products"] as List<string>;
    var itemsInSession = this.Session["Cart"] as List<string> ?? new List<string>();

    // add all products currently not in session
    var filteredProducts = products.Where(item => !itemsInSession.Contains(item));

    // Add additional filters here
    // filter product list for home users
    if (User.IsInRole("Home"))
    {
    filteredProducts = filteredProducts.Where(item => item.Contains("Home"));
    }

    return View(filteredProducts);
    }

    (Code Snippet – Building MVC Applications with Windows Azure - Ex01 Filter Products- VB)

    Function Index() As ActionResult
    Dim products = TryCast(Me.HttpContext.Application("Products"), List(Of String))
    Dim itemsInSession = If(TryCast(Me.Session("Cart"), List(Of String)), New List(Of String)())

    ' add all products currently not in session
    Dim filteredProducts = products.Where(Function(item) (Not itemsInSession.Contains(item)))

    ' Add additional filters here
    ' filter product list for home users
    If User.IsInRole("Home") Then
    filteredProducts = filteredProducts.Where(Function(item) item.Contains("Home"))
    End If

    Return View(filteredProducts)
    End Function

    Note:
    The inserted code appends an additional filter for users in the Home role that returns only items containing the text “Home”.

  3. Configure the application to use the role provider in the AspProviders project. In the Web.config file, replace the existing <roleManager> configuration section with the following (highlighted) configuration block.

    Note:
    The default ASP.NET MVC template in Visual Studio creates the configuration settings for the AspNetSqlRoleProvider, which uses SQL Server for storage, and the AspNetWindowsTokenRoleProvider, which uses Windows groups.

    (Code Snippet – Building MVC Applications with Windows Azure - Ex01 TableStorageRoleProvider)

    <configuration>
    ...
    <system.web>
    ...
    <!-- RoleManager Provider Configuration -->
    <roleManager enabled="true"
    defaultProvider="TableStorageRoleProvider"
    cacheRolesInCookie="true"
    cookieName=".ASPXROLES"
    cookieTimeout="30"
    cookiePath="/"
    cookieRequireSSL="false"
    cookieSlidingExpiration="true"
    cookieProtection="All">
    <providers>
    <clear/>
    <add name="TableStorageRoleProvider"
    type="Microsoft.Samples.ServiceHosting.AspProviders.TableStorageRoleProvider"
    description="Role provider using table storage"
    applicationName="MVCAzureStore" />
    </providers>
    </roleManager>
    ...
    </system.web>
    ...
    </configuration>

  4. Press F5 to build and run the application.
  5. In the log in page, click Register to access the user registration form. Notice that the registration wizard now displays a section to enter the role of the customer. Create a new user and assign it a Home customer profile.

    Figure 14

    Registration page showing role information

  6. Logged in as a Home user, proceed to the products page. Notice that the list of products only includes home products.

    Figure 15

    Products page showing a filtered list of products based on role

  7. Click the Logout link in the upper left corner of the application window.
  8. Register a new account and assign this user an Enterprise profile. Notice that the list of displayed products differs from that seen by a Home user.

    Figure 16

    Products page showing Enterprise products

  9. Select a product from the list and click Add item to cart. You may repeat the process to store additional items in the cart.
  10. Click the Check Out link to view the contents of the shopping cart. Verify that the items you selected appear on the list.

    Figure 17

    Check out page showing the contents of the shopping cart

  11. Do not close the browser window or navigate away from the checkout page.
  12. In the task bar, right-click the compute emulator icon and select Show Compute Emulator UI.
  13. In the Compute Emulator, right-click the AzureStoreService node and choose Suspend.

    Figure 18

    Suspending the service role instance

  14. Open a command window in elevated administrator mode, from Start | All Programs | Accessories | Command Prompt by right clicking the Command Prompt shortcut and choosing Run as Administrator and type iisreset.

    Figure 19

    Executing iisreset command

    Note:
    These two steps, recycling the role and restarting IIS, simulate what would happen in the Windows Azure platform when a role instance is restarted.

  15. Go back to the Compute Emulator and wait until the service stops as indicated by the instance icon turning red. Now, restart the service instance once again. To do this, right-click the AzureStoreService node and choose Run, then wait for the service to start.
  16. Switch back to the browser window showing the check out page and click Refresh. Notice that the order now appears empty.

    Note:
    The application is currently using inproc session state, which maintains all session state in-memory. When you stop the service instance, it discards all session state including the contents of the shopping cart. In the following task, you will configure the application to store session state in Azure storage, which allows the application to maintain session state in the presence of restarts and across multiple machines hosting the application.

  17. Close the browser window to stop the application.

Task 5 – Configuring Session Support Using the Azure TableStorageSessionProvider

Windows Azure can potentially host a Web role on multiple machines inside the fabric, which makes in-memory session state unsuitable for such an environment. In contrast, the session state provider in the AspProviders project uses table storage to store configuration information about the session and blob storage to store the session state itself.

In this task, you configure the application to use the Azure session state provider.

  1. Configure the application to use the session provider in the AspProviders project. To do this, in the Web.config file of the MVCAzureStore project, insert the following (highlighted) configuration block as an immediate child of the <system.web> element.

    (Code Snippet – Building MVC Applications with Windows Azure - Ex01 TableStorageSessionStateProvider)

    <configuration>
    ...
    <system.web>
    ...
    <!-- SessionState Provider Configuration -->
    <sessionState mode="Custom"
    customProvider="TableStorageSessionStateProvider">
    <providers>
    <clear/>
    <add name="TableStorageSessionStateProvider"
    type="Microsoft.Samples.ServiceHosting.AspProviders.TableStorageSessionStateProvider"
    applicationName="MVCAzureStore" />
    </providers>
    </sessionState>
    ...
    </system.web>
    ...
    </configuration>

  2. Press F5 to build and run the application.
  3. Log in and navigate to the products page. Select one or more products from the list and click Add item to cart. Repeat the process to store additional items in the cart.
  4. Click the Check Out link to view the contents of the shopping cart. Verify that the items you selected appear on the list.
  5. Do not close the browser window or navigate away from the checkout page.
  6. In the task bar, right-click the compute emulator icon and select Show Compute Emulator UI.
  7. In the Compute Emulator, right-click the AzureStoreService node and choose Suspend. Wait until the service stops as indicated by the instance icon turning red.
  8. Now, restart the service instance once again. To do this, right-click the AzureStoreService node and choose Run, then wait for the service to start.
  9. Switch back to the browser window showing the check out page and click Refresh. Notice that the order is intact. This confirms that the session state can persist through application restarts when using the Azure provider.
  10. Close the browser window to stop the application.