演练:使用 ASP.NET 应用程序服务

更新:2007 年 11 月

ASP.NET 在 Web 上提供一些应用程序服务,使客户端应用程序能够访问用户身份验证、角色和配置文件信息。以不同语言编写以及运行在不同操作系统上的客户端应用程序都可以访问这些信息。唯一的要求是这些客户端必须能够通过 SOAP 1.1 协议进行通信。

本演练分为以下几个部分:

  • 第 1 部分演示如何配置 ASP.NET 网站以公开应用程序服务。

  • 第 2 部分演示如何生成可访问用户的身份验证、角色和配置文件信息的 Windows 控制台应用程序。在本演练中,将生成一个 Windows 控制台应用程序,但 ASP.NET 应用程序服务可供发送和接收 SOAP 格式的消息的任意客户端应用程序使用。

先决条件

若要完成本演练,您需要:

  • Visual Studio 2008. 您不能对本演练使用 Microsoft Visual Web Developer 2005,因为 Visual Web Developer 速成版 不支持您将创建的 Windows 控制台应用程序。

  • 在计算机上安装 Microsoft SQL Server 或 SQL Server Express Edition。

公开应用程序服务

本节描述如何将应用程序服务作为 ASP.NET 网站的一部分进行公开,以便网络上的任何客户端都可以访问这些服务。这里介绍的步骤仅适用于服务器。

说明:

您必须对本演练使用文件系统网站。该演练假定使用 ASP.NET Development Server 而不是 IIS 来运行示例。有关更多信息,请参见 Visual Web Developer 中的 Web 服务器

创建应用程序服务网站

  1. 打开 Visual Studio 2008。

  2. 在“文件”菜单上单击“新建网站”。

    “新建网站”对话框随即出现。

  3. 在“Visual Studio 已安装的模板”下选择“ASP.NET 网站”。

  4. 在“位置”列表中,选择“文件系统”。

  5. 在“文件夹”文本框中,将网站命名为 WcfApplicationServices。

    说明:

    可以使用任何名称。如果您使用其他名称,请记下该名称,以便在本演练后面部分需要时替换它。

  6. 单击“确定”。

    Visual Studio 将创建一个新的 ASP.NET 网站并打开 Default.aspx 页。

  7. 在“解决方案资源管理器”中单击网站名称,然后按 F4 打开“属性”窗口。

  8. 在“属性”窗口中,将“使用动态端口”设置为“False”。

    这将指示 Visual Studio 在启动 ASP.NET Development Server 时指定一个固定端口而不是一个随机选择的端口。对于本演练,您必须拥有一个可以在生成客户端代理类和配置文件时使用的固定端口号。有关更多信息,请参见如何:指定 ASP.NET 开发服务器的端口

    说明:

    从“属性页”窗口无法访问“网站属性”窗口。

  9. 将“端口号”设置为 8080。

    说明:

    可以使用任何可用端口。如果您使用其他端口,请记下端口号,以便在本演练后面部分中用该数字替换 8080。

ASP.NET 成员资格、角色和配置文件信息存储在数据库中。此数据库在需要时自动创建。在下一个过程中,您将为应用程序创建用户和角色,该操作将自动创建此数据库。

创建用户和角色信息

  1. 将 Global.asax 文件添加到网站,并且在该文件中用下面的代码替换现有的 Application_Start 方法:

    <%@ Application Language="VB" %>
    
    <script runat="server">
    
        Sub Application_Start(ByVal sender As Object, ByVal e As EventArgs)
            ' Code that runs on application startup
            ' Warning. This code is just for test purposes 
            ' to generate a SQL Express database quickly.
            ' In a production environment, you must set 
            ' a SQL standard database separately.
            If Not Roles.RoleExists("Administrators") Then
                Roles.CreateRole("Administrators")
            End If
            If Not Roles.RoleExists("Friends") Then
                Roles.CreateRole("Friends")
            End If
        End Sub
    
    
    </script>
    
    
    <%@ Application Language="C#" %>
    
    <script runat="server">
    
        void Application_Start(object sender, EventArgs e) 
        {
            // Code that runs on application startup
            // Warning. This code is just for test purposes 
            // to generate a SQL Express database quickly.
            // In a production environment, you must set   3-25
            // a SQL standard database separately.
            if (!Roles.RoleExists("Administrators")){
                Roles.CreateRole("Administrators");
    
            }
            if (!Roles.RoleExists("Friends")){
                Roles.CreateRole("Friends");
    
            }
    
        }
    
    
    </script>
    
    

    首次运行 Web 应用程序时,代码将创建 Aspnetdb.mdf 本地数据库并将 Administrators 和 Friends 角色添加到其中。此数据库用于存储用户凭据、角色和配置文件信息。

  2. 打开 Default.apx 页并向其添加以下标记。从而为登录页、配置文件信息页和新用户页添加链接。稍后将在本演练中添加这些页。

    <%@ Page Language="VB" AutoEventWireup="true" CodeFile="Default.aspx.vb" Inherits="_Default" %>
    
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    
    <html xmlns="http://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="Profile.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" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head 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="Profile.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>
    
  3. 在 Default.aspx 代码隐藏文件中,在检查用户是否通过身份验证的 Page_Load 方法中添加代码。

    下面的示例演示如何检查经过身份验证的用户。

    Imports System
    Imports System.Data
    Imports System.Configuration
    Imports System.Collections
    Imports System.Web
    Imports System.Web.Security
    Imports System.Web.UI
    Imports System.Web.UI.WebControls
    Imports System.Web.UI.WebControls.WebParts
    Imports System.Web.UI.HtmlControls
    
    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.Data;
    using System.Configuration;
    using System.Collections;
    using System.Web;
    using System.Web.Security;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    using System.Web.UI.WebControls.WebParts;
    using System.Web.UI.HtmlControls;
    
    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";
            }
    
        }
    }
    
  4. 添加一个名为 Login.aspx 的页。请确保已选中“将代码放在单独的文件中”。

  5. Login 控件添加到 Login.aspx 文件中。

    下面的示例演示 Login.aspx 文件的标记:

    <%@ Page Language="VB" AutoEventWireup="true" %>
    
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head 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 Language="C#" AutoEventWireup="true" %>
    
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head runat="server">
        <title>Login Page</title>
    </head>
    <body>
        <form id="form1" runat="server">
        <div>
            <asp:Login ID="Login1"   runat="server"/>
        </div>
        </form>
    </body>
    </html>
    
  6. 添加一个名为 Profile.aspx 的页,并确保选中“将代码放在单独的文件中”。

  7. 将以下标记添加到 Profile.aspx 页中:

    <%@ Page Language="VB" AutoEventWireup="true" CodeFile="Profile.aspx.vb" Inherits="_Profile" %>
    
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    
    <html xmlns="http://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">ID#</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">ID#</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="Profile.aspx.cs" Inherits="ProfileInformation" %>
    
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    
    <html xmlns="http://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">ID#</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">ID#</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>
    

    配置文件页包含用于显示用户名和角色的 Label 控件,以及用于更改用户名和 ID 的 TextBox 控件。

  8. 在 Profile.aspx 页的代码隐藏文件中添加下面的代码:

    Imports System
    Imports System.Data
    Imports System.Configuration
    Imports System.Collections
    Imports System.Web
    Imports System.Web.Security
    Imports System.Web.UI
    Imports System.Web.UI.WebControls
    Imports System.Web.UI.WebControls.WebParts
    Imports System.Web.UI.HtmlControls
    
    Partial Public Class _Profile
        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.EmployeeId
            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.EmployeeId
            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.EmployeeId = TextBox3.Text
            End If
        End Sub
    End Class
    
    using System;
    using System.Data;
    using System.Configuration;
    using System.Collections;
    using System.Web;
    using System.Web.Security;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    using System.Web.UI.WebControls.WebParts;
    using System.Web.UI.HtmlControls;
    
    public partial class ProfileInformation : 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)
            {
                Label1.Text = HttpContext.Current.User.Identity.Name;
                string[] roles = Roles.GetRolesForUser();
                Label2.Text = "";
                foreach (string r in roles)
                {
                    Label2.Text += r + " ";
                }
    
                Label3.Text = Profile.FirstName;
                Label4.Text = Profile.LastName;
                Label5.Text = Profile.EmployeeId;
    
            }
            else
            {
                Label1.Text = "User is not Authenticated";
                Label1.ForeColor = System.Drawing.Color.Red;
            }
        }
    
        protected void Button2_Click(object sender, EventArgs e)
        {
            if (HttpContext.Current.User.Identity.IsAuthenticated)
            {
                Label1.Text = HttpContext.Current.User.Identity.Name;
                string[] roles = Roles.GetRolesForUser();
                Label2.Text = "";
                foreach (string r in roles)
                {
                    Label2.Text += r + " ";
                }
    
                Label3.Text = Profile.FirstName;
                Label4.Text = Profile.LastName;
                Label5.Text = Profile.EmployeeId;
    
            }
            else
            {
                Label1.Text = "User is not Authenticated";
                Label1.ForeColor = System.Drawing.Color.Red;
            }
        }
    
        protected void Button1_Click(object sender, EventArgs e)
        {
            if (HttpContext.Current.User.Identity.IsAuthenticated)
            {
                Profile.FirstName = TextBox1.Text;
                Profile.LastName = TextBox2.Text;
                Profile.EmployeeId = TextBox3.Text;
            }
        }
    }
    
    说明:

    在前面的示例中,代码隐藏文件中的类名已更改为 _Profile 以避免与 Profile 实例发生冲突。

    可以使用此页中的代码获取和更改用户配置文件信息。

    说明:

    只有启用了网站的配置文件属性后才能对项目进行编译。将在下一过程中执行该操作。

  9. 添加一个名为 CreateUser.aspx 的页并向其添加以下标记:

    <%@ Page Language="VB" AutoEventWireup="true" CodeFile="CreateUser.aspx.vb" Inherits="CreateUser" %>
    
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head 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>
            <p> 
                Check the following box to assign the user to the administrator role.
                Otherwise, the user will be assigned to the friends role by default. 
            </p>
            <span style="font-weight:bold; color:Red">Administrator</span> 
            <asp:CheckBox ID="CheckBox1" runat="server" />
    
        </div>
        </form>
    </body>
    </html>
    
    <%@ Page Language="C#" AutoEventWireup="true" 
    CodeFile="CreateUser.aspx.cs" Inherits="CreateUser" %>
    
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    
    <html xmlns="http://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>
            <p> 
                Check the following box to assign the user to the administrator role.
                Otherwise, the user will be assigned to the friends role by default. 
            </p>
            <span style="font-weight:bold; color:Red">Administrator</span> 
            <asp:CheckBox ID="CheckBox1" runat="server" />
    
        </div>
        </form>
    </body>
    </html>
    
  10. 在 CreateUser.aspx 页的代码隐藏文件中添加下面的代码:

    Imports System
    Imports System.Data
    Imports System.Configuration
    Imports System.Collections
    Imports System.Web
    Imports System.Web.Security
    Imports System.Web.UI
    Imports System.Web.UI.WebControls
    Imports System.Web.UI.WebControls.WebParts
    Imports System.Web.UI.HtmlControls
    
    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 CheckBox1.Checked Then
                HttpContext.Current.Response.Write(userName)
                Roles.AddUserToRole(userName, "Administrators")
            Else
                Roles.AddUserToRole(userName, "Friends")
            End If
    
            CheckBox1.Visible = False
    
            HttpContext.Current.Response.Redirect("~/default.aspx")
        End Sub
    End Class
    
    using System;
    using System.Data;
    using System.Configuration;
    using System.Collections;
    using System.Web;
    using System.Web.Security;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    using System.Web.UI.WebControls.WebParts;
    using System.Web.UI.HtmlControls;
    
    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 (CheckBox1.Checked)
            {
                HttpContext.Current.Response.Write(userName);
                Roles.AddUserToRole(userName, "Administrators");
            }
            else
                Roles.AddUserToRole(userName, "Friends");
    
            CheckBox1.Visible = false;
    
            HttpContext.Current.Response.Redirect("~/default.aspx");
        }
    }
    

    使用此页可以创建用户并为其分配角色。

下一步是在网站中启用 Forms 身份验证、角色和配置文件属性。您将使用 Web.config 文件中的配置设置完成此工作。

配置身份验证、角色和配置文件属性

  1. 打开网站的 Web.config 文件。

  2. 在 system.web 组中,将默认的 Windows 身份验证更改为 Forms 身份验证,如下面的示例所示:

    <authentication mode="Forms" />
    
  3. 在 system.web 组中,通过添加 roleManager 元素来配置角色服务,如下面的示例所示:

    <roleManager enabled="true"/>
    
  4. 在 system.web 组中,通过 profile 节及其 properties 元素对配置文件服务进行配置,如下面的示例所示:

    <profile enabled="true">
      <properties>
        <add name="FirstName"   type="String"/>
        <add name="LastName"    type="String"/>
        <add name="EmployeeId"  type="String"/>
      </properties>
    </profile>
    

    此配置文件设置可定义三个将由 ASP.NET 配置文件服务管理的属性。在运行时,ASP.NET 将动态创建一个类型为 ProfileCommon 且包含这些属性的类。

    下面的示例演示了部分 Web.config 文件,该部分包含了所有必需更改。

    <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="EmployeeId"  type="String"/>
      </properties>
    </profile>
    </system.web>
    

现在可以创建稍后将用于登录的用户信息。

创建用户并分配配置文件信息

  1. 在“解决方案资源管理器”中,选择 Default.aspx 页,然后按 Ctrl+F5 运行该页。

    该页将在浏览器中显示并使用以下 URL:

    https://localhost:8080/WcfApplicationServices/Default.aspx
    
  2. 单击“新建用户”。

    显示 CreateUser.aspx 页。

  3. 创建一些用户,然后将这些用户分配到预定义的角色。为此,请输入用户凭据,然后单击“创建用户”。

    请记录所创建的用户名和密码。您将需要使用它们来分配或更改用户的配置文件信息。

    例如,创建一个用户名为“joeA”的用户并选中“Administrators”(管理员)复选框,以便 joeA 成为 Administrators 角色的成员。创建另外一个用户名为“joeNA”的用户,但不选中“Administrator”(管理员)复选框。用户 joeNA 将是 Friends 角色而非 Administrators 角色的成员。Friends 和 Administrators 角色是通过您之前在 Global.asax 文件中添加到 Application_Start 方法的代码创建的。

    创建了用户后,您会被重定向到 Default.aspx 页。

  4. 在 Default.aspx 页中单击“登录”。

    显示 Login.aspx 页。

  5. 使用之前创建的其中一个用户的凭据登录。

    如果登录成功,您会被重定向到 Default.aspx 页。

  6. 单击“配置文件信息”。

    显示 Profile.aspx 页。

  7. 通过输入名字、姓氏和标识号,输入或更新已登录用户的配置文件信息。

  8. 单击“更新配置文件数据”。

  9. 单击“阅读配置文件信息”。

    此时将显示您刚输入的信息。执行此步骤可使您确保配置文件属性有效。

您已经完成创建用户和配置文件信息的工作。现在您将向客户端应用程序提供这些信息。

映射和配置应用程序服务

现在可以公开使用 ASP.NET 应用程序服务创建的用户信息。必须首先创建指向应用程序服务的映射文件 (.svc),然后才能从客户端访问用户的凭据和配置文件信息。这将使运行在可发送和接收 SOAP 消息的平台上的任何应用程序可以使用这些服务。您还必须配置网站,以便在网络上公开应用程序服务。

创建应用程序服务映射文件

  1. 将一个 WCF 服务文件 (.svc) 添加到网站并将其命名为 MyAuthenSvcWrap.svc。

  2. 用下面的指令替换现有的 @ ServiceHost 指令,下面的指令引用 System.Web.ApplicationServices.AuthenticationService 类:

    <%@ ServiceHost Language="VB"
      Service="System.Web.ApplicationServices.AuthenticationService" 
      Factory="System.Web.ApplicationServices.ApplicationServicesHostFactory" 
      Debug="true" %>
    
    <%@ ServiceHost Language="C#"
      Service="System.Web.ApplicationServices.AuthenticationService" 
      Factory="System.Web.ApplicationServices.ApplicationServicesHostFactory" 
      Debug="true" %>
    

    此示例服务不会实现自定义身份验证服务。相反,它会调用内置的 System.Web.ApplicationServices.AuthenticationService 类。

  3. 删除 App_Code 目录(App_Code\MyAuthenSvcWrap 和 App_Code\IMyAuthenSvcWrap)中的接口和类文件。

    接口和类文件是在向项目中添加 .svc 文件时创建的。由于是在使用 System.Web.ApplicationServices.AuthenticationService 服务而不是实现自定义服务,因此您不需要这些文件。

  4. 将另一个 WCF 服务文件 (.svc) 添加到网站并将其命名为 MyRoleSvcWrap.svc。

  5. 打开 MyRoleSvcWrap.svc 文件,并将其内容替换为下面的 @ ServiceHost 指令,该指令创建对 System.Web.ApplicationServices.RoleService 类的引用:

    <%@ ServiceHost Language="VB" 
       Service="System.Web.ApplicationServices.RoleService" 
       Factory="System.Web.ApplicationServices.ApplicationServicesHostFactory" %>
    
    <%@ ServiceHost Language="C#" 
      Service="System.Web.ApplicationServices.RoleService" 
      Factory="System.Web.ApplicationServices.ApplicationServicesHostFactory" %>
    
  6. 在 App_Code 目录中,删除 MyRoleSvcWrap 服务的接口和类文件。

  7. 将另一个 WCF 服务文件 (.svc) 添加到网站并将其命名为 MyProfileSvcWrap.svc。

  8. 打开 MyProfileSvcWrap.svc 文件并将其内容替换为下面的指令,该指令创建对 System.Web.ApplicationServices.ProfileService 类的引用:

    <%@ ServiceHost Language="VB"
      Service="System.Web.ApplicationServices.ProfileService" 
      Factory ="System.Web.ApplicationServices.ApplicationServicesHostFactory" %>
    
    <%@ ServiceHost Language="C#"
    Service="System.Web.ApplicationServices.ProfileService" 
    
    Factory ="System.Web.ApplicationServices.ApplicationServicesHostFactory" %>
    
  9. 在 App_Code 目录中,删除 MyProfileSvcWrap 服务的接口和类文件。

  10. 保存并关闭所有 .svc 文件。

现在可以配置 Web 应用程序以公开应用程序服务。

配置应用程序服务

  1. 打开或切换到 Web.config 文件。

  2. 在 configSections 部分下添加新的 system.web.extensions 部分。

  3. 在 scripting 元素中,通过 webServices 部分启用应用程序服务。

    下面的示例演示完成的 system.web.extensions 元素。

    </configSections>
    
    <system.web.extensions>
      <scripting>
        <webServices>
          <authenticationService enabled="true"
           requireSSL = "false"/>
          <profileService
              enabled="true"
              readAccessProperties="FirstName,LastName,EmployeeId"/>
          <roleService enabled="true"/>
        </webServices>
      </scripting>
    </system.web.extensions>
    
      <appSettings/>
    
  4. 添加一个 serviceHostingEnvironment 元素并将其 aspNetCompatibilityEnabled 设置为 true,作为 system.serviceModel 部分的子元素。

    下面的示例演示完成的 serviceHostingEnvironment 元素。

    </runtime>
     <system.serviceModel>
       <serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>
    
  5. 在 system.serviceModel 组中配置应用程序服务,以便客户端应用程序可以使用 SOAP 协议访问这些服务。为此,请按照下列步骤进行操作:

    1. 在 system.serviceModel 元素中,查找其名称属性为“MyAuthenSvcWrapBehavior”的 <behaviors><serviceBehaviors><behavior> 元素。

    2. 将 behavior 元素的 name 属性值从“MyAuthenSvcWrapBehavior”更改为“AppServiceBehaviors”。在本演练中,您可以将应用程序配置为对三个服务都使用 AppServiceBehaviors 行为。

    3. 从 <system.serviceModel><behaviors><serviceBehaviors> 元素中删除名为“MyRoleSvcWrapBehavior”和“MyProfileSvcWrapBehavior”的 behavior 元素。

    下面的示例演示完成的 <system.serviceModel> 部分。

    </runtime>
     <system.serviceModel>
       <serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>
      <behaviors>
       <serviceBehaviors>
        <behavior name="AppServiceBehaviors">
         <serviceMetadata httpGetEnabled="true" />
         <serviceDebug includeExceptionDetailInFaults="true" />
        </behavior>
       </serviceBehaviors>
      </behaviors>
    
  6. 在名为“MyAuthenSvcWrapBehavior”的 <system.serviceModel><services><service> 元素中,将 behavior 元素的 behaviorConfiguration 属性值从“MyAuthenSvcWrapBehavior”更改为“AppServiceBehaviors”。

  7. 将 name 属性值从“MyAuthenSvcWrap”更改为“System.Web.ApplicationServices.AuthenticationService”。

  8. 通过执行以下操作配置 <service><endpoint> 元素:

    1. 删除 address 属性。

    2. 将 binding 属性的值从“wsHttpBinding”更改为“basicHttpBinding”。

    3. 将 contract 属性的值从“IMyAuthenSvcWrap”更改为“System.Web.ApplicationServices.AuthenticationService”。

    4. 添加 bindingNamespace 属性并将其设置为“https://asp.net/ApplicationServices/v200”。

    5. 删除 identity 子元素。

    下面的示例演示身份验证 service 元素的标记。

    <service
      behaviorConfiguration="AppServiceBehaviors" 
      name="System.Web.ApplicationServices.AuthenticationService">
        <endpoint binding="basicHttpBinding" 
      contract="System.Web.ApplicationServices.AuthenticationService"
          bindingNamespace="https://asp.net/ApplicationServices/v200"       
                   >
        </endpoint>
    </service>
    

    有关更多信息,请参见 <service> 元素

  9. 对 MyAuthenSvcWrap 元素重复执行步骤 8。

    下面的示例演示完整的 system.serviceModel 元素。

    <system.serviceModel>
      <serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>
      <behaviors>
       <serviceBehaviors>
        <behavior name="AppServiceBehaviors">
         <serviceMetadata httpGetEnabled="true" />
         <serviceDebug includeExceptionDetailInFaults="true" />
        </behavior>
       </serviceBehaviors>
      </behaviors>
      <services>
        <service 
            behaviorConfiguration="AppServiceBehaviors" 
            name="System.Web.ApplicationServices.AuthenticationService">
          <endpoint  binding="basicHttpBinding" 
              contract="System.Web.ApplicationServices.AuthenticationService"
               bindingNamespace="https://asp.net/ApplicationServices/v200"       
                   />
        </service>
        <service 
            behaviorConfiguration="AppServiceBehaviors" 
            name="System.Web.ApplicationServices.RoleService">
          <endpoint  binding="basicHttpBinding" 
              contract="System.Web.ApplicationServices.RoleService"
              bindingNamespace="https://asp.net/ApplicationServices/v200"       
                   />
        </service>
        <service 
            behaviorConfiguration="AppServiceBehaviors" 
            name="System.Web.ApplicationServices.ProfileService">
          <endpoint  binding="basicHttpBinding"
              contract="System.Web.ApplicationServices.ProfileService"
              bindingNamespace="https://asp.net/ApplicationServices/v200"
                   />
        </service>
      </services>
     </system.serviceModel>
    </configuration>
    

现在可以运行网站以激活将由 Windows 客户端应用程序使用的身份验证服务。此操作还使您可以验证应用程序服务基础结构是否能够正常工作。

激活网站以公开应用程序服务

  • 在“解决方案资源管理器”中,右击 MyAuthenSvcWrap.svc 文件,然后单击“在浏览器中查看”。

    将调用相应的 Web 服务,并且浏览器中将显示某一页,其中提供了有关测试该服务的说明。请记下服务 URL,因为在接下来的步骤中您将需要利用它从客户端应用程序访问该服务。

    说明:

    不要关闭浏览器。使用 ASP.NET Development Server 时,浏览器必须一直打开以使应用程序服务保持活动状态。

您已经完成了在 Web 上配置应用程序服务以使它们在 Web 上可用的工作。下一步是从客户端应用程序调用这些服务。

使用应用程序服务

本节演示如何创建 Windows 控制台应用程序形式的客户端应用程序以访问应用程序服务。可以发送和接收 SOAP 格式消息的任何客户端都能访问应用程序服务。

若要创建客户端控制台应用程序,请执行以下一般步骤:

  • 创建客户端应用程序。

  • 生成应用程序服务代理文件和相关的配置文件。

  • 将生成的代理和配置文件添加到客户端应用程序,然后编译该应用程序。

  • 通过生成的代理调用应用程序服务操作。

    说明:

    如果向服务传递敏感用户数据(例如身份验证凭据),请使用安全套接字层(SSL,利用 HTTPS 协议)。例如,在下面的示例中,将 authenticationService 元素的 requireSSL 属性的值从“false”更改为“true”。有关更多信息,请参见 MSDN 网站上的传输安全HTTP Security and ASP.NET Web Services(HTTP 安全与 ASP.NET Web 服务)以及 IIS 网站上的在 IIS 7.0 中配置安全套接字层

创建 Windows 控制台应用程序

  1. 在 Visual Studio 的“文件”菜单上单击“添加”,然后单击“新建项目”。

  2. 选择首选语言,然后在“Visual Studio 已安装的模板”下选择“控制台应用程序”。

  3. 将应用程序命名为 AppSvcClient,输入应用程序的位置,然后单击“确定”。

    Visual Studio 将项目添加到当前解决方案并打开默认的类文件。

  4. 右击控制台应用程序的名称,然后单击“添加引用”。

  5. 在“添加引用”对话框中单击“.NET”选项卡,选择“System.ServiceModel”和“System.Runtime.Serialization”,然后单击“确定”。

    这会将包含使用代理类所需的类的命名空间添加到项目。

为应用程序服务生成代理类和配置信息

现在可以生成代理类和配置信息,以使控制台应用程序能够从 AppSvcClient 控制台应用程序中访问应用程序服务。需要为每个应用程序服务分别生成代理类和配置。

为应用程序服务生成代理类

  1. 在 Windows 的“开始”菜单中单击“所有程序”,然后依次单击“Microsoft Visual Studio 2008”、“Visual Studio Tools”和“Visual Studio 2008 命令提示”。

    说明:

    如果您运行的是 Microsoft Vista,必须以管理员身份运行此命令。

    将打开 Windows“命令”窗口,其环境设置包括 .NET Framework 工具的路径。

  2. 在 Windows 命令行下,转到包含 AppSvcClient 项目的 Program.cs 或 Module1.vb 文件的目录。

  3. 使用服务实用工具 (Svcutil.exe) 生成身份验证服务代理类。在您在第 1 步中打开的 Windows 命令行中输入下面的命令:

    svcutil https://localhost:8080/WcfApplicationServices/MyAuthenSvcWrap.svc?wsdl /language:"VB"
    
    svcutil https://localhost:8080/WcfApplicationServices/MyAuthenSvcWrap.svc?wsdl /language:"C#"
    
    说明:

       默认的语言输出是 C#。只有针对 Visual Basic 时才需要 /language:"VB" 标志。

    值“localhost:8080”必须与运行本演练中的网站时使用的 URL 匹配。如果您为 ASP.NET Development Server 使用了其他端口号,或者如果您要使用动态域名分配机制,请将其替换为相应值。如果端口号更改,则必须更新 Svcutil.exe 工具生成的 .config 文件以与新的端口号匹配。

    命令中的 .svc 文件的名称必须匹配在本演练前面部分中用于创建 .svc 文件的名称。代理类文件可以使用任意名称;在此示例中,代理类名称与相应 .svc 文件的名称匹配。

  4. 将由服务实用工具生成的 output.config 配置文件重命名为 App.config。

  5. 在“解决方案资源管理器”中右击控制台应用程序的名称,依次单击“添加”和“现有项”,选择生成的 AuthenticationService 代理类文件,然后单击“添加”。

  6. 在控制台应用程序的主类文件中,添加下面的代码以创建测试。

    Imports System.ServiceModel
    
    Module Module1
    
        Sub Main(ByVal args As String())
    
            If (args.Length <> 2) Then
                Console.WriteLine("missing args username password")
                Return
            End If
    
            Dim username As String = args(0)
            Dim password As String = args(1)
            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 have logged in.")
            Else
                Console.WriteLine("We could not validate your credentials.")
            End If
    
            Console.WriteLine("Enter any key to exit.")
            Console.Read()
    
        End Sub
    
    End Module
    
    using System;
    using System.Text;
    using System.ServiceModel;
    
    class Program {
    
        static void Main(string[] args) {
    
            if (args.Length < 1) {
                Console.WriteLine("missing args username password");
                return;
            }
    
            string username = args[0];
            string password = args[1];
            bool result = false;
    
            // BasicHttpBinding and endpoint are provided in app.config file
            AuthenticationServiceClient authService = new AuthenticationServiceClient();
            string customCredential = "Not Used by the default membership provider";
            bool isPersistent = true;  // authentication ticket remains valid across sessions.
    
            result = authService.Login(username, password, customCredential, isPersistent);
    
            if (result == true)
                Console.WriteLine("Welcome " + username + ". You have logged in.");
            else
                Console.WriteLine("Unable to login");
        }
    }
    

    从控制台应用程序运行该代码时,可以将用户名和密码传递给服务。您可以使用在本演练前面部分中创建的用户和密码值。

    测试应用程序可从 App.config 文件获取绑定和终结点信息。

  7. 通过执行以下操作来测试项目:

    1. 在 Visual Studio 中生成解决方案。

    2. 在命令行中,更改为 \bin\debug 文件夹并运行 AppSvcClient.exe。在命令行中传递用户名和密码。

    控制台应用程序将显示一条指示您已登录的消息。

  8. 通过将下面的命令复制到 Windows“命令”窗口中,生成配置文件服务代理类:

    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
    

    /config:app.config 选项将 App.config 文件指定为配置文件,以代替默认的 output.config 文件。/mergeConfig 选项指定此步骤中生成的配置信息应该与前面步骤中 App.config 文件中已有的信息合并。

  9. 通过将下面的命令复制到 Windows“命令”窗口中,生成身份验证服务代理类:

    svcutil.exe https://localhost:8080/WcfApplicationServices/MyAuthenSvcWrap.svc?wsdl /language:"VB" /config:app.config /mergeConfig
    
    svcutil.exe https://localhost:8080/WcfApplicationServices/MyAuthenSvcWrap.svc?wsdl /language:"C#" /config:app.config /mergeConfig
    
  10. 通过将下面的命令复制到 Windows“命令”窗口中,生成角色服务代理类:

    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
    
  11. 在“解决方案资源管理器”中右击控制台应用程序的名称,依次单击“添加”和“现有项”,选择生成的代理类文件,然后单击“添加”。

    代理类与 App.config 文件位于同一文件夹下,并且分别命名为 AuthenticationService、ProfileService 和 RoleService。

  12. 用下面的代码替换 Program 类中的代码:

    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
    
    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("http://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("http://someuri.tld")))
            End Sub
    
            Sub GetUserRoles(ByVal cookieContainer As CookieContainer)
                Dim roleSvc As New RoleServiceClient()
    
                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 profileSvc As New ProfileServiceClient()
    
                Using New OperationContextScope(DirectCast(profileSvc.InnerChannel, IContextChannel))
                    SetCookies(OperationContext.Current, cookieContainer)
                    Dim profileData As Dictionary(Of String, Object) = profileSvc.GetPropertiesForCurrentUser(New String() {"FirstName", "LastName", "EmployeeId"}, True)
    
                    Console.WriteLine("FirstName: " + profileData("FirstName"))
                    Console.WriteLine("LastName: " + profileData("LastName"))
                    Console.WriteLine("EmployeeId: " + profileData("EmployeeId"))
                End Using
            End Sub
    
            Public Function strEndPtAddr(ByVal service As String) As String
                Dim endPtAddr As String = "http://" + 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 , use that.
                    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("MyAuthenSvcWrap")
    
                Console.WriteLine("Attempting to connect as username = " + username + vbNewLine _
                  + "password length = " + password.Length.ToString() + vbNewLine _
                  + " on server " + Host + vbNewLine _
                  + "End point address: " + endPtAddr _
                  )
                ' BasicHttpBinding and endpoint are explicitly passed and ignored
                ' in 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"
                Dim isPersistent As Boolean = True   ' authentication ticket remains valid across sessions.
    
                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 have logged in.")
    
                    GetProfileInfo(cookieContainer)
                    GetUserRoles(cookieContainer)
                Else
                    Console.WriteLine("We could not validate your credentials.")
                End If
    
    
            End Sub
        End Class
    
    
    
        Sub Main(ByVal args As String())
    
            If (args.Length < 1) Then
                Console.WriteLine("missing args username password")
                Return
            End If
    
            Dim mst As MyServiceTst = New MyServiceTst()
            mst.Init(args)
    
    
            Console.WriteLine("Enter any key to exit.")
            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(@"http://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(@"http://someuri.tld")));
        }
    
    
        void GetUserRoles(CookieContainer cookieContainer) {
    
            string endPtAddr = strEndPtAddr("MyRoleSvcWrap");
    
            RoleServiceClient roleSvc = new RoleServiceClient(new BasicHttpBinding(),
                 new EndpointAddress(endPtAddr));
    
            using (new OperationContextScope((IContextChannel)roleSvc.InnerChannel)) {
                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", "EmployeeId" };
    
            using (new OperationContextScope((IContextChannel)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 = @"http://" + Host + "/WcfApplicationServices/"
                + service + ".svc?wsdl";
    
            return endPtAddr;
        }
    
        public void Init(string[] args) {
    
            if (args.Length == 3)   // The host address was passed in , use that
                Host = args[2];
            else
                Host = "localhost:8080";  
    
            string username = args[0];
            string password = args[1];
            bool result = false;
            BasicHttpBinding binding = new BasicHttpBinding();
            string endPtAddr = strEndPtAddr("MyAuthenSvcWrap");
    
            Console.WriteLine("Attempting to connect as username = " + username
                + "\n password length = " + password.Length.ToString()
                + "\n on server " + Host + "\n"
                + "\n" + endPtAddr
            );
    
            // BasicHttpBinding and endpoint are explicitly passed and ignored
            // in app.config file
    
            AuthenticationServiceClient authService = new AuthenticationServiceClient(binding,
                                                         new EndpointAddress(endPtAddr));
    
            CookieContainer cookieContainer;
            string customCredential = "Not Used by the default membership provider";
            bool isPersistent = true;  // authentication ticket remains valid across sessions.
    
            using (new OperationContextScope(authService.InnerChannel)) {
                try {
                    result = 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 (result) {
                Console.WriteLine("Welcome " + username + ". You have logged in.");
    
                GetUserRoles(cookieContainer);
                GetProfileInfo(cookieContainer);
            } else {
                Console.WriteLine("We could not validate your credentials.");
            }
    
        }
    }
    
    class Program {
    
        static void Main(string[] args) {
    
            if (args.Length < 1) {
                Console.WriteLine("missing args username password [host]");
                return;
            }
            MyServiceTst mst = new MyServiceTst();
            mst.Init(args);
    
            Console.WriteLine("Enter any key to exit.");
            // Console.Read();
        }
    
    }
    
    
  13. 生成项目。

访问应用程序服务

现在可以运行客户端应用程序,并使用已经作为网站的一部分公开的应用程序服务。

运行 Windows 应用程序

  1. 在 Windows 命令提示符下,切换到控制台应用程序目录。

  2. 输入以下命令,其中的用户名和密码是在本演练前面部分中创建的其中一个用户的用户名和密码:

    AppSvcClient.exe <userName> <password>

    如果您输入了正确的凭据,则将通过身份验证并获得与已登录用户相关联的角色和配置文件信息。

后续步骤

本演练阐释了从可以发送和接收 SOAP 格式消息的客户端应用程序访问 ASP.NET 应用程序服务的基本原理。

您可能想要尝试其他应用程序服务功能。建议研究的方面如下:

  • 了解有关通过 .NET Framework 客户端使用应用程序服务的更多内容。有关更多信息,请参见客户端应用程序服务概述

  • 了解有关 Windows Communication Foundation (WCF) 和利用客户端以 SOAP 格式进行数据交换的更多内容。有关更多信息,请参见 MSDN 网站上的 XML Web Services Infrastructure(XML Web services 基础结构)。

有关 Web 服务的一般信息,您可能希望进行以下工作:

  • 了解进行 Web 服务调用时发生的处理。有关更多信息,请参见XML Web services 生存期分析

  • 了解如何使用 Web 服务。有关更多信息,请参见 XML Web services 方案

  • 了解有关 ASP.NET 应用程序服务的更多信息。有关更多信息,请参见 AuthenticationServiceLogin()。

请参见

任务

如何:启用 WCF 身份验证服务

如何:启用 WCF 角色服务

如何:启用 WCF 配置文件服务

概念

定义 ASP.NET 配置文件属性

ASP.NET 应用程序服务概述