ASP.NET 部署和使用自定义 Web 服务器控件

来源:互联网 发布:王砚辉 知乎 编辑:程序博客网 时间:2024/06/06 16:36

本演练演示如何创建和测试自定义 ASP.NET Web 服务器控件。

在本演练中,您将学会如何执行以下任务:

  • 创建一个 ASP.NET Web 服务器控件。

  • 通过向该控件添加元数据来指定安全设置和设计时行为。

  • 在配置文件和该控件的程序集中指定一个标记前缀。

  • 指定一个供该控件在 Visual Studio 工具箱中使用的图标。

  • 将该控件编译为程序集并添加项目引用,以便在同一解决方案的另一个项目中使用它。

  • 在网页中测试该控件,并使用“属性”窗口或 IntelliSense 访问其属性。

Download(下载)主题附带含源代码的 Visual Studio 解决方案。

创建服务器控件

您将创建一个从标准 Label 控件派生的简单控件。该控件名为 WelcomeLabel它会将用户名称追加到 Text 属性中定义的文本字符串。例如,如果页开发人员将“Hello”设置为 Text 属性的值,则WelcomeLabel 控件将呈现“Hello, 用户名!”

该控件定义了 DefaultUserName 属性,该属性可指定用户未登录时使用的用户名值。例如,如果页开发人员将 Text 属性设置为“Hello”,并将DefaultUserName 属性设置为“Guest”,在当用户未登录时,该控件将显示“Hello Guest!”。

创建自定义服务器控件

  1. “文件”菜单中选择“新建项目”

    将显示“新建项目”对话框。

  2. “已安装的模板”下,展开“Visual Basic”“Visual C#”,然后选择“Web”

  3. 选择“ASP.NET 服务器控件”模板。

  4. “名称”框中输入 ServerControl1。

    “新建项目”对话框与下图类似。

    “新建项目”对话框
  5. 单击“确定”

    Visual Studio 会创建一个服务器控件项目,该项目具有一个名为 ServerControl1.cs 或 ServerControl1.vb 的类文件。

  6. “服务器资源管理器”中,将 ServerControl1.cs 或 ServerControl1.vb 重命名为 WelcomeLabel.cs 或 WelcomeLabel.vb。

    将出现一个对话框,询问您是否要重命名对 ServerControl1 的所有引用,如下图所示。

    重命名文件并更新引用
  7. 单击“是”

  8. 打开 WelcomeLabel.cs 或 WelcomeLabel.vb。

  9. 更改 WelcomeLabel 类,以便该类从System.Web.UI.WebControls.Label 而非System.Web.UI.WebControls.WebControl 继承。

  10. WelcomeLabel 类的 ToolboxData 特性中,将显示字符串“ServerControl1”的两个位置将该字符串更改为“WelcomeLabel”。

  11. 删除 WelcomeLabel 类中的代码,并插入DefaultUserName 属性和 RenderContents 方法,如下面的示例所示:

    VB
    ' WelcomeLabel.vbOption Strict OnImports SystemImports System.ComponentModelImports System.Security.PermissionsImports System.WebImports System.Web.UIImports System.Web.UI.WebControlsNamespace Samples.AspNet.VB.Controls    < _    AspNetHostingPermission(SecurityAction.Demand, _        Level:=AspNetHostingPermissionLevel.Minimal), _    AspNetHostingPermission(SecurityAction.InheritanceDemand, _        Level:=AspNetHostingPermissionLevel.Minimal), _    DefaultProperty("Text"), _    ToolboxData( _        "<{0}:WelcomeLabel runat=""server""> </{0}:WelcomeLabel>") _    > _    Public Class WelcomeLabel        Inherits WebControl        < _        Bindable(True), _        Category("Appearance"), _        DefaultValue(""), _        Description("The welcome message text."), _        Localizable(True) _        > _        Public Overridable Property Text() As String            Get                Dim s As String = CStr(ViewState("Text"))                If s Is Nothing Then s = String.Empty                Return s            End Get            Set(ByVal value As String)                ViewState("Text") = value            End Set        End Property        Protected Overrides Sub RenderContents( _            ByVal writer As HtmlTextWriter)            writer.WriteEncodedText(Text)            If Context IsNot Nothing Then                Dim s As String = Context.User.Identity.Name                If (s IsNot Nothing) AndAlso (s <> String.Empty) Then                    Dim split() As String = s.Split("\".ToCharArray)                    Dim n As Integer = split.Length - 1                    If (split(n) <> String.Empty) Then                        writer.Write(", ")                        writer.Write(split(n))                    End If                End If            End If            writer.Write("!")        End Sub    End ClassEnd Namespace
    C#
    VB
    // WelcomeLabel.csusing System;using System.ComponentModel;using System.Security.Permissions;using System.Web;using System.Web.UI;using System.Web.UI.WebControls;namespace Samples.AspNet.CS.Controls{    [    AspNetHostingPermission(SecurityAction.Demand,        Level = AspNetHostingPermissionLevel.Minimal),    AspNetHostingPermission(SecurityAction.InheritanceDemand,         Level=AspNetHostingPermissionLevel.Minimal),    DefaultProperty("Text"),    ToolboxData("<{0}:WelcomeLabel runat=\"server\"> </{0}:WelcomeLabel>")    ]    public class WelcomeLabel : WebControl    {        [        Bindable(true),        Category("Appearance"),        DefaultValue(""),        Description("The welcome message text."),        Localizable(true)        ]        public virtual string Text        {            get            {                string s = (string)ViewState["Text"];                return (s == null) ? String.Empty : s;            }            set            {                ViewState["Text"] = value;            }        }        protected override void RenderContents(HtmlTextWriter writer)        {            writer.WriteEncodedText(Text);            if (Context != null)            {                string s = Context.User.Identity.Name;                if (s != null && s != String.Empty)                {                    string[] split = s.Split('\\');                    int n = split.Length - 1;                    if (split[n] != String.Empty)                    {                        writer.Write(", ");                        writer.Write(split[n]);                    }                }            }            writer.Write("!");        }    }}
    C#
    using System.Drawing;using System;using System.Collections.Generic;using System.ComponentModel;using System.Linq;using System.Text;using System.Web;using System.Web.UI;using System.Web.UI.WebControls;namespace ServerControl1{    [DefaultProperty("Text")]    [ToolboxData("<{0}:WelcomeLabel runat=server></{0}:WelcomeLabel>")]    public class WelcomeLabel : Label    {        [        Bindable(true),        Category("Appearance"),        DefaultValue(""),        Description("The text to display when the user is not logged in."),        Localizable(true)        ]        public virtual string DefaultUserName        {            get            {                string s = (string)ViewState["DefaultUserName"];                return (s == null) ? String.Empty : s;            }            set            {                ViewState["DefaultUserName"] = value;            }        }        protected override void RenderContents(HtmlTextWriter writer)        {            writer.WriteEncodedText(Text);            string displayUserName = DefaultUserName;            if (Context != null)            {                string userName = Context.User.Identity.Name;                if (!String.IsNullOrEmpty(userName))                {                    displayUserName = userName;                }            }            if (!String.IsNullOrEmpty(displayUserName))            {                writer.Write(", ");                writer.WriteEncodedText(displayUserName);            }            writer.Write("!");        }    }}
  12. “解决方案资源管理器”中,展开“属性”“我的项目”,然后打开 AssemblyInfo.cs 或 AssemblyInfo.vb。

  13. 在文件开头添加下面的行:

    C#
    Using System.Web.UI;
    VB
    Imports System.Web.UI

    下一个步骤中将添加的 TagPrefixAttribute 特性需要此命名空间。

  14. 在文件末尾添加下面的行:

    C#
    [assembly: TagPrefix("ServerControl1", "aspSample")]
    VB
    <Assembly: TagPrefix("ServerControl1", "aspSample")> 

    TagPrefixAttribute 特性在命名空间ServerControl1 与前缀 aspSample 之间创建映射。

  15. 保存 WelcomeLabel.cs 或 WelcomeLabel.vb 文件。

代码讨论

以下各节说明了您在上一过程中创建的代码。

从 WebControl 类继承

如果控件要呈现用户界面 (UI) 元素或任何其他客户端可见的元素,则应从 System.Web.UI.WebControls.WebControl(或从其派生的类)派生该控件。(在此示例中,自定义控件派生自 Label,而后者派生自System.Web.UI.WebControls.WebControl。)如果控件要呈现在客户端浏览器中不可见的元素(如隐藏元素或meta 元素),则应从 System.Web.UI.Control 派生该控件。WebControl类从 Control 派生,并添加了与样式相关的属性,如FontForeColorBackColor此外,一个从 WebControl 派生的控件也自行参与到 ASP.NET 的主题功能。

DefaultUserName 属性

WelcomeLabel 控件定义了一个DefaultUserName 属性,并且该控件使用视图状态在回发期间保留此属性的值。 每次回发时,将重新创建页并从视图状态还原值。 如果 DefaultUserName 属性值并未存储在视图状态中,则在每次回发时会将值设置为其默认的 EmptyViewState属性继承自 WebControl,是保存数据值的字典。通过使用 String 键,可输入和检索值。此示例中将“DefaultUserName”用作键。 字典中的项被类型化为 Object,然后当您访问这些项时,必须将其强制转换为实际属性类型。有关视图状态的更多信息,请参见 ASP.NET 状态管理概述

RenderContents 方法

WelcomeLabel 控件通过重写继承的RenderContents 方法将文本写入响应流中。传入 RenderContents 方法的参数是HtmlTextWriter 类型的对象,是具有呈现 HTML 的方法的类。

注意,WelcomeLabel 控件会连续调用HtmlTextWriter 对象的Write 方法,而不是先执行字符串串联然后调用Write 方法。由于 HtmlTextWriter 对象直接写入输出流,因此这样可以提高性能。字符串串联需要时间和内存来创建字符串,然后写入流。

通常,在从 WebControl 派生控件并呈现单个元素时,应重写RenderContents 方法(而不是Render 方法)。在呈现控件及其样式特性的开始标记之后,WebControlRender 方法将调用RenderContents如果重写 Render 方法以写入内容,则控件将丢失生成到WebControlRender 方法中的样式呈现逻辑。有关呈现从 WebControl 派生的控件的更多信息,请参见Web 控件呈现示例

控件的特性

应用于 WelcomeLabel 控件和DefaultUserName 属性的特性中包含公共语言运行以及设计时工具使用的元数据。 在类级别上,通过以下特性标记 WelcomeLabel

  • DefaultPropertyAttribute. 此特性是设计时特性,它指定控件的默认属性。 在可视化设计器中,当页开发人员在设计图面上单击控件时,属性浏览器通常突出显示此默认属性。

  • ToolboxDataAttribute. 此特性指定元素的格式字符串。 如果在工具箱中双击控件或将其从工具箱拖动到设计图面上时,该字符串将成为控件的标记。 对于 WelcomeLabel,该字符串创建以下元素:

    <aspSample:WelcomeLabel runat="server"> </aspSample:WelcomeLabel>

WelcomeLabel 控件还从 WebControl 基类继承了两个特性:ParseChildrenAttributePersistChildrenAttribute这些特性将作为 ParseChildren(true)PersistChildren(false) 应用。 这些特性一起与 ToolboxDataAttribute 特性共同使用,这样可将子元素解释为属性,并将属性作为特性保留。

DefaultUserName 属性的特性

以下应用于 WelcomeLabelDefaultUserName 属性的特性是设计时特性,通常会将它们应用于控件的所有公共属性:

  • BindableAttribute. 此特性指定将属性绑定到数据对可视化设计器是否有意义。例如,在 Visual Studio 中,如果属性标记为 Bindable(true),则该属性可显示在“数据绑定”对话框中。 如果属性没有使用此特性标记,则属性浏览器会推断其值为 Bindable(false)

  • CategoryAttribute. 此特性指定如何在可视化设计器的属性浏览器中对属性进行分类。例如,当页开发人员使用属性浏览器的分类视图时,Category("Appearance") 将告知属性浏览器在“外观”类别中显示属性。可以指定一个对应于属性浏览器中的现有类别的字符串参数,也可以创建自己的类别。

  • DescriptionAttribute. 此特性指定属性的简短描述。 在 Visual Studio 中,属性浏览器将在“属性”窗口底部显示选定的属性的描述。

  • DefaultValueAttribute. 此特性指定属性的默认值。 此值应与从属性访问器 (getter) 返回的默认值相同。 在 Visual Studio 中,DefaultValueAttribute 特性允许页开发人员通过在“属性”窗口中显示快捷菜单,然后单击“重置”按钮将属性值重置为其默认值。

  • LocalizableAttribute. 此特性指定本地化属性对可视化设计器是否有意义。 当某属性标记为 Localizable(true) 时,可视化设计器会在将属性序列化为资源时包含该属性值。对控件轮询可本地化的属性时,设计器会将此属性值保存到非特定于区域性的资源文件或另一个本地化源中。

应用于控件及其成员的设计时特性不会影响控件在运行时工作的方式。 但在可视化设计器中使用该控件时,设计时特性能改进开发人员体验。 有关服务器控件的设计时和运行时特性的完整列表,可参见自定义服务器控件的元数据特性

标记前缀

标记前缀是指在页中以声明方式创建控件时出现在控件类型名称前面的前缀(如 <asp:Table /> 中的“asp”)。若要在页中以声明方式使用您的控件,则必须将一个标记前缀映射到该控件的命名空间。 通过在每个使用自定义控件的页上添加一个 @ Register 指令,页开发人员可提供标记前缀/命名空间映射,如以下示例所示:

<%@ Register Assembly="ServerControl" TagPrefix="aspSample"         Namespace="ServerControl"%>

将自定义服务器控件从工具箱拖动到 .aspx 页时,Visual Studio 将自动添加Register 指令。

除了在每个 .aspx 页中使用 @ Register 指令,您还可以在 Web.config 文件中指定标记前缀/命名空间映射。 如果将在 Web 应用程序的多个页中使用自定义控件,则该方法非常有用。 下面的示例显示了一个 Web.config 文件,该文件指定了ServerControl1 程序集的标记前缀。

<?xml version="1.0"?><configuration>  <system.web>       <pages>     <controls>       <add tagPrefix="aspSample" Assembly="ServerControl"          namespace="ServerControl">       </add>     </controls>   </pages>  </system.web></configuration>

测试自定义服务器控件

在下面的过程中,您将完成以下任务:

  • 创建一个网站,您将使用此网站测试在上一过程中创建的服务器控件。

  • 将网站项目中的引用添加到服务器控件项目。

  • WelcomeLabel 控件添加到“工具箱”中。

  • WelcomeLabel 控件的实例添加到 Default.aspx 页中。

  • 运行 Default.aspx 页以查看 WelcomeLabel 控件的工作情况。

首先,创建可用于测试的网站。

本演练使用网站项目。 您可以改用 Web 应用程序项目。 有关这些 Web 项目类型之间的差异的信息,请参见Web 应用程序项目与网站项目

创建网站项目以测试自定义服务器控件

  1. “文件”菜单上,单击“添加”,然后选择“新建网站”

    显示“新建网站”对话框。

  2. “已安装的模板”下,选择“Visual Basic”“Visual C#”,然后选择“ASP.NET 网站”模板。

  3. 将网站命名为 TestWebSite,并将它保存在 ServerControl1 解决方案文件夹下的一个新文件夹中。

    “新建网站”对话框与下图类似:

    “新建网站”对话框
  4. 单击“确定”

    Visual Studio 将创建一个网站项目,并将该项目添加到 ServerControl1 解决方案,然后在“源”视图中打开 Default.aspx 页。

  5. “服务器资源浏览器”中右击该网站项目,并选择“设为启动项目”

  6. “服务器资源浏览器”中右击该网站项目,并选择“添加引用”

    显示“添加引用”对话框。

  7. 选择“项目”选项卡,再选择“ServerControl1”项目,然后单击“确定”下图显示了“添加引用”对话框:

    “添加引用”对话框

下一个步骤是将服务器控件添加到工具箱中,以便您能在测试网站的网页中使用它。

将 WelcomeLabel 控件添加到工具箱中

  1. “生成”菜单中选择“生成解决方案”

    Visual Studio 将编译该解决方案,并将 ServerControl1 项目创建的程序集复制到 TestWebSite 项目的 Bin 文件夹中。

  2. 如果 Default.aspx 页仍处于打开状态,请打开“工具箱”窗口。

  3. 右击“工具箱”窗口中的任意位置,再单击“添加选项卡”

  4. 将新选项卡命名为 Server Control1。

  5. 右击“Server Control1”选项卡,然后单击“选择项”

  6. 选择“浏览”,然后浏览到 TestWebSite 项目的 Bin 文件夹。

  7. 选择 ServerControl1.dll,然后单击“打开”

    ServerControl1 程序集将添加到“选择工具箱项”对话框的“.NET Framework 组件”选项卡,如下图所示:

    “选择项”对话框
  8. 单击“确定”

    WelcomeLabel 控件即显示在“工具箱”“Server Control1”选项卡中。

现在可以将该服务器控件添加到一个网页中,然后对该网页进行测试。

测试 WelcomeLabel 控件

  1. 在 Default.aspx 页中,删除“Welcome to ASP.NET!”文本,并从“工具箱”中将WelcomeLabel 控件拖动到该位置。

  2. TextDefaultUserName 特性添加到 WelcomeLabel 控件的标记中,并将其设置为“Welcome”,如下面的示例所示:

    <aspSample:WelcomeLabel ID="WelcomeLabel1" runat="server" Text="Welcome" DefaultUserName="Guest"></aspSample:WelcomeLabel>
  3. 按 Ctrl-F5 在浏览器中显示该网页。

    WelcomeLabel 控件显示“Welcome!”,如下图所示:

    不带用户名的 WelcomeLabel 控件
  4. 单击“登录”超链接。

    此时将显示“登录”页。

  5. 单击“注册”超链接。

    将显示“创建新帐户”页,如下图所示。

    “创建新帐户”页面
  6. 输入 newuser 作为用户名,输入 newuser@asp.net 作为电子邮件地址,输入密码,然后单击“创建用户”按钮。

    ASP.NET 创建新用户帐户,让您以新用户身份登录,然后返回主页。 WelcomeLabel 控件现在显示“Welcome, newuser!”,如下图所示:

    带用户名的 WelcomeLabel 控件

为工具箱指定一个图标

Visual Studio 通常在工具箱中使用默认图标来显示控件,如下图所示:

工具箱中的默认服务器控件图标

作为控件的一个选项,可以通过在控件的程序集中嵌入一个 16*16 像素的位图来自定义控件在工具箱中的外观。

为工具箱指定一个图标

  1. 创建或获取一个 16*16 像素的位图,将其作为控件的工具箱图标。

  2. 将该位图命名为 WelcomeLabel.bmp。

  3. “解决方案资源管理器”中右击 ServerControl1 项目,选择“添加现有项”,然后选择位图文件。

  4. “属性”窗口中,将位图文件的“生成操作”属性更改为“嵌入的资源”

  5. “解决方案资源管理器”中,右击 ServerControl1 项目,然后选择“添加新项”

    显示“添加新项”对话框。

  6. 选择“类”模板,将文件命名为 ResourceFinder.cs 或 ResourceFinder.vb,然后单击“添加”

    打开 ResourceFinder.cs 或 Resourcefinder.vb 文件。

  7. 使 ResourceFinder 类成为sealedinternal(在 Visual Basic 中为FriendNotInheritable),如下面的示例所示。

    VB
    Friend NotInheritable Class ResourceFinderEnd Class
    C#
    VB
    using System;using System.Collections.Generic;using System.Linq;using System.Text;namespace ServerControl1{    internal sealed class ResourceFinder    {    }}
    C#
    <%@ Page Language="C#"%><!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>WelcomeLabel Test</title>  </head>  <body>    <form id="form1" runat="server">      <div>        <aspSample:WelcomeLabel Text="Hello" ID="WelcomeLabel1"           runat="server" BackColor="Wheat" ForeColor="SaddleBrown" />      </div>    </form>  </body></html>
  8. 保存并关闭文件。

  9. 打开 WelcomeLabel.cs 或 WelcomeLabel.vb 文件,然后将以下行添加到文件的开头:

    C#
    VB
    Using System.Drawing;

    下一个步骤中将添加的 ToolboxBitmapAttribute 特性需要此命名空间。

  10. WelcomeLabel 类中,添加ToolboxBitmapAttribute 特性,并指定具有 ServerControl1 命名空间前缀的 WelcomeLabel.bmp 文件名,如下面的示例所示:

    C#
    VB
    [DefaultProperty("Text")][ToolboxData("<{0}:WelcomeLabel runat=server></{0}:WelcomeLabel>")][ToolboxBitmap(typeof(ResourceFinder), "ServerControl1.WelcomeLabel.bmp")]public class WelcomeLabel : Label
  11. 保存并关闭文件。

  12. “生成”菜单中选择“生成解决方案”

  13. “TestWebSite”项目中,打开 Default.aspx 文件。

  14. “工具箱”中,右击“WelcomeLabel”控件,然后选择“删除”

  15. 右击“Server Control1”选项卡,然后单击“选择项”

  16. 选择“浏览”,然后浏览到 TestWebSite 项目的 Bin 文件夹。

  17. 选择 ServerControl1.dll,然后单击“打开”

    ServerControl1 程序集将添加到“选择工具箱项”对话框的“.NET Framework 组件”选项卡中。

  18. “选择项”对话框中,单击“确定”

    WelcomeLabel 控件即重新显示在“工具箱”“Server Control1”选项卡中。所选图标将显示在名称“WelcomeLabel”的左侧,如下图所示。

    工具箱中的自定义服务器控件图标

后续步骤

本演练演示了如何开发简单的自定义 ASP.NET 服务器控件以及如何在页中使用该控件。有关更多信息,包括有关呈现、定义属性、维护状态、处理不同的浏览器或设备类型以及实现复合控件的信息,请参见开发自定义 ASP.NET 服务器控件

通过使用在设计时和运行时提供不同用户界面的可视化设计器类,复杂控件(如 GridView 控件)进一步增强了其设计时体验。有关如何为控件实现自定义设计器类的更多信息,请参见 ASP.NET 控件设计器概述

请参见

其他资源

开发自定义 ASP.NET 服务器控件
Web Custom Control Behavior and Authoring
阅读全文
0 0
原创粉丝点击