Walkthrough: Using ASP.NET Application Services
ASP.NET provides application services that can be accessed over the Web that enable client applications to use user authentication, role, and profile information. The services can be accessed by client applications that are written in different languages and that run on different operating systems. The only requirement is that these clients must be able to communicate by using SOAP 1.1 protocol.
This walkthrough shows how to configure and use ASP.NET application services. The walkthrough is divided into the following parts:
The first part shows how to configure an ASP.NET Web site to expose the application services.
The second part shows how to build a Windows console application that accesses a user's authentication, role, and profile information. In this walkthrough you will build a Windows console application, but the ASP.NET application services are available to any client applications that can send and receive messages in SOAP format.
The final part describes how to deploy the application services Web site on Windows Server 2008 and IIS 7.0.
Prerequisites
In order to complete this walkthrough, you will need:
Visual Studio 2010 or later. You cannot use Visual Web Developer Express for this walkthrough, because you will create a Windows console application, which is not supported in Visual Web Developer Express.
Microsoft SQL Server or SQL Server Express installed on your computer.
Exposing the Application Services
This section describes how to expose the application services as part of an ASP.NET Web site so that they can be accessed by any client on the network. The steps described here apply only to the server.
Note
You must use a file system Web site or a Web application project for this walkthrough. For information about the difference between the project types, see Web Application Projects versus Web Site Projects in Visual Studio. The walkthrough assumes that you are using the Visual Studio Development Server instead of IIS to run the examples. For more information, see Web Servers in Visual Studio for ASP.NET Web Projects. For information about how to deploy the application on Windows Server 2008, see Deploying the Application Services Web Site on Windows Server 2008 later in this walkthrough.
To create the application services Web site
Open Visual Studio.
On the File menu, click New Web Site.
The New Web Site dialog box is displayed.
Under Visual Studio installed templates, select ASP.NET Web Site.
In the Location list, select File System.
In the Folder text box, name the Web site WcfApplicationServices.
Note
You can use any name. If you use a different name, note the name so that you can substitute it when it is required later in this walkthrough.
ClickOK.
Visual Studio creates a new ASP.NET Web site and opens the Default.aspx page.
In the View menu, clickOther Windows, and then clickProperties Window.
In Solution Explorer, click the name of the Web site.
In the Properties window, set Use dynamic ports to False.
This instructs Visual Studio to specify a fixed port instead of a randomly selected port when it starts the ASP.NET Development Server. For this walkthrough, you must have a fixed port number that you can use when you generate the client proxy classes and configuration files. For more information, see How to: Specify a Port for the ASP.NET Development Server.
Note
You cannot access the Web Site Properties window from the Properties Pages window.
Set Port number to 8080.
Note
You can use any available port. If you use a different port, note the port number so that you can substitute that number for 8080 later in this walkthrough.
ASP.NET membership, role, and profile information is stored in a database. This database is created automatically when it is first accessed. In the next procedure, you will write the code that creates users and roles for the Web site. The first time that the Web site is accessed, the database is automatically created. In addition, two roles (Managers and Friends) are added to it.
To create users and role information
Add a Global.asax file to the Web site.
Open the Global.asax file and replace the existing Application_Start method with the following code:
Sub Application_Start(ByVal sender As Object, ByVal e As EventArgs) If Not Roles.RoleExists("Managers") Then Roles.CreateRole("Managers") End If If Not Roles.RoleExists("Friends") Then Roles.CreateRole("Friends") End If End Sub
void Application_Start(object sender, EventArgs e) { if (!Roles.RoleExists("Managers")) { Roles.CreateRole("Managers"); } if (!Roles.RoleExists("Friends")) { Roles.CreateRole("Friends"); } }
The first time that the Web site is accessed, the code creates the Aspnetdb.mdf database in the App_Data folder and adds the roles Managers and Friends to it. This database is used to store user credentials, roles, and profile information.
Open the Default.aspx page and replace the markup that is in the page with the following markup.
<%@ Page Language="VB" AutoEventWireup="true" CodeFile="Default.aspx.vb" Inherits="_Default" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="https://www.w3.org/1999/xhtml"> <head id="Head1" runat="server"> <title>Application Services Home Page</title> </head> <body> <form id="form1" runat="server"> <div> <h2>Enter Users' Information</h2> The following selections enable you to create users, and assign them roles and profile information. <p> <asp:Label ID="LoggedId" Font-Bold="true" ForeColor="red" runat="server"/> </p> <table border="1"> <tr> <td align="left">Login to change profile</td> <td align="left"><asp:LoginStatus ID="LoginStatus1" runat="server" /></td> </tr> <tr> <td align="left">Define profile information (you must login first)</td> <td align="left"><a href="ProfileInfo.aspx" target="_self">Profile Information</a></td> </tr> <tr> <td align="left">Create user and assign role</td> <td align="left"><a href="CreateUser.aspx"target="_self">New User</a></td> </tr> </table> </div> </form> </body> </html>
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="https://www.w3.org/1999/xhtml"> <head id="Head1" runat="server"> <title>Application Services Home Page</title> <style type="text/css"> td{padding:6px; vertical-align:top;border:solid 1px #eeeeee;} </style> </head> <body> <form id="form1" runat="server"> <div> <h1>Application Services Home Page</h1> The following selections let you create users, assign them to roles, and set their profile information. <p> <asp:Label ID="LoggedId" Font-Bold="true" ForeColor="red" runat="server"/> </p> <table> <tr> <td align="right" >Log in:</td> <td align="left"><asp:LoginStatus ID="LoginStatus1" runat="server" /></td> </tr> <tr> <td align="right" >Set profile information:<br/>(You must be logged in.)</td> <td align="left"><a href="ProfileInfo.aspx" target="_self">Profile Information</a></td> </tr> <tr> <td align="right" >Create user and assign role:</td> <td align="left"><a href="CreateUser.aspx"target="_self">New User</a></td> </tr> </table> </div> </form> </body> </html>
This markup creates links for the login page, the profile information page, and the new user page. You will add these pages later in the walkthrough.
In the Default.aspx code-behind file, add the following code in the Page_Load method.
Imports System Imports System.Web Partial Public Class _Default Inherits System.Web.UI.Page Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs) If HttpContext.Current.User.Identity.IsAuthenticated Then LoggedId.Text = HttpContext.Current.User.Identity.Name + " you are logged in" End If End Sub End Class
using System; using System.Web; public partial class _Default : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { if (HttpContext.Current.User.Identity.IsAuthenticated) { LoggedId.Text = HttpContext.Current.User.Identity.Name + " you are logged in."; } else LoggedId.Text = "You are not logged in."; } }
The code checks whether the user is authenticated.
Add a page named Login.aspx.
Add a Login control to the Login.aspx file.
The following example shows the markup for the Login.aspx file:
<%@ Page Language="VB" AutoEventWireup="true" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="https://www.w3.org/1999/xhtml"> <head id="Head1" runat="server"> <title>Login Page</title> </head> <body> <form id="form1" runat="server"> <div> <asp:Login ID="Login1" runat="server" /> </div> </form> </body> </html>
<%@ Page AutoEventWireup="true" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="https://www.w3.org/1999/xhtml"> <head id="Head1" runat="server"> <title>User Login Page</title> </head> <body> <form id="form1" runat="server"> <h1> Log In</h1> <div> <%-- The Login control does all the work. --%> <asp:Login ID="Login1" runat="server"> </asp:Login> </div> </form> </body> </html>
Add a page named ProfileInfo.aspx, and make sure that Place code in separate file is selected.
Add the following markup to the ProfileInfo.aspx page:
<%@ Page Language="VB" AutoEventWireup="false" CodeFile="ProfileInfo.aspx.vb" Inherits="ProfileInfo" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="https://www.w3.org/1999/xhtml"> <head id="Head1" runat="server"> <title>Profile Page</title> </head> <body> <form id="form1" runat="server"> <div> <h3>Current Authenticated User Profile Information</h3> <a href="Default.aspx">back to default page</a> <h4>Read Profile Information</h4> <table> <tr> <td align="left">User Name</td> <td align="left"> <asp:Label ID="Label1" runat="server" Text="Label"/> </td> </tr> <tr> <td align="left">User Roles</td> <td align="left"> <asp:Label ID="Label2" runat="server" Text="Label"/> </td> </tr> <tr> <td align="left">First Name</td> <td> <asp:Label ID="Label3" runat="server" Text="Label"/> </td> </tr> <tr> <td align="left">Last Name</td> <td> <asp:Label ID="Label4" runat="server" Text="Label"/> </td> </tr> <tr> <td align="left">Phone #</td> <td> <asp:Label ID="Label5" runat="server" Text="Label"/> </td> </tr> </table> <asp:Button ID="Button2" runat="server" onclick="Button2_Click" Text="Read Profile Information" /> <hr /> <h3>Update Profile Information </h3> <table> <tr> <td align="left">First Name</td> <td align="left"><asp:TextBox ID="TextBox1" runat="server"/></td> </tr> <tr> <td align="left">Last Name</td> <td align="left"><asp:TextBox ID="TextBox2" runat="server"/></td> </tr> <tr> <td align="left">Phone Number</td> <td align="left"><asp:TextBox ID="TextBox3" runat="server"/></td> </tr> </table> <asp:Button ID="Button1" runat="server" onclick="Button1_Click" Text="Update Profile Data" /> </div> </form> </body> </html>
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="ProfileInfo.aspx.cs" Inherits="ProfileInfo" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="https://www.w3.org/1999/xhtml"> <head id="Head1" runat="server"> <title>User Profile Information Page</title> <style type="text/css"> td { padding: 6px; vertical-align: top; border: solid 1px #eeeeee; } </style> </head> <body> <form id="form1" runat="server"> <div> <h1> View and Update User Profile Information</h1> <p> This page lets you view and set profile information for the currently logged-in user.</p> <p> <a href="Default.aspx">Back to default page</a></p> <h2> View Profile Information</h2> <table> <tr> <td align="right"> User name: </td> <td align="left"> <asp:Label ID="Lbl_UserName" runat="server" Font-Bold="true" /> </td> </tr> <tr> <td align="right"> User roles: </td> <td align="left"> <asp:Label ID="Lbl_Roles" runat="server" Font-Bold="true" /> </td> </tr> <tr> <td align="right"> First name: </td> <td> <asp:Label ID="Lbl_FirstName" runat="server" Font-Bold="true" /> </td> </tr> <tr> <td align="right"> Last name: </td> <td> <asp:Label ID="Lbl_LastName" runat="server" Font-Bold="true" /> </td> </tr> <tr> <td align="right"> Phone number: </td> <td> <asp:Label ID="Lbl_Phone" runat="server" Font-Bold="true" /> </td> </tr> </table> <br /> <asp:Button ID="But_ReadProfile" runat="server" OnClick="But_ReadProfile_Click" Text="Read Profile Information" /> <br /> <hr /> <h2> Update Profile Information </h2> <table> <tr> <td align="right"> First name: </td> <td align="left"> <asp:TextBox ID="TB_FirstName" runat="server" /> </td> </tr> <tr> <td align="right"> Last name: </td> <td align="left"> <asp:TextBox ID="TB_LastName" runat="server" /> </td> </tr> <tr> <td align="right"> Phone number: </td> <td align="left"> <asp:TextBox ID="TB_phoneNumber" runat="server" /> </td> </tr> </table> <br /> <asp:Button ID="But_UpdateProfile" runat="server" OnClick="But_UpdateProfile_Click" Text="Update Profile Data" /> </div> </form> </body> </html>
The Profile page contains Label controls that are used to display the user name and role, and TextBox controls that are used to change the user name and phone number.
In the code-behind file for the ProfileInfo.aspx page, add the following code:
Imports System Imports System.Web Imports System.Web.Security Partial Class ProfileInfo Inherits System.Web.UI.Page Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs) Dim Profile As ProfileCommon = TryCast(HttpContext.Current.Profile, ProfileCommon) If HttpContext.Current.User.Identity.IsAuthenticated Then Label1.Text = HttpContext.Current.User.Identity.Name Dim roles As String() = _ System.Web.Security.Roles.GetRolesForUser() Label2.Text = "" For Each r As String In roles Label2.Text += r + " " Next Label3.Text = Profile.FirstName() Label4.Text = Profile.LastName Label5.Text = Profile.PhoneNumber Else Label1.Text = "User is not Authenticated" Label1.ForeColor = System.Drawing.Color.Red End If End Sub Protected Sub Button2_Click(ByVal sender As Object, ByVal e As EventArgs) If HttpContext.Current.User.Identity.IsAuthenticated Then Label1.Text = HttpContext.Current.User.Identity.Name Dim roles As String() = _ System.Web.Security.Roles.GetRolesForUser() Label2.Text = "" For Each r As String In roles Label2.Text += r + " " Next Label3.Text = Profile.FirstName Label4.Text = Profile.LastName Label5.Text = Profile.PhoneNumber Else Label1.Text = "User is not Authenticated" Label1.ForeColor = System.Drawing.Color.Red End If End Sub Protected Sub Button1_Click(ByVal sender As Object, ByVal e As EventArgs) If HttpContext.Current.User.Identity.IsAuthenticated Then Profile.FirstName = TextBox1.Text Profile.LastName = TextBox2.Text Profile.PhoneNumber = TextBox3.Text End If End Sub End Class
public partial class ProfileInfo : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { ProfileCommon Profile = HttpContext.Current.Profile as ProfileCommon; if (HttpContext.Current.User.Identity.IsAuthenticated) { Lbl_UserName.Text = HttpContext.Current.User.Identity.Name; string[] roles = Roles.GetRolesForUser(); Lbl_Roles.Text = ""; foreach (string r in roles) { Lbl_Roles.Text += r + " "; } Lbl_FirstName.Text = Profile.FirstName; Lbl_LastName.Text = Profile.LastName; Lbl_Phone.Text = Profile.PhoneNumber; } else { Lbl_UserName.Text = "User is not logged in."; Lbl_UserName.ForeColor = System.Drawing.Color.Red; } } protected void But_ReadProfile_Click(object sender, EventArgs e) { if (HttpContext.Current.User.Identity.IsAuthenticated) { Lbl_UserName.Text = HttpContext.Current.User.Identity.Name; string[] roles = Roles.GetRolesForUser(); Lbl_Roles.Text = ""; foreach (string r in roles) { Lbl_Roles.Text += r + " "; } Lbl_FirstName.Text = Profile.FirstName; Lbl_LastName.Text = Profile.LastName; Lbl_Phone.Text = Profile.PhoneNumber; } else { Lbl_UserName.Text = "User is not logged in."; Lbl_UserName.ForeColor = System.Drawing.Color.Red; } } protected void But_UpdateProfile_Click(object sender, EventArgs e) { if (HttpContext.Current.User.Identity.IsAuthenticated) { Profile.FirstName = TB_FirstName.Text; Profile.LastName = TB_LastName.Text; Profile.PhoneNumber = TB_phoneNumber.Text; } } }
The code in this page enables you to obtain and change user profile information.
Note
The project will not compile until you enable profile properties for the Web site. You will do this in the next procedure.
Add a page named CreateUser.aspx and add the following markup to it:
<%@ Page Language="VB" AutoEventWireup="true" CodeFile="CreateUser.aspx.vb" Inherits="CreateUser" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="https://www.w3.org/1999/xhtml"> <head id="Head1" runat="server"> <title>Add New User</title> </head> <body> <form id="form1" runat="server"> <div> <h2>Add New User</h2> <a href="Default.aspx">back to default page</a> <asp:CreateUserWizard ID="CreateUserWizard1" runat="server" OnCreatedUser="On_CreatedUser"> <wizardsteps> <asp:CreateUserWizardStep ID="CreateUserWizardStep1" runat="server" /> <asp:CompleteWizardStep ID="CompleteWizardStep1" runat="server" /> </wizardsteps> </asp:CreateUserWizard> <span style="font-weight:bold; color:Red">Security Group</span> <br /> <asp:RadioButton ID="RDO_Friends" Text="Friends" runat="server" Checked="true" GroupName="GP1"/> <asp:RadioButton ID="RDO_Manager" Text="Managers" runat="server" GroupName="GP1" /> </div> </form> </body> </html> Imports System Imports System.Web Imports System.Web.Security Partial Public Class CreateUser Inherits System.Web.UI.Page Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs) End Sub Protected Sub On_CreatedUser(ByVal sender As Object, ByVal e As EventArgs) Dim userName As String = CreateUserWizard1.UserName If RDO_Manager.Checked Then HttpContext.Current.Response.Write(userName) Roles.AddUserToRole(userName, "Managers") Else Roles.AddUserToRole(userName, "Friends") End If HttpContext.Current.Response.Redirect("~/default.aspx") End Sub End Class
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="CreateUser.aspx.cs" Inherits="CreateUser" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="https://www.w3.org/1999/xhtml"> <head id="Head1" runat="server"> <title>Add User Page</title> </head> <body> <form id="form1" runat="server"> <div> <h1>Add User</h1> <a href="Default.aspx">Back to default page</a><br /> <asp:CreateUserWizard ID="CreateUserWizard1" runat="server" OnCreatedUser="On_CreatedUser"> <WizardSteps> <asp:CreateUserWizardStep ID="CreateUserWizardStep1" runat="server" /> <asp:CompleteWizardStep ID="CompleteWizardStep1" runat="server" /> </WizardSteps> </asp:CreateUserWizard> <span style="font-weight: bold; color: Red">Security Group</span> <br /> <asp:RadioButton ID="RDO_Friends" Text="Friends" runat="server" Checked="true" GroupName="GP1" /> <asp:RadioButton ID="RDO_Manager" Text="Managers" runat="server" GroupName="GP1" /> </div> </form> </body> </html>
using System; using System.Web; using System.Web.Security; public partial class CreateUser : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { } protected void On_CreatedUser(object sender, EventArgs e) { string userName = CreateUserWizard1.UserName; if (RDO_Manager.Checked){ HttpContext.Current.Response.Write(userName); Roles.AddUserToRole(userName, "Managers"); } else Roles.AddUserToRole(userName, "Friends"); HttpContext.Current.Response.Redirect("~/default.aspx"); } }
In the code-behind file for the CreateUser.aspx page, add the following code:
This page enables you to create users and assign them to a role.
The next step is to enable forms authentication, roles, and profile properties in the Web site. You do this with configuration settings in the Web.config file.
To configure authentication, roles, and profile properties
Open the Web site's Web.config file.
In the authentication element in the system.web section, change the default windows authentication to use forms, as shown in the following example:
<authentication mode="Forms" />
In the system.web section, configure the roles service by adding the roleManager element, as shown in the following example:
<roleManager enabled="true"/>
In the system.web section, configure the profile service through the profile section and its properties element as shown in the following example:
<profile enabled="true"> <properties> <add name="FirstName" type="String"/> <add name="LastName" type="String"/> <add name="PhoneNumber" type="String"/> </properties> </profile>
This profile setting defines three properties (FirstName, LastName, and PhoneNumber) that will be managed by the ASP.NET profile service. At run time, ASP.NET will dynamically create a class of type ProfileCommon that contains these properties.
The following example shows a part of the Web.config file that has all the required changes.
<system.web> <!-- Other settings. --> <authentication mode="Forms" /> <roleManager enabled="true"/> <profile enabled="true"> <properties> <add name="FirstName" type="String"/> <add name="LastName" type="String"/> <add name="PhoneNumber" type="String"/> </properties> </profile> <!-- Other settings. --> </system.web>
You can now create user information that you will use later to log in.
To create users and assign profile information
In Solution Explorer, select the Default.aspx page then press CTRL+F5 to run the page.
The page is displayed in the browser with the following URL:
https://localhost:8080/WcfApplicationServices/Default.aspx
Click New User.
The CreateUser.aspx page is displayed.
Create some users and assign them to the predefined roles. To do this, enter the user's credentials then click Create User.
Record the user names and passwords that you have created. You will need them to assign or change the users' profile information.
For example, create a user that has a user name "joeM" and select the Managers radio button so that joeM is a member of the Managers role. Create a second user that has a user name "joeNA", and select the Friends radio button. The user joeNA will be a member of the Friends role but not of the Managers role. The Friends and Managers roles are created by code that you added earlier to the Application_Start method in the Global.asax file.
After a user is created, you are redirected to the Default.aspx page.
In the Default.aspx page, click Login.
The Login.aspx page is displayed.
Log in using the credentials of one of the users that you created earlier.
If your login is successful, you are redirected to the Default.aspx page.
Click Profile Information.
The Profile.aspx page is displayed.
Enter or update the profile information for the logged-in user by entering the first name, last name, and phone number.
Click Update Profile Data.
Click Read Profile Information.
The information that you just entered is displayed. This step lets you make sure that profile properties are working.
Return to the Default.aspx page.
Log out from the user account for the user in the manager role.
Log in as a user in the Friends role.
For example, log in as joeNA.
Enter profile information for the logged-in user.
You are finished creating users, roles, and profile information. You will now make this information available to client applications.
Mapping and Configuring the Application Services
You can now expose the user information that you have created by using ASP.NET application services. Before you can access the user's credential and profile information from the client, you must create mapping files (.svc) that point to the application services. This makes the services available to any application that is running on a platform that can send and receive SOAP messages. You must also configure the Web site so the application services are exposed on the network.
To create application services mapping files
Add a WCF service file (.svc) to the Web site and name it MyAuthenticationSvcWrap.svc.
Open the MyAuthenticationSvcWrap.svc file and replace the existing @ ServiceHost directive with the following directive, which references the System.Web.ApplicationServices.AuthenticationService class:
<%@ ServiceHost Language="VB" Service="System.Web.ApplicationServices.AuthenticationService" Debug="true" %>
<%@ ServiceHost Language="C#" Service="System.Web.ApplicationServices.AuthenticationService" Debug="true" %>
This example service does not implement a custom authentication service. Instead, it calls (wraps) the built-in System.Web.ApplicationServices.AuthenticationService class.
Delete the interface and class files for the MyAuthenticationSvcWrap service in the App_Code directory (App_Code\MyAuthenticationSvcWrap and App_Code\IMyAuthenticationSvcWrap).
The interface and class files were created when the .svc file was added to the project. You do not need these files, because you are using the System.Web.ApplicationServices.AuthenticationService service and are not implementing a custom service.
Add another WCF service file (.svc) to the Web site and name it MyRoleSvcWrap.svc.
Open the MyRoleSvcWrap.svc file and replace its contents with the following @ ServiceHost directive, which creates a reference to the System.Web.ApplicationServices.RoleService class:
<%@ ServiceHost Language="VB" Service="System.Web.ApplicationServices.RoleService" %>
<%@ ServiceHost Language="C#" Service="System.Web.ApplicationServices.RoleService" %>
In the App_Code directory, delete the interface and class files for the MyRoleSvcWrap service.
Add another WCF service file (.svc) to the Web site and name it MyProfileSvcWrap.svc.
Open the MyProfileSvcWrap.svc file and replace its contents with the following directive, which creates a reference to the System.Web.ApplicationServices.ProfileService class:
<%@ ServiceHost Language="VB" Service="System.Web.ApplicationServices.ProfileService" %>
<%@ ServiceHost Language="C#" Service="System.Web.ApplicationServices.ProfileService" %>
In the App_Code directory, delete the interface and class files for the MyProfileSvcWrap service.
Save and close all .svc files
Build the WcfApplicationServices project to make sure that the markup, code, and configuration settings compile.
You can now configure the Web application to expose the application services.
To configure the application services
Open or switch to the Web.config file.
Between the configSections element and appSettings element, add a new system.web.extensions element.
Add a scripting element to the system.web.extensions element.
In the scripting element, enable the authentication, profile, and roles services through the webServices section.
The following example shows the finished system.web.extensions element.
<configSections> ... </configSections> <system.web.extensions><scripting><webServices><authenticationService enabled="true"requireSSL = "false"/><profileServiceenabled="true"readAccessProperties="FirstName,LastName,PhoneNumber"/><roleService enabled="true"/></webServices></scripting></system.web.extensions> <appSettings/>
Note
In a live Web site, you should set the requireSSL attribute to true.
As a child of the system.serviceModel section, add a serviceHostingEnvironment element and set its aspNetCompatibilityEnabled attribute to true.
The following example shows the finished serviceHostingEnvironment element.
<runtime> ... </runtime> <system.serviceModel><serviceHostingEnvironment aspNetCompatibilityEnabled="true"/> <behaviors> ... </behaviors>
In the system.serviceModel group, configure the application services so that they can be accessed by client applications by using the SOAP protocol. To do this, follow these steps:
In the system.serviceModel element, find the <behaviors><serviceBehaviors><behavior> element whose name attribute is MyAuthenticationSvcWrapBehavior.
Change the behavior element's name attribute value from MyAuthenticationSvcWrapBehavior to AppServiceBehaviors. In this walkthrough, you configure the application to use the AppServiceBehaviors behavior for the all three services.
Delete the behavior elements whose names are MyRoleSvcWrapBehavior and MyProfileSvcWrapBehavior from the <system.serviceModel><behaviors><serviceBehaviors> element.
In the <system.serviceModel><services><service> element that has a behaviorConfiguration attribute whose value is MyAuthenticationSvcWrapBehavior, do the following:
Change the behaviorConfiguration attribute value from MyAuthenticationSvcWrapBehavior to AppServiceBehaviors.
Change the name attribute value from MyAuthenticationSvcWrap to System.Web.ApplicationServices.AuthenticationService.
Configure the <service><endpoint> element by doing the following:
Delete the address attribute.
Change the value of the binding attribute value from wsHttpBinding to basicHttpBinding.
Change the value of the contract attribute from IMyAuthenticationSvcWrap to System.Web.ApplicationServices.AuthenticationService.
Add the bindingNamespace attribute and set it to https://asp.net/ApplicationServices/v200.
Delete the child identity element.
Delete the endpoint element whose address attribute is set to mex.
The following example shows the markup for the authentication service element.
<service behaviorConfiguration="AppServiceBehaviors" name="System.Web.ApplicationServices.AuthenticationService"> <endpoint binding="basicHttpBinding" bindingNamespace="https://asp.net/ApplicationServices/v200" contract="System.Web.ApplicationServices.AuthenticationService"/> </endpoint> </service>
For more information, see <service> element and <endpoint> element.
Repeat step 7 for the service elements that have a behaviorConfiguration attribute whose values are MyRoleSvcWrapBehavior and MyProfileSvcWrapBehavior. Substitute the following values for the name and contract attributes:
System.Web.ApplicationServices.RoleService
System.Web.ApplicationServices.ProfileService
The following example shows the complete system.serviceModel element.
<configuration> ... <system.serviceModel> <serviceHostingEnvironment aspNetCompatibilityEnabled="true"/> <services> <!-- this enables the WCF AuthenticationService endpoint --> <service behaviorConfiguration="AppServiceBehaviors" name="System.Web.ApplicationServices.AuthenticationService"> <endpoint binding="basicHttpBinding" bindingNamespace="https://asp.net/ApplicationServices/v200" contract="System.Web.ApplicationServices.AuthenticationService"/> </service> <!-- this enables the WCF RoleService endpoint --> <service behaviorConfiguration="AppServiceBehaviors" name="System.Web.ApplicationServices.RoleService"> <endpoint binding="basicHttpBinding" bindingNamespace="https://asp.net/ApplicationServices/v200" contract="System.Web.ApplicationServices.RoleService"/> </service> <!-- this enables the WCF ProfileService endpoint --> <service behaviorConfiguration="AppServiceBehaviors" name="System.Web.ApplicationServices.ProfileService"> <endpoint binding="basicHttpBinding" bindingNamespace="https://asp.net/ApplicationServices/v200" contract="System.Web.ApplicationServices.ProfileService"/> </service> </services> <behaviors> <serviceBehaviors> <behavior name="AppServiceBehaviors"> <serviceMetadata httpGetEnabled="true"/> <serviceDebug includeExceptionDetailInFaults="true"/> </behavior> </serviceBehaviors> </behaviors> </system.serviceModel> ... </configuration>
You can now run the Web service in order to activate the authentication, profile, and roles services that will be used by the client application. This also enables you to verify that the application service is working correctly.
To activate the Web site to expose the application services
In Solution Explorer, right-click the MyAuthenticationSvcWrap.svc file and then click View in Browser.
The Web service is invoked and a page is displayed in the browser that gives you instructions for testing the service. Make a note of the service URL (the URL that ends with "?wsdl"), because you will need it in the next steps to access the service from the client application. Repeat the process for the other two service files.
You have finished configuring the application services so that they are available on the Web. The next step is to invoke these services from a client application.
Using the Application Services in a Client Application
This section shows how to create a client application in the form of a Windows console application to access the application services. The application services can be accessed by any client that can send and receive messages in SOAP format.
To create the client console application, you follow these general steps:
Create the client application.
Generate application services proxy-class files and a related app.config configuration file.
Add the generated proxy-class and configuration files to the client application and compile the application.
Call application service operations through the generated proxy classes.
Note
If you pass sensitive user data to the service such as authentication credentials, use the secure sockets layer (SSL, by using HTTPS protocol). For example, in the sample later in this document, you would change the value of the authenticationService element's requireSSL attribute from false to true. (However, do not do this for the walkthrough, which does not provide instructions for configuring the site to use SSL.) For more information, see Transport Security and HTTP Security and ASP.NET Web Services on the MSDN Web site, and Configuring Secure Sockets Layer in IIS 7.0 on the IIS Web site.
To create a Windows console application
In Visual Studio, on the File menu, click Add and then click New Project.
Select your preferred language, and then under Visual Studio installed templates, select Console Application.
Name the application AppSvcClient, enter a location for the application, and then click OK.
Visual Studio adds the project to the current solution and opens the default class file.
Right-click the name of the console application and click Add Reference.
In the Add Reference dialog box, click the .NET tab, select System.ServiceModel and System.Runtime.Serialization, and then click OK. If you are using Visual Basic, you must also add System.Web.Extensions.
This adds assemblies to the project that are required in order to use the proxy classes that you will add in the next section.
Generating Proxy Classes and Configuration Information for Application Services
You can now generate proxy classes and configuration information that will enable the console application to access the application services from the AppSvcClient console application. You generate a proxy class and configuration separately for each application service.
To generate proxy classes for the application services
In the Windows Start menu, click All Programs, click Microsoft Visual Studio 2008, click Visual Studio Tools, and then click Visual Studio 2008 Command Prompt.
Note
If you are running Windows Vista®, run this command as an Administrator.
This opens a Windows Command window whose environment settings include the path for the .NET Framework tools.
At the Windows command line, change to the directory that contains the Program.cs or Module1.vb file for the AppSvcClient project.
Generate the authentication service proxy class by using the service utility tool (Svcutil.exe). Follow these steps:
In Solution Explorer, right-click the MyAuthenticationSvcWrap.svc file and then click View in Browser.
Copy the svcutil.exe command from the browser window.
At the Windows command window that you opened in step 1, paste the command from the browser window.
If you are working in Visual Basic, append /language:"VB" to the command.
The following example shows the command.
svcutil https://localhost:8080/WcfApplicationServices/MyAuthenticationSvcWrap.svc?wsdl /language:"VB"
svcutil.exe https://localhost:8080/WcfApplicationServices/MyAuthenticationSvcWrap.svc?wsdl
Note
The default language output is C#. The flag /language:"VB" is required only for Visual Basic. The svcutil command is displayed in the browser when you view the MyAuthenticationSvcWrap.svc file.
The value "localhost:8080" must match the URL that you use when you run the Web site from this walkthrough. If you used a different port number for the ASP.NET Development Server, or if you are using a dynamic port assignment, substitute the appropriate value. If the port number changes, you must update the .config file that is generated by the Svcutil.exe tool to match the new port number.
The name of the .svc file in the command must match the name that you used to create the .svc file earlier in this walkthrough. Because you are not explicitly specifying a name for the generated proxy class, the name of the generated proxy class is based on the service name that is assigned in the .svc file in the Web site (AuthenticationServices).
Rename the output.config configuration file that was generated by the service utility tool to App.config.
Note
Do not close the Windows Command window; you will generate additional proxy classes later in this walkthrough.
In Solution Explorer, right-click the name of the console application, click Add, click Existing Item, select the AuthenticationService proxy class file that you generated, and then click Add.
Using the same procedure as in the previous step, add the App.config file to the console application project.
In the console application's main class file, add the following code to create a test.
Imports System.ServiceModel Module Module1 Sub Main(ByVal args As String()) Dim username As String = "joeM" Dim password As String = "*(IU89iu" Dim result As Boolean = False Dim customCredential As String = "Not used by the default membership provider." Dim isPersistent As Boolean = True ' authentication ticket remains valid across sessions. 'BasicHttpBinding and endpoint are provided in app.config file. Dim authService As New AuthenticationServiceClient() result = authService.Login(username, password, customCredential, isPersistent) If result Then Console.WriteLine("Welcome, " & username & ". You are logged in.") Else Console.WriteLine("We could not validate your credentials.") End If Console.WriteLine("Press any key to quit.") Console.Read() End Sub End Module
using System; using System.Text; using System.ServiceModel; class Program { static void Main(string[] args) { string username = "joeNA"; string password = "*(IU89iu"; bool bLogin = false; // BasicHttpBinding and endpoint are provided in app.config file. AuthenticationServiceClient authService = new AuthenticationServiceClient(); string customCredential = "Not used by the default membership provider."; // Authentication ticket remains valid across sessions. bool isPersistent = true; bLogin = authService.Login(username, password, customCredential, isPersistent); if (bLogin == true) Console.WriteLine("Welcome " + username + ". You have logged in."); else Console.WriteLine("Unable to login!"); } }
The code enables you to pass a user name and password to the service when you run it from the console application. You can use values from the users and passwords that you created earlier in the walkthrough.
The test application gets the binding and endpoint information from the App.config file.
Test the project by doing the following:
Change the user name and password to values that you used earlier in the walkthrough.
In Solution Explorer, right-click the name of the console application (AppSvcClient) and then click Set as Startup Project.
In Visual Studio, press CTRL+F5 to build and run the solution.
The console application displays a message that states that you have logged in.
Generate the profile service proxy class by doing the following:
In Solution Explorer, right-click the MyProfileSvcWrap.svc file and then click View in Browser.
Copy the svcutil.exe command from the browser window.
At the Windows command window that you opened in step 1, paste the command from the browser window.
If you are working in Visual Basic, append /language:"VB" to the command.
Append the merge configuration (/mergeConfig) parameter.
The following example shows the command.
svcutil.exe https://localhost:8080/WcfApplicationServices/MyProfileSvcWrap.svc?wsdl /language:"VB" /config:app.config /mergeConfig
svcutil.exe https://localhost:8080/WcfApplicationServices/MyProfileSvcWrap.svc?wsdl /language:"C#" /config:app.config /mergeConfig
The /config:app.config option designates the App.config file as the configuration file instead of the output.config file, which is the default. The /mergeConfig option specifies that the configuration information that is generated in this step should be merged with the information that is already in the App.config file from previous steps.
Generate the role service proxy class by doing the following:
In Solution Explorer, right-click the MyRoleSvcWrap.svc file and then click View in Browser.
Copy the svcutil.exe command from the browser window.
At the Windows command window that you opened in step 1, paste the command from the browser window.
If you are working in Visual Basic, append /language:"VB" to the command.
Append the merge configuration (/mergeConfig) parameter.
The following example shows the command.
svcutil.exe https://localhost:8080/WcfApplicationServices/MyRoleSvcWrap.svc?wsdl /language:"VB" /config:app.config /mergeConfig
svcutil.exe https://localhost:8080/WcfApplicationServices/MyRoleSvcWrap.svc?wsdl /language:"C#" /config:app.config /mergeConfig
In Solution Explorer, right-click the name of the console application, click Add, click Existing Item, select the proxy class files that you generated, and then click Add.
The proxy classes are in the same folder as the App.config file, and are named AuthenticationService, ProfileService, and RoleService.
Replace the code in the Program class with the following code:
Imports System Imports System.Collections.Generic Imports System.Text Imports System.ServiceModel Imports System.ServiceModel.Activation Imports System.ServiceModel.Channels Imports System.ComponentModel Imports System.Web Imports System.Net 'Imports System.Web.ApplicationServices Module Module1 Class MyServiceTst Dim _host As String Public Property Host() As String Get Return _host End Get Set(ByVal value As String) _host = value End Set End Property Function GetCookies(ByVal oc As OperationContext) As CookieContainer Dim httpResponseProperty As HttpResponseMessageProperty = DirectCast(oc.IncomingMessageProperties(HttpResponseMessageProperty.Name), HttpResponseMessageProperty) If (httpResponseProperty.Equals(Nothing) = False) Then Dim cookieContainer As New CookieContainer() Dim header As String = httpResponseProperty.Headers(HttpResponseHeader.SetCookie) If header <> Nothing Then cookieContainer.SetCookies(New Uri("https://someuri.tld"), header) End If Return cookieContainer End If Return Nothing End Function Sub SetCookies(ByVal oc As OperationContext, ByVal cookieContainer As CookieContainer) Dim httpRequestProperty = New HttpRequestMessageProperty() httpRequestProperty = Nothing If oc.OutgoingMessageProperties.ContainsKey(HttpRequestMessageProperty.Name) Then httpRequestProperty = TryCast(oc.OutgoingMessageProperties(HttpRequestMessageProperty.Name), HttpRequestMessageProperty) End If If httpRequestProperty Is Nothing Then httpRequestProperty = New HttpRequestMessageProperty() oc.OutgoingMessageProperties.Add(HttpRequestMessageProperty.Name, httpRequestProperty) End If httpRequestProperty.Headers.Add(HttpRequestHeader.Cookie, cookieContainer.GetCookieHeader(New Uri("https://someuri.tld"))) End Sub Sub GetUserRoles(ByVal cookieContainer As CookieContainer) Dim endPtAddr As String = strEndPtAddr("MyRoleSvcWrap") Dim roleSvc As New RoleServiceClient(New BasicHttpBinding(), New EndpointAddress(endPtAddr)) Using New OperationContextScope(DirectCast(roleSvc.InnerChannel, IContextChannel)) SetCookies(OperationContext.Current, cookieContainer) Dim roles As String() = roleSvc.GetRolesForCurrentUser() If roles.Length = 0 Then Console.WriteLine("User does not belong to any role.") Else Dim userRoles As String = "" Dim i As Integer = 0 While i < roles.Length userRoles &= roles(i) & " " Global.System.Math.Max(Global.System.Threading.Interlocked.Increment(i), i - 1) End While Console.WriteLine("User's roles: " & userRoles) End If End Using End Sub Sub GetProfileInfo(ByVal cookieContainer As CookieContainer) Dim endPtAddr As String = strEndPtAddr("MyProfileSvcWrap") Dim profileSvc As New ProfileServiceClient(New BasicHttpBinding(), New EndpointAddress(endPtAddr)) Using New OperationContextScope(DirectCast(profileSvc.InnerChannel, IContextChannel)) SetCookies(OperationContext.Current, cookieContainer) Dim profileData As Dictionary(Of String, Object) = _ profileSvc.GetPropertiesForCurrentUser(New String() _ {"FirstName", "LastName", "PhoneNumber"}, True) Console.WriteLine("FirstName: " & profileData("FirstName")) Console.WriteLine("LastName: " & profileData("LastName")) Console.WriteLine("PhoneNumber: " & profileData("PhoneNumber")) End Using End Sub Public Function strEndPtAddr(ByVal service As String) As String Dim endPtAddr As String = "https://" & Host & "/WcfApplicationServices/" & service & ".svc?wsdl" Return endPtAddr End Function Sub Init(ByVal args As String()) If (args.Length = 3) Then ' The host address was passed in, so that is used. Host = args(2) Else Host = "localhost:8080" End If Dim username As String = args(0) Dim password As String = args(1) Dim result As Boolean Dim binding As BasicHttpBinding = New BasicHttpBinding() Dim endPtAddr As String = strEndPtAddr("MyAuthenticationSvcWrap") Console.WriteLine("Attempting to connect as username = " & username & vbNewLine _ & "password length = " & password.Length.ToString() & vbNewLine _ & " on server " & Host & vbNewLine _ & vbNewLine & "End point address: " & endPtAddr _ ) ' BasicHttpBinding and endpoint are explicitly passed and ignored ' in the app.config file. Dim authService As AuthenticationServiceClient = New AuthenticationServiceClient(binding, _ New EndpointAddress(endPtAddr)) Dim cookieContainer As CookieContainer = Nothing Dim customCredential As String = "Not used by the default membership provider." ' Authentication ticket remains valid across sessions. Dim isPersistent As Boolean = True Using New OperationContextScope(authService.InnerChannel) Try result = authService.Login(username, password, customCredential, isPersistent) cookieContainer = GetCookies(OperationContext.Current) Catch enf As EndpointNotFoundException Console.WriteLine(enf.Message) Return End Try End Using If result Then Console.WriteLine("Welcome, " & username & ". You are logged in.") GetUserRoles(cookieContainer) GetProfileInfo(cookieContainer) Else Console.WriteLine("Credentials could not be validated.") End If End Sub End Class Sub Main(ByVal args As String()) If (args.Length < 1) Then Console.WriteLine("Missing command-line arguments: username password [host]") Return End If Dim mst As MyServiceTst = New MyServiceTst() mst.Init(args) Console.WriteLine("Press any key to quit.") Console.Read() End Sub End Module
using System; using System.Collections.Generic; using System.Text; using System.ServiceModel; using System.ServiceModel.Activation; using System.ServiceModel.Channels; using System.ComponentModel; using System.Web; using System.Net; class MyServiceTst { string _Host { get; set; } CookieContainer GetCookies(OperationContext oc) { HttpResponseMessageProperty httpResponseProperty = (HttpResponseMessageProperty)oc.IncomingMessageProperties[HttpResponseMessageProperty.Name]; if (httpResponseProperty != null) { CookieContainer cookieContainer = new CookieContainer(); string header = httpResponseProperty.Headers[HttpResponseHeader.SetCookie]; if (header != null) { cookieContainer.SetCookies(new Uri(@"https://someuri.tld"), header); } return cookieContainer; } return null; } void SetCookies(OperationContext oc, CookieContainer cookieContainer) { HttpRequestMessageProperty httpRequestProperty = null; if (oc.OutgoingMessageProperties.ContainsKey(HttpRequestMessageProperty.Name)) { httpRequestProperty = oc.OutgoingMessageProperties[HttpRequestMessageProperty.Name] as HttpRequestMessageProperty; } if (httpRequestProperty == null) { httpRequestProperty = new HttpRequestMessageProperty(); oc.OutgoingMessageProperties.Add(HttpRequestMessageProperty.Name, httpRequestProperty); } httpRequestProperty.Headers.Add(HttpRequestHeader.Cookie, cookieContainer.GetCookieHeader(new Uri(@"https://someuri.tld"))); } void GetUserRoles(CookieContainer cookieContainer) { string endPtAddr = strEndPtAddr("MyRoleSvcWrap"); RoleServiceClient roleSvc = new RoleServiceClient(new BasicHttpBinding(), new EndpointAddress(endPtAddr)); using (new OperationContextScope(roleSvc.InnerChannel)) { // CookieContainer must be set in order to call GetRolesForCurrentUser(). // 1638 SetCookies(OperationContext.Current, cookieContainer); string[] roles = roleSvc.GetRolesForCurrentUser(); if (roles.Length == 0) { Console.WriteLine("User does not belong to any role."); } else { string userRoles = ""; for (int i = 0; i < roles.Length; i++) { userRoles += roles[i] + " "; } Console.WriteLine("User's roles: " + userRoles); } } } void GetProfileInfo(CookieContainer cookieContainer) { string endPtAddr = strEndPtAddr("MyProfileSvcWrap"); ProfileServiceClient profileSvc = new ProfileServiceClient(new BasicHttpBinding(), new EndpointAddress(endPtAddr)); string[] strProfileProps = new string[] { "FirstName", "LastName", "PhoneNumber" }; using (new OperationContextScope(profileSvc.InnerChannel)) { SetCookies(OperationContext.Current, cookieContainer); Dictionary<string, object> profileData = profileSvc.GetPropertiesForCurrentUser(strProfileProps, true); foreach (string sProp in strProfileProps) Console.WriteLine(sProp + ": " + profileData[sProp]); } } public string strEndPtAddr(string service) { string endPtAddr = @"https://" + _Host + "/WcfApplicationServices/" + service + ".svc?wsdl"; return endPtAddr; } public MyServiceTst(string[] args) { if (args.Length == 3) // The host address was passed in, so that is used. _Host = args[2]; else _Host = "localhost:8080"; string username = args[0]; string password = args[1]; string endPtAddr = strEndPtAddr("MyAuthenticationSvcWrap"); Console.WriteLine("Attempting to connect as username = " + username + "\n password length = " + password.Length.ToString() + "\n on server " + _Host + "\n" + "\n" + "End point address: " + endPtAddr ); // BasicHttpBinding and endpoint are explicitly passed and ignored // in th app.config file. BasicHttpBinding binding = new BasicHttpBinding(); AuthenticationServiceClient authService = new AuthenticationServiceClient(binding, new EndpointAddress(endPtAddr)); CookieContainer cookieContainer; string customCredential = "Not used by the default membership provider."; // Authentication ticket remains valid across sessions. bool isPersistent = true; bool bLogin = false; using (new OperationContextScope(authService.InnerChannel)) { try { bLogin = authService.Login(username, password, customCredential, isPersistent); cookieContainer = GetCookies(OperationContext.Current); } catch (EndpointNotFoundException enfe) { Console.WriteLine(enfe.Message); if (enfe.InnerException != null && enfe.InnerException.Message != null) Console.WriteLine(enfe.InnerException.Message); return; } } if (bLogin) { Console.WriteLine("Welcome, " + username + ". You are now logged in."); GetUserRoles(cookieContainer); GetProfileInfo(cookieContainer); } else { Console.WriteLine("Credentials could not be validated."); } } } class Program { static void Main(string[] args) { if (args.Length < 1) { Console.WriteLine("Missing command-line arguments: username password [host]"); return; } MyServiceTst mst = new MyServiceTst(args); Console.WriteLine("Press any key to quit."); Console.Read(); } }
Build the project.
Accessing the Application Services
You can now run the client application and use the application services that you have exposed as part of the Web site.
To run the Windows application
At the Windows command prompt, change to the console application directory.
Enter the following command, using the user name and password of one of the users that you created earlier in the walkthrough:
AppSvcClient.exe <userName> <password>
If you entered the correct credentials, you will be authenticated and will be able to obtain roles and profile information that is associated with the logged-in user.
Deploying the Application Services Web Site on Windows Server 2008
In order to run the application in a production environment, you can copy the Web site to a computer that is running Windows Server 2008 and then access the Web service from a client.
Note
This procedure assumes that you are familiar with Windows 2008 server administration tasks and with using IIS Manager to manage Web applications.
To run the Web application on Windows Server 2008
On the computer that is running Windows Server 2008, verify that the Web Server Role is installed on the server and the ASP.NET Role Service.
Verify that Microsoft SQL Server Express is installed.
Note
SQL Server Express is not recommended for production systems.
Copy the WcfApplicationServices directory and its subdirectories to the server.
Using IIS Manager, add a virtual directory at the root of the Web site and give it the alias WcfApplicationServices.
Set the WcfApplicationServices physical path to the path of the WcfApplicationServices directory from the previous step.
Convert the WcfApplicationServices virtual directory into an application.
In Windows Explorer, open the WcfApplicationServices directory.
Delete the SQL Server Express log file (aspnetdb_log.ldf), which is in the App_Data folder of the Web site.
Right-click the WcfApplicationServices\App_Data directory, click Properties, and then click the Security tab.
Click Edit.
The Permissions dialog box for the App_Data folder is displayed.
Click Add.
The Select Users, Computers, or Groups dialog box is displayed
Verify that the local server computer is listed under From this location type. If the server is not listed, click Location and then select the local server.
In the text box, enter NETWORK SERVICE.
Close the dialog boxes that you have opened.
The default application pool runs under the NETWORK SERVICE account. This account needs permission to create the SQL log file and to make changes to the aspnetdb.mdf file.
On a different computer that has access to the server, open a browser and request the Default.aspx page in the Web application.
Log in to one of the accounts that you created earlier in the walkthrough to verify that the application is working.
On the server computer, run the ServiceModel registration tool (ServiceModelReg.exe) to register the service. From an elevated command prompt, enter the following command:
ServiceModelReg.exe -i
This registers the service model and updates the scriptmaps on IIS to expose the service.
On the client computer, run the following AppSvcClient.exe command, passing a user name and password, and passing the server as the third argument:
AppSvcClient.exe <userName> <password> <server>
You see the same output from AppSvcClient.exe as in the previous step.
If the AppSvcClient program returns an error, compare the URL parameter passed to AppSvcClient with the URL that is displayed by Svcutil.exe when you browse to WcfApplicationServices/MyAuthenticationSvcWrap.svc. For example, if the server computer name is bp0, enter the following URL in the browser:
https://bp0/WcfApplicationServices/MyAuthenticationSvcWrap.svc
The instructions to test the service include the URL that is required by the client application.
Next Steps
This walkthrough has illustrated the basic principles of accessing the ASP.NET application services from a client application that can send and receive messages in SOAP format.
You might want to experiment with additional application service features. Suggestions for additional exploration include the following:
Learn more about how to use application services from .NET Framework clients. For more information, see Client Application Services Overview.
Learn more about the Windows Communication Foundation (WCF) and about data exchange with the client in SOAP format. For more information, see XML Web Services Infrastructure on the MSDN Web site.
For general information about Web services, you might want to do following:
Understand how to use Web services. For more information, see XML Web Service Scenarios.
Learn more about ASP.NET application services. For more information, see AuthenticationService.Login.
Understand the processing that occurs when you make a Web service call. For more information, see Anatomy of an XML Web Service Lifetime.
See Also
Tasks
Walkthrough: Creating a Web Site with Membership and User Login
How to: Enable the WCF Authentication Service
How to: Enable the WCF Role Service
How to: Enable the WCF Profile Service
Reference
How to: Enable the WCF Role Serviced
Concepts
Defining ASP.NET Profile Properties