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
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. } }
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>")]
Compile the MailLink control in a library and name it MaiLink.Dll.
To add the custom control to the Toolbox
On the View menu, click Toolbox.
In the Toolbox, right-click and select Choose Items.
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.
Select the check box for the MailLink control and click OK.
The custom MailLink control appears in the Toolbox.
To reference the MailLink control in a page
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#" %>
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>
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.
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