
Introduction
This is the fifth in a series of six articles, following the design, development and practical use of a fully functional ASP.NET custom control.
The full list of articles is as follows:
These articles are not intended to be a comprehensive look at custom control development (there are 700+ page books that barely cover it), but they do cover a significant number of fundamentals, some of which are poorly documented elsewhere.
The intent is to do so in the context of a single fully reusable and customizable control (as opposed to many contrived examples) with some awareness that few people will want many parts of the overall article but many people will want few parts of it.
This article looks at a couple of simple Web Forms which implement the NoSpamEmailHyperlink
control. It is intended for people who have written web forms using standard .NET Framework controls but not using custom controls.
It assumes at least a basic knowledge of ASP.NET web forms.
Downloads are available from the first article in the series.
Using the NoSpamEmailHyperlink
Readers who use WYSIWYG designers with drag-and-drop functionality, such as Visual Studio .NET, can add the control to the toolbox simply by right-clicking the toolbox, selecting Add/Remove Items..., clicking the Browse button and then browsing to the downloaded DLL.
The rest of the work is done for you when you drag the control onto a page.
The examples described below are specifically designed to appeal to readers with or without visual designers.
Example 1: Static Data
Including the NoSpamEmailHyperlink
in a page is as simple as including any other custom control. Simply register the assembly and then include the tag. Remember that you can use any of the standard formatting properties provided by the WebControl
class.
<%@ Page %>
<%@ Register TagPrefix="cpspam" Namespace="CP.WebControls"
Assembly="CP.WebControls.NoSpamEmailHyperlink" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
<html>
<head>
<title>NoSpamEmailHyperlink Example 1</title>
</head>
<body>
<form id="myForm" method="post" runat="server">
<cpspam:NoSpamEmailHyperlink id="NoSpamEmailHyperlink1"
runat="server" Email="pdriley@santt.com"
ScrambleSeed="181" BackColor="#E0E0E0"
Font-Bold="True">
Paul Riley (pdriley@santt.com)
</cpspam:NoSpamEmailHyperlink>
</form>
</body>
</html>
This generates the following HTML:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
<html>
<head>
<title>NoSpamEmailHyperlink Example 1</title>
</head>
<body>
<form name="myForm" method="post" action="nsehex01.aspx" id="Form1">
<input type="hidden" name="__VIEWSTATE"
value="dDwyMDU4NTgyNDA1Ozs+8SYFCkNptnxci/WjgtV6u5nwN1c=" />
<a id="NoSpamEmailHyperlink1" href="mailto:WsyhiJc@7kDit.com"
style="background-color:#E0E0E0;font-weight:bold;">
Paul Riley (WsyhiJc@7kDit.com)
</a>
<!--
<script language="javascript">
<!--
var NoSpamEmailHyperlink_LinkNames = new Array("NoSpamEmailHyperlink1");
var NoSpamEmailHyperlink_Seeded = new Array("181");
</script>
<!--
<!--
</html>
The email address pdriley@santt.com does not appear anywhere in the HTML, but there is a perfectly valid (but fake) email address for the benefit of any email harvesters trawling through our site.

The control JavaScript is examined in detail in an earlier article: NoSpamEmailHyperlink: 3. Email Encoding and Decoding.
For the purposes of this article, suffice to say that the code is designed to use the arrays shown above to identify those links created by the NoSpamEmailHyperlink
and decode the email address wherever it appears in each link.
Example 2: DataBinding
It is no more difficult to bind a NoSpamEmailHyperlink
into a DataGrid
or DataList
. Registration is implemented in exactly the same way as for Example 1. The control itself is included as part of an ItemTemplate
, for example:
<asp:datagrid id="DataGrid1" runat="server" AutoGenerateColumns="False"
CellPadding="2" CellSpacing="3">
<AlternatingItemStyle BackColor="#E0E0E0" />
<HeaderStyle BackColor="#FFC080" />
<Columns>
<asp:BoundColumn DataField="ID" HeaderText="ID">
<HeaderStyle Width="30px" HorizontalAlign="Right" />
<ItemStyle HorizontalAlign="Right" />
</asp:BoundColumn>
<asp:TemplateColumn>
<HeaderStyle Width="100px" />
<HeaderTemplate>
Person
</HeaderTemplate>
<ItemTemplate>
<cpspam:NoSpamEmailHyperlink id="nseh" runat="server"
Email='<%# DataBinder.Eval(Container.DataItem, "Email") %>'
ScrambleSeed='<%# DataBinder.Eval(Container.DataItem, "ID") %>'>
<%# DataBinder.Eval(Container.DataItem, "Name") %>
(<%# DataBinder.Eval(Container.DataItem, "Email") %>)
</cpspam:NoSpamEmailHyperlink>
</ItemTemplate>
</asp:TemplateColumn>
</Columns>
</asp:datagrid>

Any property in the control can be DataBound using standard databinding blocks, as above. Only the .Text
inner property can include multiple data blocks; all others must be entirely populated by one data block.
The control defined above will appear in a designer such as Visual Studio .NET as a link with text "Databound", as shown to the right.
Try the above example, using the following code, either as "code-behind" or an inline <script runat="server">
block, to build a bindable ArrayList
.
private void Page_Load(object sender, System.EventArgs e)
{
ArrayList list = new ArrayList();
list.Add(new Person(1, "Paul Riley", "pdriley@santt.com"));
list.Add(new Person(2, "David Duncan-Smythe", "david@duncan-smythe.com"));
list.Add(new Person(3, "Jim Jones", "jim_jones@britdomain.co.uk"));
DataGrid1.DataSource = list;
if (!IsPostBack) this.DataBind();
}
public class Person
{
private int _id = 0;
private string _name = "";
private string _email = "";
public Person (int NewID, string NewName, string NewEmail) : base()
{
_id = NewID;
_name = NewName;
_email = NewEmail;
}
public int ID {
get { return _id; }
set { _id = value; }
}
public string Name {
get { return _name; }
set { _name = value; }
}
public string Email {
get { return _email; }
set { _email = value; }
}
}

As you can see above, the visible page is exactly as you would expect it to appear. But the HTML source (shown in the Notepad window behind the browser) does not contain any of the addresses directly. Only the extensions are retained, to keep the addresses valid.
The JavaScript required to decode several links is not much longer than that required to decode one. The only difference between the JavaScript here and that in Example 1 is the array definitions.
<script language="javascript">
<!--
var NoSpamEmailHyperlink_LinkNames = new Array(
"DataGrid1__ctl2_nseh", "DataGrid1__ctl3_nseh", "DataGrid1__ctl4_nseh");
var NoSpamEmailHyperlink_Seeded = new Array("1", "2", "3");
</script>
Note that the links still have unique IDs, despite only having been declared once, thanks to the DataGrid
control implementing the INamingContainer
interface.
First it takes the name of the DataGrid
(DataGrid1
), then the name of the row (_ctl#
) and finally the name of the NoSpamEmailHyperlink
(nseh
), joining them with underscores to make DataGrid1__ctl#_nseh
.
Conclusion
The NoSpamEmailHyperlink
is easy to implement, whether you use a WYSIWYG designer with drag-and-drop operations or simply code by hand.
Once registered with a page or user control, the NoSpamEmailHyperlink
is really no different from including a normal hyperlink control. All the encoding is handled by the control class at the server and all decoding is handled by JavaScript transmitted along with the control.
The only thing left that we may want to do is to customize the control and further confuse any email harvester that gets wise to our scheme. This is covered in the final article of the series: NoSpamEmailHyperlink: 6. Customization.