How to: Use Custom ASP.NET Server Controls in Visual Studio

You can make your custom server controls available in the Visual Studio Toolbox by defining the appropriate design-time attributes to be used by the visual designer. The following procedures create a simple control named MailLink, include it in the Toolbox, and use it to create an e-mail link in a Web page by rendering a hyperlink <a> element with a mailto: URL.

To create a custom control that contains design-time attributes

  1. In Visual Studio, create a library project and define a custom class that derives from WebControl, as shown in the following example.

    Note

    The complete source code is listed in the Example section.

    <Assembly: TagPrefix("Samples.AspNet", "Sample")> 
    Namespace Samples.AspNet
       < _
        ToolboxData("<{0}:MailLink ID='MailLinkID' Text='WebMaster' runat=""server""> </{0}:MailLink>")> _
        Public Class MailLink
            Inherits WebControl
         ' Custom code goes here.
    End Class
    
    End Namespace
    
    [assembly:TagPrefix("Samples.AspNet", "Sample")]
    namespace Samples.AspNet
    {
    
        [
            ToolboxData("<{0}:MailLink ID='MailLinkID' Text='WebMaster' runat=\"server\"> </{0}:MailLink>")
        ]
        public class MailLink : WebControl
        {
            // Custom code goes here.
        }
    
    }
    
  2. Add design-time attributes to provide custom metadata that will be used to display the control in the visual designer at design time. The following two design attributes are the only ones needed to make the MailLink control available in the Visual Studio Toolbox.

    The TagPrefix attribute specifies the prefix in front of the control name MailLink. Together, the prefix and control name define the tag name for the custom control (in this case, <Sample:MailLink> </Sample:MailLink>).

    <Assembly: TagPrefix("Samples.AspNet", "Sample")> 
    
    [assembly:TagPrefix("Samples.AspNet", "Sample")]
    

    The ToolboxData attribute specifies the default tag generated for the MailLink control when it is dragged from the Toolbox into a page at design time.

    <ToolboxData("<{0}:MailLink ID='MailLinkID' Text='Mail Webmaster' runat='server'"> </{0}:MailLink>")> 
    
    [ToolboxData("<{0}:MailLink ID='MailLinkID' Text='Mail Webmaster' runat=\"server\"> </{0}:MailLink>")]
    
  3. Compile the MailLink control in a library and name it MaiLink.Dll.

To add the custom control to the Toolbox

  1. On the View menu, click Toolbox.

  2. In the Toolbox, right-click and select Choose Items.

  3. In the Choose Toolbox Items dialog box, select the .NET Framework Components tab, and then click the Browse button to locate the MailLink.Dll you just built.

  4. Select the check box for the MailLink control and click OK.

    The custom MailLink control appears in the Toolbox.

  1. Create a new Web project. Then create a page named MailLink.aspx. This page will contain one of the following directives, depending on the language you selected for the project.

    <%@ page language="VB" %>
    
    <%@ page language="C#" %>
    
  2. Add the following basic page structure to host the MailLink control.

    <html xmlns="http://www.w3.org/1999/xhtml" >
    <head runat="server">
        <title>Using the MailLink control</title>
    </head>
    <body>
    <h1>Using the MailLink Custom Server Control</h1>
        <form id="form1" runat="server">
        <div>
    
       </div>
    
        </form>
    </body>
    </html>
    
  3. Switch to Design view and drag the MailLink control onto your page.

    Visual Studio adds two items to the page: a Register directive for the MailLink control, and the tag name of the MailLink control to use in the page.

  4. Run the page in a browser, and click the Mail Webmaster link.

    A mail message opens, addressed to the address specified by the control's Email property.

Example

The MailLink control overrides the TagKey property to render an <a> element instead of the default <span> element rendered by the WebControl class.

Imports System
Imports System.ComponentModel
Imports System.Security
Imports System.Security.Permissions
Imports System.Web
Imports System.Web.UI
Imports System.Web.UI.WebControls

<Assembly: TagPrefix("Samples.AspNet", "Sample")> 
Namespace Samples.AspNet

    <AspNetHostingPermission( _
    SecurityAction.Demand, _
    Level:=AspNetHostingPermissionLevel.Minimal), _
    AspNetHostingPermission( _
    SecurityAction.InheritanceDemand, _
    Level:=AspNetHostingPermissionLevel.Minimal), _
    ParseChildren(True, "Text"), _
    DefaultProperty("Email"), _
    ToolboxData("<{0}:MailLink ID='MailLinkID' Text='Mail Web Master' runat=""server""> </{0}:MailLink>")> _
    PublicClass MailLink
        Inherits WebControl

        <Browsable(True), Category("Appearance"), _
        DefaultValue("webmaster@contoso.com"), _
        Description("The e-mail address.")> _
        PublicOverridableProperty Email() AsStringGetDim s AsString = CStr(ViewState("Email"))
                If s IsNothingThen s = "webmaster@contoso.com"Return s
            EndGetSet(ByVal value AsString)
                ViewState("Email") = value
            EndSetEndProperty


        <Browsable(True), Category("Appearance"), _
        DefaultValue("Web Master"), _
        Description("The name to display."), _
        Localizable(True), _
        PersistenceMode(PersistenceMode.InnerDefaultProperty)> _
        PublicOverridableProperty [Text]() AsStringGetDim s AsString = CStr(ViewState("Text"))
                If s IsNothingThen s = String.Empty
                Return s
            EndGetSet(ByVal value AsString)
                ViewState("Text") = value
            EndSetEndPropertyProtectedOverridesReadOnlyProperty TagKey() _
        As HtmlTextWriterTag
            GetReturn HtmlTextWriterTag.A
            EndGetEndPropertyProtectedOverridesSub AddAttributesToRender(ByVal writer _
        As HtmlTextWriter)
            MyBase.AddAttributesToRender(writer)
            writer.AddAttribute( _
            HtmlTextWriterAttribute.Href, "mailto:" + Email)

        EndSub 'AddAttributesToRender


        ProtectedOverridesSub RenderContents(ByVal writer _
        As HtmlTextWriter)
            If [Text] = String.Empty Then
                [Text] = Email
            EndIf
            writer.WriteEncodedText([Text])

        EndSub 'RenderContents
    EndClass 'MailLink
EndNamespace
using System;
using System.ComponentModel;
using System.Security;
using System.Security.Permissions;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

[assembly:TagPrefix("Samples.AspNet", "Sample")]
namespace Samples.AspNet
{


    [
        AspNetHostingPermission(SecurityAction.Demand,
        Level = AspNetHostingPermissionLevel.Minimal),
        AspNetHostingPermission(SecurityAction.InheritanceDemand,
        Level = AspNetHostingPermissionLevel.Minimal),
        ParseChildren(true, "Text"),
        DefaultProperty("Email"),
        ToolboxData("<{0}:MailLink ID='MailLinkID' Text='Mail Web Master' runat=\"server\"> </{0}:MailLink>")
    ]
    publicclass MailLink : WebControl
    {
        [
            Browsable(true),
            Category("Appearance"),
            DefaultValue("webmaster@contoso.com"),
            Description("The e-mail address.")
        ]
        publicvirtualstring Email
        {
            get
            {
                string s = (string)ViewState["Email"];
                return (s == null) ? "webmaster@contoso.com" : s;
            }
            set
            {
                ViewState["Email"] = value;
            }
        }

        [
            Browsable(true),
            Category("Appearance"),
            DefaultValue("Web Master"),
            Description("The name to display."),
            Localizable(true),
            PersistenceMode(PersistenceMode.InnerDefaultProperty)
        ]
        publicvirtualstring Text
        {
            get
            {
                string s = (string)ViewState["Text"];
                return (s == null) ? String.Empty : s;
            }
            set
            {
                ViewState["Text"] = value;
            }
        }

        protectedoverride HtmlTextWriterTag TagKey
        {
            get
            {
                return HtmlTextWriterTag.A;
            }
        }

        protectedoverridevoid AddAttributesToRender(
            HtmlTextWriter writer)
        {
            base.AddAttributesToRender(writer);
            writer.AddAttribute(HtmlTextWriterAttribute.Href,
                "mailto:" + Email);
        }

        protectedoverridevoid RenderContents(HtmlTextWriter writer)
        {
            if (Text == String.Empty)
            {
                Text = Email;
            }
            writer.WriteEncodedText(Text);
        }
    }
}

The MailLink control also demonstrates inner text persistence. MailLink enables a page developer to specify the Text property within the control's tags, as shown in the following example.

<Sample:MailLink id="MaillinkID" Email="Webmaster@contoso.com" 
    runat="server">
 Mail Support Team
</Sample:MailLink>

Inner persistence is in contrast to default persistence on the control's opening tag, as in the following example.

<Sample:MailLink Text="Mail Webmaster" runat="server" > </Sample:MailLink>

The preceding code is the default tag generated for the control when it is dragged from the Toolbox into a page.

Compiling the Code

In Visual Studio, create a library project and define a custom class that derives from WebControl, as shown in the procedure above. The complete source code is listed in the previous code section.

Security

Custom server controls extend the functionality of ASP.NET and must follow some precise security guidelines. In particular, you need to consider the following:

  • Run-time and design-time security.

  • Custom controls in strong-named assemblies.

  • Operating system security and access control lists (ACLs) on the server that hosts the custom server control.

  • Code access security to restrict the resources the control can access.

  • Managed assemblies in the global assembly cache.

See Also

Concepts

Design-Time Attributes for Components

Attributes and Design-Time Support

Securing Custom Server Controls

Other Resources

Developing Custom ASP.NET Server Controls