<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" media="screen" href="/styles/xslt/rss.xslt"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:media="http://search.yahoo.com/mrss/" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" xmlns:c9="http://channel9.msdn.com">
<channel>
	<title>Channel 9</title>
    <atom:link rel="self" type="application/rss+xml" href="http://channel9.msdn.com/Niners/c4f.Stephen-Walther/Posts/RSS"></atom:link>
    <itunes:summary></itunes:summary>
    <itunes:author>Microsoft</itunes:author>
    <itunes:subtitle></itunes:subtitle>
    <image>
      <url>http://mschnlnine.vo.llnwd.net/d1/Dev/App_Themes/C9/images/feedimage.png</url>
      <title>Channel 9</title>
      <link>http://channel9.msdn.com/Niners/c4f.Stephen-Walther/Posts</link>
    </image>
    <itunes:image href=""></itunes:image>
    <itunes:category text="Technology"></itunes:category>
    <description>Channel 9 keeps you up to date with the latest news and behind the scenes info from Microsoft that developers love to keep up with. From LINQ to SilverLight – Watch videos and hear about all the cool technologies coming and the people behind them.</description>
    <link>http://channel9.msdn.com/Niners/c4f.Stephen-Walther/Posts</link>
    <language>en</language>
    <pubDate>Tue, 21 May 2013 14:53:48 GMT</pubDate>
    <lastBuildDate>Tue, 21 May 2013 14:53:48 GMT</lastBuildDate>
    <generator>Rev9</generator>
    <c9:totalResults>5</c9:totalResults>
    <c9:pageCount>1</c9:pageCount>
    <c9:pageSize>25</c9:pageSize>
  <item>
      <title>Who Is Looking: Building a Custom ASP.NET Control that uses Javascript, Cascading Style Sheets, and Ajax</title>
      <description><![CDATA[<span id="c4fmetadata">
<table cellspacing="0" cellpadding="1" width="100%" border="0">
<tbody>
<tr class="entry_overview">
<td width="50">&nbsp;</td>
<td><span class="entry_description">In this article, Stephen Walther shows you how to create a custom ASP.NET control that uses Javascript, Cascading Style Sheets, and Ajax to display a list of people who are looking at a web page in real time. You learn how
 to create the WhoIsLooking control.</span></td>
</tr>
<tr>
<td colspan="2">
<div class="entry_author">Stephen Walther</div>
<div class="entry_company"><a href="http://superexpert.com">Steve's Blog</a></div>
<br>
<div class="entry_details"><b>Difficulty: </b><span class="entry_details_input">Advanced</span></div>
<div class="entry_details"><b>Time Required:</b> <span class="entry_details_input">
Less than 1 hour</span></div>
<div class="entry_details"><b>Cost: </b><span class="entry_details_input">Free</span></div>
<div class="entry_details"><b>Software: </b><span class="entry_details_input"><a href="http://msdn.com/express/">Visual Web Developer Express</a>
<a href="http://msdn.com/express/">Visual Basic or Visual C# Express Editions</a>,</span></div>
<div class="entry_details"><b>Hardware: </b><span class="entry_details_input"></span></div>
<div class="entry_details"><b>Download: </b><a href="http://channel9.msdn.com/ShowPost.aspx?PostID=305671">Download</a>
<ul>
</ul>
</div>
</td>
</tr>
</tbody>
</table>
</span>
<p>I want to know who is looking at my websites. Don't get me wrong -- I'm not paranoid, I'm just curious (and maybe a little vain). After I have undergone all of the pain and effort of building a web page, I want to know that someone is actually looking at
 it. </p>
<p>Yes, yes -- I know about website statistics programs. But that is not what I want. I want to know who is visiting a web page right now in real time. Furthermore, I want to share this information with anyone else&nbsp;who is visiting the web page.
</p>
<p>This month, we build a custom ASP.NET 2.0 control that displays a list of everyone who is currently looking at a particular web page (see Figure 1). The list rendered by the control is updated, in real time, using Javascript and Ajax. People pop in and out
 of the list as they visit and leave the web page. We create a control named the WhoIsLooking control.
</p>
<p><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/2429765/clip_image0025.gif"><img height="318" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/2429765/clip_image002_thumb.gif" width="334"></a>
</p>
<p><b>Figure 1 - The WhoIsLooking control</b> </p>
<p>The WhoIsLooking control is a complicated control. To get it to work, I had to take advantage of a number of advanced control building techniques. Therefore, this post is divided into several parts.
</p>
<p>In the first part, I describe how you create custom controls for the ASP.NET 2.0 framework. After getting the basics out of the way, I explain how you can embed Javascript and Cascading Style Sheets in a custom control. Then, we explore the very trendy topic
 of Ajax. Finally, I discuss how you can grab information about the users viewing a web page.
</p>
<p>If you want to play with the control right now, you can go ahead and click the download link at the top of this article to download all of the control source code (There is both a C# and VB.NET version of the source code). The download package also includes
 a test ASP.NET website that you can use to try out the control. When&nbsp;testing the control, open up multiple types of browsers and point them to the same page (If you open up multiple instances of Microsoft Internet Explorer, you'll see only one instance of
 the browser listed by the WhoIsLooking control since all instances of the same browser share the same set of cookies).
</p>
<h3>Creating Custom ASP.NET 2.0 Controls</h3>
<p>All the ASP.NET 2.0 controls that you find in the Visual Studio toolbox, such as the GridView, TextBox, and TreeView controls, were created as custom controls. If you ever get bored of the standard controls, you always have the option of building new ones.
</p>
<p>An ASP.NET control -- like just about everything else in the .NET framework -- is a class. Typically, a custom control is a class that derives from the WebControl class. Creating a custom control generally involves completing the following three steps:
</p>
<p>(1) Add a new class to your website's App_Code folder </p>
<p>(2) Modify the class so that it derives from the base WebControl class </p>
<p>(3) Override the base WebControl class's RenderContents() method </p>
<p>One of my favorite new features of ASP.NET 2.0 is the magic App_Code folder. If you add the source code for a class to this special folder, the class gets compiled automatically. Since ASP.NET controls are just a type of class, this means that you can create
 a new ASP.NET control simply by adding the source for the control to the App_Code folder.
</p>
<p>When you create a custom control, you typically derive the control from the base WebControl class (found in the System.Web.UI.WebControls namespace) and override the base class's RenderContents() method.
</p>
<p>At its most basic level, a control is simply a class that renders content to a Web browser. In the RenderContents() method, you output the content that you want to send to the browser.
</p>
<p>For example, Listing 1 contains the simplest control that I can imagine -- a Hello World control. This control renders the text “Hello World”.
</p>
<p><b>Listing 1 -- HelloWorld.cs</b></p>
<pre class="csharpcode"><span class="kwrd">using</span> System;

<span class="kwrd">using</span> System.Web.UI;

<span class="kwrd">using</span> System.Web.UI.WebControls;

<span class="kwrd">namespace</span> myControls

{

<span class="kwrd">  public</span> <span class="kwrd">class</span> HelloWorld : WebControl

  {

<span class="kwrd">    protected</span> <span class="kwrd">override</span> <span class="kwrd">void</span> RenderContents(HtmlTextWriter writer)

    {

      writer.Write(<span class="str">&quot;Hello World&quot;</span>);

    }

  }

}

</pre>
<style type="text/css">
<!--
.csharpcode, .csharpcode 
	{font-size:small;
	color:black;
	font-family:consolas,"Courier New",courier,monospace;
	background-color:#ffffff}
.csharpcode 
	{margin:0em}
.csharpcode .rem
	{color:#008000}
.csharpcode .kwrd
	{color:#0000ff}
.csharpcode .str
	{color:#006080}
.csharpcode .op
	{color:#0000c0}
.csharpcode .preproc
	{color:#cc6633}
.csharpcode .asp
	{background-color:#ffff00}
.csharpcode .html
	{color:#800000}
.csharpcode .attr
	{color:#ff0000}
.csharpcode .alt
	{background-color:#f4f4f4;
	width:100%;
	margin:0em}
.csharpcode .lnum
	{color:#606060}
-->
</style>
<p><b>Listing 1 -- HelloWorld.vb</b> </p>
<p>&nbsp;</p>
<pre class="csharpcode"><span class="kwrd">Imports</span> System

<span class="kwrd">Imports</span> System.Web.UI

<span class="kwrd">Imports</span> System.Web.UI.WebControls

<span class="kwrd">Namespace</span> myControls

<span class="kwrd">  Public</span> <span class="kwrd">Class</span> HelloWorld

<span class="kwrd">    Inherits</span> WebControl

<span class="kwrd">    Protected</span> <span class="kwrd">Overrides</span> <span class="kwrd">Sub</span> RenderContents(<span class="kwrd">ByVal</span> writer <span class="kwrd">As</span> HtmlTextWriter)

      writer.Write(<span class="str">&quot;Hello World&quot;</span>)

<span class="kwrd">    End</span> <span class="kwrd">Sub</span>

<span class="kwrd">  End</span> <span class="kwrd">Class</span>

<span class="kwrd">End</span> <span class="kwrd">Namespace</span>

</pre>
<style type="text/css">
<!--
.csharpcode, .csharpcode 
	{font-size:small;
	color:black;
	font-family:consolas,"Courier New",courier,monospace;
	background-color:#ffffff}
.csharpcode 
	{margin:0em}
.csharpcode .rem
	{color:#008000}
.csharpcode .kwrd
	{color:#0000ff}
.csharpcode .str
	{color:#006080}
.csharpcode .op
	{color:#0000c0}
.csharpcode .preproc
	{color:#cc6633}
.csharpcode .asp
	{background-color:#ffff00}
.csharpcode .html
	{color:#800000}
.csharpcode .attr
	{color:#ff0000}
.csharpcode .alt
	{background-color:#f4f4f4;
	width:100%;
	margin:0em}
.csharpcode .lnum
	{color:#606060}
-->
</style>
<p>After you create a new custom control, you can add it to a page in one of three ways. The first option is to register the control in a particular page. For example, you can register the HelloWorld control in a page by adding the following directive to the
 page: </p>
<p>&nbsp; &lt;%@ Register TagPrefix=&quot;custom&quot; Namespace=&quot;myControls&quot; %&gt; </p>
<p>The value of the TagPrefix attribute can be anything you want. The value of the Namespace attribute must match the namespace that you declared in the source code for the custom control.
</p>
<p>After you register to a control for a page, you can declare the control with a tag that looks like this:
</p>
<p>&nbsp; &lt;custom:HelloWorld ID=&quot;HelloWorld1&quot; runat=&quot;server&quot; /&gt; </p>
<p>Another option is to register the control in your website's configuration file. This is a new option in ASP.NET 2.0. If you want to register a control so that it can be used by all pages in an application, then you can add the following &lt;pages&gt; element to
 your Web.Config file: </p>
<p>&lt;pages&gt; </p>
<p>&nbsp; &lt;controls&gt; </p>
<p>&nbsp;&nbsp;&nbsp; &lt;add tagPrefix=&quot;custom&quot; namespace=&quot;myControls&quot;/&gt; </p>
<p>&nbsp; &lt;/controls&gt; </p>
<p>&lt;/pages&gt; </p>
<p>I tend to use this second option the most often when incorporating custom controls into my applications.
</p>
<p>Finally, you can add a custom control to the Visual Studio (or Visual Web Developer) Toolbox. If you add a control to the Toolbox, then you can add the control to a page simply by dragging the control from the Toolbox onto the page.
</p>
<p>Unfortunately, you cannot take advantage of this last option when creating custom controls in the App_Code folder. You can add a custom control to the Toolbox only when the control has been compiled into a separate assembly. When we create the WhoIsLooking
 control later in this article, we will create the control as a separate assembly.
</p>
<p>You add a control to the Toolbox by right-clicking the Toolbox window and selecting the menu option Choose Items. Selecting this menu item will open a dialog box that enables you to browse to an assembly (Click the Browse button). After you select the assembly
 that contains the custom control, the control will appear in your Toolbox. </p>
<h3>Embedding Javascript</h3>
<p>Our control is going to do something much more interesting than merely render some HTML to the browser. Our control is going to inject Javascript and CSS into its containing page.
</p>
<p>There is one main class in the ASP.NET Framework included for working with Javascript: the ClientScriptManager class. This class is exposed by the Page.ClientScript property. The ClientScriptManager class has several useful methods for working with Javascript
 including: </p>
<ul>
<li>RegisterClientScriptBlock() - Adds a script to a page right after the opening server-side &lt;form&gt; tag
</li><li>RegisterStartupScript() - Adds a script to a page right before the closing server-side &lt;form&gt; tag
</li><li>RegisterClientScriptInclude() - Adds a reference to an external Javascript file
</li><li>GetWebResourceUrl() - Returns the URL to a server-side resource </li></ul>
<p>The RegisterClientScriptBlock and RegisterStartupScript methods enable you to add inline Javascript scripts to a page. If you have a little snippet of Javascript that you need to add to a page, then these are great methods to use. However, if you need to
 work with a more complex Javascript script, as we will need to do, then you should use either the RegisterClientScriptInclude() or GetWebResourceUrl() method.
</p>
<p>The RegisterClientScriptInclude() method adds a tag that looks like this to your page:
</p>
<p>&nbsp; &lt;script type=&quot;text/Javascript&quot; src=&quot;SomeScript.js&quot;&gt;&lt;/script&gt; </p>
<p>The method simply adds a reference to an external Javascript file (you supply the method with the path to the Javascript file that you want to include).
</p>
<p>The disadvantage of using the RegisterClientScriptInclude() method is that it requires you to distribute a separate Javascript file (or files) with your custom control. In order for people to use your control, they need to add the necessary Javascript files
 to their projects in the right locations. </p>
<p>A better alternative is to take advantage of the GetWebResourceUrl() method. You can embed a Javascript file (or any other type of resource) directly into your custom control. Using the GetWebResourceUrl() method, you can get the URL that you need to retrieve
 the embedded Javascript file from your control. In other words, by taking advantage of the GetWebResourceUrl() method, you can distribute a single assembly (.dll file) that contains both your custom control and Javascript files.
</p>
<p>The tricky part is embedding the resource (the Javascript file) in the assembly. Unfortunately, you cannot embed a resource into an assembly when you create a control in the App_Code folder. You need to create the control in a separate project. For this
 reason, I created the custom WhoIsLooking control in a separate Class Library project.
</p>
<p>You cannot create a Class Library project with Visual Web Developer. If you want to create a Class Library project, you either need to use the full version of Visual Studio 2005 or you need to download either Microsoft Visual C# 2005 Express Edition or Microsoft
 Visual Basic 2005 Express Edition from the Microsoft website (The download that accompanies this article includes both a Visual C# Express and Visual VB.NET Express Class Library project that contains the source code for the WhoIsLooking control).
</p>
<p><em>Note: When creating custom controls in a Class Library project, you need to add a reference to the System.Web.dll assembly. Select Project, Add Reference and select the System.Web assembly from beneath the .NET tab.</em>
</p>
<p>Within Visual C# Express or Visual VB.NET Express, you can embed any file as a resource into an assembly by selecting the file in the Solution Explorer window, opening the Properties window, and changing the Build Action property for the file to the value
 Embedded Resource. </p>
<p>Next, you need to add a WebResource attribute to the AssemblyInfo file for each embedded resource. When working with Microsoft Visual Basic 2005 Express Edition, select the menu option Project, Show All Files and expand the My Project folder in the Solution
 Explorer window to view the AssemblyInfo file. When working with Microsoft C# 2005 Express Edition, expand the Properties folder to view the AssemblyInfo file. You need to add the following attribute to embed an image resource named MyImage.gif:
</p>
<p><b>VB.NET</b> </p>
<p>&lt;Assembly: WebResource(&quot;ProjectNamespace.MyImage.gif&quot;, &quot;image/gif&quot;)&gt; </p>
<p><b>C#</b> </p>
<p>[Assembly: WebResource(&quot;ProjectNamespace.MyImage.gif&quot;, &quot;image/gif&quot;)] </p>
<p>By default, the ProjectNamespace will be the same as your project name. In the case of the WhoIsLooking project, the project namespace is WhoIsLooking. You can view the default namespace for your project by right-clicking on the name of your project in the
 Solution Explorer window and selecting Properties. </p>
<p>The WhoIsLooking control adds a reference to Javascript file in its OnPreRender() method. The OnPreRender() method includes the following two lines of code:
</p>
<p><b>C#</b> </p>
<p>// Add Javascript include </p>
<p>string scriptUrl = Page.ClientScript.GetWebResourceUrl( this.GetType(), </p>
<p>&quot;WhoIsLooking.WhoIsLooking.js&quot;); </p>
<p>Page.ClientScript.RegisterClientScriptInclude(&quot;WhoIsLooking&quot;, scriptUrl); </p>
<p><b>VB.NET</b> </p>
<p>' Add Javascript include </p>
<p>Dim scriptUrl As String = Page.ClientScript.GetWebResourceUrl(Me.GetType(), &quot;WhoIsLooking.WhoIsLooking.js&quot;)
</p>
<p>Page.ClientScript.RegisterClientScriptInclude(&quot;WhoIsLooking&quot;, scriptUrl) </p>
<h3>Embedding Cascading Style Sheets</h3>
<p>You can use the same technique that we used to embed Javascript into our custom control to embed a Cascading Style Sheet. The WhoIsLooking control takes advantage of a Cascading Style Sheet to format the appearance of the control.
</p>
<p>If you select the WhoIsLooking.css file in the Solution Explorer window and view the properties for the file, then you will see that the Build Action for the file is set to the value Embedded Resource.
</p>
<p>Furthermore, the WhoIsLooking project includes the following attribute in its AssemblyInfo file:
</p>
<p><b>VB.NET</b> </p>
<p>&nbsp; &lt;Assembly: WebResource(&quot;WhoIsLooking.WhoIsLooking.css&quot;, &quot;text/css&quot;)&gt; </p>
<p><b>C#</b> </p>
<p>&nbsp; [Assembly: WebResource(&quot;WhoIsLooking.WhoIsLooking.css&quot;, &quot;text/css&quot;)] </p>
<p>Finally, the WhoIsLooking control includes the following lines of code in its OnPreRender() method:
</p>
<p><b>VB.NET</b> </p>
<p>' Add style sheet to parent page </p>
<p>Dim cssUrl As String = Page.ClientScript.GetWebResourceUrl(Me.GetType(), &quot;WhoIsLooking.WhoIsLooking.css&quot;)
</p>
<p>Dim cssLink As New HtmlLink() </p>
<p>cssLink.Href = cssUrl </p>
<p>cssLink.Attributes.Add(&quot;rel&quot;, &quot;stylesheet&quot;) </p>
<p>cssLink.Attributes.Add(&quot;type&quot;, &quot;text/css&quot;) </p>
<p>Page.Header.Controls.Add(cssLink) </p>
<p>' Add class name </p>
<p>Me.CssClass = &quot;WhoIsLooking&quot; </p>
<p><b>C#</b> </p>
<p>// Add style sheet to parent page </p>
<p>string cssUrl = Page.ClientScript.GetWebResourceUrl(this.GetType(), </p>
<p>&quot;WhoIsLooking.WhoIsLooking.css&quot;); </p>
<p>HtmlLink cssLink = new HtmlLink(); </p>
<p>cssLink.Href = cssUrl; </p>
<p>cssLink.Attributes.Add(&quot;rel&quot;, &quot;stylesheet&quot;); </p>
<p>cssLink.Attributes.Add(&quot;type&quot;, &quot;text/css&quot;); </p>
<p>this.Page.Header.Controls.Add(cssLink); </p>
<p>// Add class name </p>
<p>this.CssClass = &quot;WhoIsLooking&quot;; </p>
<p>This code grabs a reference to the external Cascading Style Sheet file by taking advantage of the GetWebResourceUrl() method. Next, an HtmlLink control is created and added to the header for the page. This control renders the following HTML:
</p>
<p>&lt;link href=&quot;/TestSite/WebResource.axd?d=Zyww-wIBakY8NHKUtjeDQZr5yvS_5HEj1E2zyc2CVX9Hyb34lNTSxDhkIp1IsJrd0&amp;amp;t=504910944000000000&quot; rel=&quot;stylesheet&quot; type=&quot;text/css&quot; /&gt;
</p>
<p>Notice that the link refers to a strange file named WebResource.axd. Resources are exposed to the client-side through an HTTP handler named WebResource.axd. The link contains a long key that uniquely identifies the resource to retrieve.
</p>
<p>Finally, the code associates the WhoIsLooking control with the WhoIsLooking Cascading Style Sheet class. Any style rules for the WhoIsLooking class are applied to the WhoIsLooking control automatically.
</p>
<p>Using an external Cascading Style Sheet to format a control is great way to style a control when you need to provide a lot of default formatting. You can use the handy Style Sheet editor included in Visual Studio to build up a fancy Style Sheet and then
 embed it in your control. </p>
<h3>Using Ajax</h3>
<p>The WhoIsLooking control takes advantage of Ajax to display who is visiting a particular web page in real time. The control polls the server (by default, every 5 seconds) to retrieve a list of the people currently visiting the page.
</p>
<p>Ajax stands for Asynchronous Javascript and XML. Ajax enables you to send information back and forth between a web browser and a web server without posting the page back to the web server. Communication happens behind the scenes.
</p>
<p>The WhoIsLooking control takes advantage of the Ajax support built into the ASP.NET 2.0 Framework. In the ASP.NET 2.0 Framework, Ajax is called client callbacks. I'm going to continue to refer to the technology as Ajax instead of client callbacks because
 no one refers to the technology as client callbacks. </p>
<p>Implementing Ajax in a custom control requires you to complete three steps: </p>
<p>(1) Use the GetCallbackEventReference() method to initiate an Ajax call from the browser to the web server
</p>
<p>(2) Implement the ICallBackEventHandler interface to respond to the Ajax call on the server-side. This interface has two methods that you must implement: the RaiseCallbackEvent() and GetCallbackResult methods.
</p>
<p>(3) Create a Javascript function that does something with the result returned by the server
</p>
<p>The WhoIsLooking control initiates an Ajax call every 5 seconds. The control includes the following code in its OnPreRender() method:
</p>
<p><b>C#</b> </p>
<p>// Add polling call </p>
<p>string callback = Page.ClientScript.GetCallbackEventReference </p>
<p>( </p>
<p>this, </p>
<p>null, </p>
<p>&quot;WhoIsLooking.UpdateDisplay&quot;, </p>
<p>String.Format(&quot;'{0}'&quot;, this.ClientID), </p>
<p>&quot;WhoIsLooking.CallbackError&quot;, </p>
<p>true); </p>
<p>string startupScript = String.Format(&quot;setInterval( \&quot;{0}\&quot;, {1} );&quot;, callback, _PollingInterval * 1000);
</p>
<p>Page.ClientScript.RegisterStartupScript(this.GetType(), &quot;WhoIsLooking&quot;, startupScript, true);
</p>
<p><b>VB.NET</b> </p>
<p>' Add polling call </p>
<p>Dim callback As String = Page.ClientScript.GetCallbackEventReference( _ </p>
<p>Me, _ </p>
<p>Nothing, _ </p>
<p>&quot;WhoIsLooking.UpdateDisplay&quot;, _ </p>
<p>String.Format(&quot;'{0}'&quot;, Me.ClientID), _ </p>
<p>&quot;WhoIsLooking.CallbackError&quot;, _ </p>
<p>True) </p>
<p>Dim startupScript As String = String.Format(&quot;setInterval( &quot;&quot;{0}&quot;&quot;, {1} );&quot;, callback, _PollingInterval * 1000)
</p>
<p>Page.ClientScript.RegisterStartupScript(Me.GetType(), &quot;WhoIsLooking&quot;, startupScript, True)
</p>
<p>In the first line of code, the GetCallbackEventReference() method is used to get the snippet of Javascript necessary for initiating the Ajax call. Next, the Javascript window.setInterval method is used to initiate the Ajax call whenever a particular interval
 of time passes (the default polling interval is 5 seconds). Finally, the RegisterStartupScript() method is used to add the Javascript to the page.
</p>
<p>The WhoIsLooking control implements the ICallbackEventHandler interface. The control includes both a RaiseCallbackEvent() and GetCallbackResult() method. The RaiseCallbackEvent() method adds the current user to the list of users viewing the page. The method
 also removes users who have not viewed the page for more than 10 seconds (twice the polling interval).
</p>
<p>The GetCallbackResult() method returns a list of users viewing the page back to the browser. The following information is returned for each user:
</p>
<ul>
<li>userId - Unique id for each user (the Session ID) </li><li>userName - The authenticated user name (otherwise, the value “anonymous”) </li><li>duration - The amount of time (in minutes) that the user has visited the page
</li><li>browser - The type and version of the user's browser </li><li>remoteHost - The domain name of the user's host </li><li>platform - The operating system used by the remote browser </li></ul>
<p>This method returns a string that represents a JSON array of users. JSON is the standard format for serializing information in an Ajax call (to learn more about JSON, visit JSON.org). For example, if there were two users visiting the page, the JSON string
 would look something like this: </p>
<p>[{userId:&quot;fooglm45cjcycw55qi4yluvk&quot;,userName:&quot;SUPEREXPERT\\Steve&quot;, duration:&quot;0 minute(s)&quot;, browser: &quot;IE 7.0&quot;, remoteHost: &quot;superexpert.com&quot;, platform: &quot;WinXP&quot;},{userId:&quot;1kqatn55sxc4vi55ummxghil&quot;,userName:&quot;SUPEREXPERT\\Bill&quot;, duration:&quot;0 minute(s)&quot;, browser:
 &quot;Firefox 1.5.0.11&quot;, remoteHost: &quot;superexpert.com&quot;, platform: &quot;WinXP&quot;}] </p>
<p>You create a JSON array by creating a comma-separated list of values enclosed in brackets. You create a JSON object by create a comma-separated list of name/value pairs enclosed in curly braces. That's pretty much it for the JSON standard (it's much leaner
 and easier to use than XML). </p>
<p>Finally, the WhoIsLooking control uses a Javascript function named UpdateDisplay() to display the list of users in the browser. This function creates a &lt;div&gt; tag for each user. When you hover your mouse over a &lt;div&gt; tag, details for the user popup (see Figure
 2). </p>
<p><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/2429765/clip_image0045.gif"><img height="313" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/2429765/clip_image004_thumb.gif" width="336"></a>
</p>
<p><b>Figure 2 - Viewing the WhoIsLooking control</b> </p>
<h4>Retrieving User Information</h4>
<p>Most of the information that the WhoIsLooking control retrieves for each user is retrieved with the help of the HttpBrowserCapabilities class (this class is exposed by the Request.Browser property). The HttpBrowserCapabilities class contains a wealth of
 information about the browser being used to visit the page. There are far too many properties to list here, but here is a random selection of some of the more interesting ones:
</p>
<p>• AOL - Returns true if the client is using an AOL browser<br>
• Browser - Returns the type of browser (IE, Firefox, Opera)<br>
• ClrVersion - Returns the version of the .NET Framework installed on the client<br>
• EcmaScriptVersion - Returns the version of Javascript installed on the client<br>
• SupportsCallback - Returns a value indicating whether the browser supports client callbacks (Ajax)<br>
• W3CDomVersion - Returns the version of the DOM (Document Object Model) supported by the browser
</p>
<p>There is one property that the WhoIsLooking control displays that it does not get with the help of the HttpBrowserCapabilities class. The control displays the remote domain name associated with the user requesting the page. The remote domain name is retrieved
 by performing a reverse DNS lookup. In the .NET Framework 2.0, performing a reverse DNS lookup is ridiculously easy. The WhoIsLooking control uses the following code:
</p>
<p><b>C#</b> </p>
<p>// Get remote IP address </p>
<p>_remoteIP = context.Request.UserHostAddress; </p>
<p>// Get host name </p>
<p>_remoteHost = Dns.GetHostEntry(_remoteIP).HostName; </p>
<p><b>VB.NET</b> </p>
<p>' Get remote IP address </p>
<p>_remoteIP = context.Request.UserHostAddress </p>
<p>' Get host name </p>
<p>_remoteHost = Dns.GetHostEntry(_remoteIP).HostName </p>
<h3>Conclusion</h3>
<p>I think the WhoIsLooking control is super cool. The control takes advantage of Javascript and Ajax to display a list of everyone who is looking at a particular Web page in real time. Please feel free to add the control to your websites, I'll come and visit.</p>
 <img src="http://m.webtrends.com/dcs1wotjh10000w0irc493s0e_6x1g/njs.gif?dcssip=channel9.msdn.com&dcsuri=http://channel9.msdn.com/Niners/c4f.Stephen-Walther/Posts/RSS&WT.dl=0&WT.entryid=Entry:RSSView:709a411e9be143daa6509e7600d40db2">]]></description>
      <comments>http://channel9.msdn.com/coding4fun/articles/Who-Is-Looking-Building-a-Custom-ASPNET-Control-that-uses-Javascript-Cascading-Style-Sheets-and-Ajax</comments>
      <itunes:summary>



&amp;nbsp;
In this article, Stephen Walther shows you how to create a custom ASP.NET control that uses Javascript, Cascading Style Sheets, and Ajax to display a list of people who are looking at a web page in real time. You learn how
 to create the WhoIsLooking control.



Stephen Walther
Steve&#39;s Blog

Difficulty: Advanced
Time Required: 
Less than 1 hour
Cost: Free
Software: Visual Web Developer Express
Visual Basic or Visual C# Express Editions,
Hardware: 
Download: Download








I want to know who is looking at my websites. Don&#39;t get me wrong -- I&#39;m not paranoid, I&#39;m just curious (and maybe a little vain). After I have undergone all of the pain and effort of building a web page, I want to know that someone is actually looking at
 it.  
Yes, yes -- I know about website statistics programs. But that is not what I want. I want to know who is visiting a web page right now in real time. Furthermore, I want to share this information with anyone else&amp;nbsp;who is visiting the web page.
 
This month, we build a custom ASP.NET 2.0 control that displays a list of everyone who is currently looking at a particular web page (see Figure 1). The list rendered by the control is updated, in real time, using Javascript and Ajax. People pop in and out
 of the list as they visit and leave the web page. We create a control named the WhoIsLooking control.
 

 
Figure 1 - The WhoIsLooking control  
The WhoIsLooking control is a complicated control. To get it to work, I had to take advantage of a number of advanced control building techniques. Therefore, this post is divided into several parts.
 
In the first part, I describe how you create custom controls for the ASP.NET 2.0 framework. After getting the basics out of the way, I explain how you can embed Javascript and Cascading Style Sheets in a custom control. Then, we explore the very trendy topic
 of Ajax. Finally, I discuss how you can grab information about the users viewing a web page.
 
If you want to play with the control rig</itunes:summary>
      <link>http://channel9.msdn.com/coding4fun/articles/Who-Is-Looking-Building-a-Custom-ASPNET-Control-that-uses-Javascript-Cascading-Style-Sheets-and-Ajax</link>
      <pubDate>Sat, 05 May 2007 12:41:09 GMT</pubDate>
      <guid isPermaLink="false">http://channel9.msdn.com/coding4fun/articles/Who-Is-Looking-Building-a-Custom-ASPNET-Control-that-uses-Javascript-Cascading-Style-Sheets-and-Ajax</guid>
      <media:thumbnail url="http://ecn.channel9.msdn.com/o9/c4f/images/2429765_100.jpg" height="75" width="100"></media:thumbnail>
      <media:thumbnail url="http://ecn.channel9.msdn.com/o9/c4f/images/2429765_220.jpg" height="165" width="220"></media:thumbnail>      
      <dc:creator>Stephen Walther</dc:creator>
      <itunes:author>Stephen Walther</itunes:author>
      <slash:comments>15</slash:comments>
      <wfw:commentRss>http://channel9.msdn.com/coding4fun/articles/Who-Is-Looking-Building-a-Custom-ASPNET-Control-that-uses-Javascript-Cascading-Style-Sheets-and-Ajax/RSS</wfw:commentRss>
      <category>Web</category>
      <category>web miscellaneous</category>
    </item>
  <item>
      <title>Creating a Vanity Search Page</title>
      <description><![CDATA[<span id="c4fmetadata">
<table cellspacing="0" cellpadding="1" width="100%" border="0">
<tbody>
<tr class="entry_overview">
<td width="50">&nbsp;</td>
<td><span class="entry_description">It's all about you. Learn how to call the Windows Live Search service to create a vanity page that displays images, news articles, and websites about you.</span></td>
</tr>
<tr>
<td colspan="2">
<div class="entry_author">Stephen Walther</div>
<div class="entry_company"><a href="http://www.superexpert.com">Superexpert Blog</a></div>
<br>
<div class="entry_details"><b>Difficulty: </b><span class="entry_details_input">Easy</span></div>
<div class="entry_details"><b>Time Required:</b> <span class="entry_details_input">
Less than 1 hour</span></div>
<div class="entry_details"><b>Cost: </b><span class="entry_details_input">Free</span></div>
<div class="entry_details"><b>Software: </b><span class="entry_details_input"><a href="http://msdn.microsoft.com/vstudio/express/vwd/">Visual Web Developer 2005 Express Edition</a></span></div>
<ul>
</ul>
<div></div>
</td>
</tr>
</tbody>
</table>
</span>
<p></p>
<p>This month, we create a vanity search page. The vanity search page displays any images, news or website entries about a particular person (for example, you). To create this page, we take advantage of the Windows Live Search API. This free API enables you
 to retrieve search results by calling a web service that Microsoft exposes on the web.
</p>
<p>I decided to write this article because I wanted an excuse to play with the Windows Live SDK (see
<a href="http://dev.live.com/">http://dev.live.com</a>). The SDK includes documentation and samples for accessing all of the Windows Live web services including the Windows Live Search Web Service, Virtual Earth, and Windows Live Alerts.
</p>
<p>I fully admit that I&nbsp;was&nbsp;actively avoiding writing this article because I dreaded the thought of needing to learn yet another Application Programming Interface. I was pleasantly surprised to discover that the API for Windows Live Search is both logical and
 painlessly simple to understand. I wrote the code for this article in less than an hour.
</p>
<p>Before you can access the Windows Live services, you need to get an Application ID. You pass this ID to the Windows Live services to identify yourself. You get an Application ID by signing an agreement at the following URL:
<a href="http://search.msn.com/developer/appids.aspx">http://search.msn.com/developer/appids.aspx</a>.
</p>
<p><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1855817/image08.png"><img height="178" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1855817/image0_thumb4.png" width="240" border="0"></a>
</p>
<p><strong>Figure 1 - Adding a Web Reference for Windows&nbsp;Live Search</strong> </p>
<p>After you have an Application ID, you are ready to start calling Windows Live web services. Here are the steps for creating the vanity search page:
</p>
<p>1. Launch Visual Web Developer and create a new Web Site </p>
<p>2. Select the menu option Website, Add Web Reference to add a Web Reference to the Windows Live Search web service (see Figure 1). Enter the following address into the URL field:
<a href="http://soap.search.msn.com/webservices.asmx?wsdl">http://soap.search.msn.com/webservices.asmx?wsdl</a>. When you click OK, a new Web reference named com.msn.search.soap is created.
</p>
<p>3. Create a new Web Form Page by selecting the menu option Website, Add New Item. When you create the new Web Form Page, give it the name Vanity.aspx. Also, make sure that the checkbox labeled
<b>Place code in separate file</b> is not checked. </p>
<p>4. Replace the contents of the page with the following code: </p>
<p><b>VB.NET Code</b>&nbsp; </p>
<div>
<pre class="csharpcode">&lt;%@ Page Language=<span class="str">&quot;VB&quot;</span> %&gt;

&lt;%@ Import <span class="kwrd">Namespace</span>=<span class="str">&quot;com.msn.search.soap&quot;</span> %&gt;

&lt;%@ Import <span class="kwrd">Namespace</span>=<span class="str">&quot;System.Text.RegularExpressions&quot;</span> %&gt;

&lt;!DOCTYPE html <span class="kwrd">PUBLIC</span> <span class="str">&quot;-//W3C//DTD XHTML 1.0 Transitional//EN&quot;</span> <span class="str">&quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd&quot;</span>&gt;

&lt;script runat=<span class="str">&quot;server&quot;</span>&gt;

<span class="kwrd">Const</span> appId <span class="kwrd">As</span> <span class="kwrd">String</span> = <span class="str">&quot;&quot;</span>

<span class="kwrd">Const</span> query <span class="kwrd">As</span> <span class="kwrd">String</span> = <span class="str">&quot;&quot;</span><span class="str">&quot;Bill Gates&quot;</span><span class="str">&quot;&quot;</span>

<span class="kwrd">Const</span> startMark <span class="kwrd">As</span> <span class="kwrd">String</span> = <span class="str">&quot;\uE000&quot;</span>

<span class="kwrd">Const</span> endMark <span class="kwrd">As</span> <span class="kwrd">String</span> = <span class="str">&quot;\uE001&quot;</span>

<span class="kwrd">Private</span> <span class="kwrd">Sub</span> Page_Load()

<span class="rem">' Create instance of MSN Search Services</span>

<span class="kwrd">Dim</span> search <span class="kwrd">As</span> <span class="kwrd">New</span> MSNSearchService()

<span class="rem">' Build Source Request</span>

<span class="kwrd">Dim</span> NewsSource <span class="kwrd">As</span> <span class="kwrd">New</span> SourceRequest()

NewsSource.Source = SourceType.News

<span class="kwrd">Dim</span> webSource <span class="kwrd">As</span> <span class="kwrd">New</span> SourceRequest()

webSource.Source = SourceType.Web

<span class="kwrd">Dim</span> imageSource <span class="kwrd">As</span> <span class="kwrd">New</span> SourceRequest()

imageSource.Source = SourceType.Image

imageSource.ResultFields = ResultFieldMask.Image <span class="kwrd">Or</span> ResultFieldMask.Url

<span class="rem">' Build the Search Request</span>

<span class="kwrd">Dim</span> request <span class="kwrd">As</span> <span class="kwrd">New</span> SearchRequest()

request.AppID = appId

request.Requests = <span class="kwrd">New</span> SourceRequest() {imageSource, NewsSource, webSource}

request.Query = query

request.CultureInfo = <span class="str">&quot;en-US&quot;</span>

request.Flags = SearchFlags.MarkQueryWords

<span class="rem">' Execute Search</span>

<span class="kwrd">Dim</span> response <span class="kwrd">As</span> SearchResponse = search.Search(request)

lstResponses.DataSource = response.Responses

lstResponses.DataBind()

<span class="kwrd">End</span> <span class="kwrd">Sub</span>

<span class="kwrd">Private</span> <span class="kwrd">Function</span> hiLite(<span class="kwrd">ByVal</span> item <span class="kwrd">As</span> <span class="kwrd">Object</span>) <span class="kwrd">As</span> <span class="kwrd">String</span>

<span class="kwrd">If</span> item <span class="kwrd">Is</span> <span class="kwrd">Nothing</span> <span class="kwrd">Then</span>

<span class="kwrd">Return</span> <span class="kwrd">String</span>.Empty

<span class="kwrd">End</span> <span class="kwrd">If</span>

<span class="kwrd">Dim</span> text <span class="kwrd">As</span> <span class="kwrd">String</span> = item.ToString()

text = Regex.Replace(text, startMark, <span class="str">&quot;&lt;span class='hiLite'&gt;&quot;</span>)

text = Regex.Replace(text, endMark, <span class="str">&quot;&lt;/span&gt;&quot;</span>)

<span class="kwrd">Return</span> text

<span class="kwrd">End</span> <span class="kwrd">Function</span>

<span class="kwrd">Private</span> <span class="kwrd">Function</span> toImage(<span class="kwrd">ByVal</span> objImage <span class="kwrd">As</span> <span class="kwrd">Object</span>) <span class="kwrd">As</span> <span class="kwrd">String</span>

<span class="kwrd">If</span> <span class="kwrd">Not</span> objImage <span class="kwrd">Is</span> <span class="kwrd">Nothing</span> <span class="kwrd">Then</span>

<span class="kwrd">Dim</span> image <span class="kwrd">As</span> com.msn.search.soap.Image = <span class="kwrd">CType</span>(objImage, com.msn.search.soap.Image)

<span class="kwrd">Return</span> image.ImageURL

<span class="kwrd">End</span> <span class="kwrd">If</span>

<span class="kwrd">Return</span> <span class="kwrd">String</span>.Empty

<span class="kwrd">End</span> <span class="kwrd">Function</span>

&lt;/script&gt;

&lt;html xmlns=<span class="str">&quot;http://www.w3.org/1999/xhtml&quot;</span> &gt;

&lt;head runat=<span class="str">&quot;server&quot;</span>&gt;

&lt;title&gt;Untitled Page&lt;/title&gt;

&lt;style type=<span class="str">&quot;text/css&quot;</span>&gt;

html 

{

font:12px Verdana;

}

a {text-decoration:none}

.hiLite {background-color:yellow}

&lt;/style&gt;

&lt;/head&gt;

&lt;body&gt;

&lt;form id=<span class="str">&quot;form1&quot;</span> runat=<span class="str">&quot;server&quot;</span>&gt;

&lt;div&gt;

&lt;asp:DataList

id=<span class="str">&quot;lstResponses&quot;</span>

Runat=<span class="str">&quot;server&quot;</span>&gt;

&lt;ItemTemplate&gt;

&lt;h1&gt;&lt;%# Eval(<span class="str">&quot;Source&quot;</span>) %&gt; (&lt;%# Eval(<span class="str">&quot;Total&quot;</span>) %&gt; Results)&lt;/h1&gt;

&lt;asp:Repeater

id=<span class="str">&quot;grdResults&quot;</span>

DataSource=<span class="rem">'&lt;%# Eval(&quot;Results&quot;) %&gt;'</span>

Runat=<span class="str">&quot;server&quot;</span>&gt;

&lt;HeaderTemplate&gt;

&lt;ul&gt;

&lt;/HeaderTemplate&gt;

&lt;ItemTemplate&gt;

&lt;li&gt;

&lt;asp:HyperLink 

id=<span class="str">&quot;lnkResult&quot;</span>

ImageUrl=<span class="rem">'&lt;%# toImage( Eval(&quot;Image&quot;)) %&gt;'</span>

Text=<span class="rem">'&lt;%# hiLite( Eval(&quot;Title&quot;) ) %&gt;'</span>

NavigateUrl=<span class="rem">'&lt;%# Eval(&quot;Url&quot;) %&gt;'</span>

Runat=<span class="str">&quot;server&quot;</span> /&gt;

&lt;p&gt;

&lt;%# hiLite( Eval(<span class="str">&quot;Description&quot;</span>) ) %&gt;

&lt;/p&gt;

&lt;/li&gt;

&lt;/ItemTemplate&gt;

&lt;FooterTemplate&gt;

&lt;/ul&gt;

&lt;/FooterTemplate&gt;

&lt;/asp:Repeater&gt;

&lt;/ItemTemplate&gt;

&lt;/asp:DataList&gt;

&lt;/div&gt;

&lt;/form&gt;

&lt;/body&gt;

&lt;/html&gt;

</pre>
</div>
<style type="text/css">
<!--
.csharpcode, .csharpcode 
	{font-size:small;
	color:black;
	font-family:consolas,"Courier New",courier,monospace}
.csharpcode 
	{margin:0em}
.csharpcode .rem
	{color:#008000}
.csharpcode .kwrd
	{color:#0000ff}
.csharpcode .str
	{color:#006080}
.csharpcode .op
	{color:#0000c0}
.csharpcode .preproc
	{color:#cc6633}
.csharpcode .asp
	{background-color:#ffff00}
.csharpcode .html
	{color:#800000}
.csharpcode .attr
	{color:#ff0000}
.csharpcode .alt
	{background-color:#f4f4f4;
	width:100%;
	margin:0em}
.csharpcode .lnum
	{color:#606060}
-->
</style>
<p><b>C# Code</b> </p>
<p>&nbsp; </p>
<div>
<pre class="csharpcode">&lt;%@ Page Language=<span class="str">&quot;C#&quot;</span> %&gt;

&lt;%@ Import Namespace=<span class="str">&quot;com.msn.search.soap&quot;</span> %&gt;

&lt;%@ Import Namespace=<span class="str">&quot;System.Text.RegularExpressions&quot;</span> %&gt;

&lt;!DOCTYPE html PUBLIC <span class="str">&quot;-//W3C//DTD XHTML 1.0 Transitional//EN&quot;</span> <span class="str">&quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd&quot;</span>&gt;

&lt;script runat=<span class="str">&quot;server&quot;</span>&gt;

<span class="kwrd">const</span> <span class="kwrd">string</span> appId = <span class="str">&quot;&quot;</span>;

<span class="kwrd">const</span> <span class="kwrd">string</span> query = <span class="str">&quot;\&quot;Bill Gates\&quot;&quot;</span>;

<span class="kwrd">const</span> <span class="kwrd">string</span> startMark = <span class="str">&quot;\uE000&quot;</span>;

<span class="kwrd">const</span> <span class="kwrd">string</span> endMark = <span class="str">&quot;\uE001&quot;</span>;

<span class="kwrd">void</span> Page_Load()

{

<span class="rem">// Create instance of MSN Search Services</span>

MSNSearchService search = <span class="kwrd">new</span> MSNSearchService();

<span class="rem">// Build Source Request</span>

SourceRequest newsSource = <span class="kwrd">new</span> SourceRequest();

newsSource.Source = SourceType.News;

SourceRequest webSource = <span class="kwrd">new</span> SourceRequest();

webSource.Source = SourceType.Web;

SourceRequest imageSource = <span class="kwrd">new</span> SourceRequest();

imageSource.Source = SourceType.Image;

imageSource.ResultFields = ResultFieldMask.Image | ResultFieldMask.Url;

<span class="rem">// Build the Search Request</span>

SearchRequest request = <span class="kwrd">new</span> SearchRequest();

request.AppID = appId;

request.Requests = <span class="kwrd">new</span> SourceRequest[] {imageSource, newsSource, webSource};

request.Query = query;

request.CultureInfo = <span class="str">&quot;en-US&quot;</span>;

request.Flags = SearchFlags.MarkQueryWords;

<span class="rem">// Execute Search</span>

SearchResponse response = search.Search(request);

lstResponses.DataSource = response.Responses;

lstResponses.DataBind();

}

<span class="kwrd">string</span> hiLite(<span class="kwrd">object</span> item)

{

<span class="kwrd">if</span> (item == <span class="kwrd">null</span>)

<span class="kwrd">return</span> String.Empty;

<span class="kwrd">string</span> text = item.ToString();

text = Regex.Replace(text, startMark, <span class="str">&quot;&lt;span class='hiLite'&gt;&quot;</span>);

text = Regex.Replace(text, endMark, <span class="str">&quot;&lt;/span&gt;&quot;</span>);

<span class="kwrd">return</span> text;

}

<span class="kwrd">string</span> toImage(<span class="kwrd">object</span> objImage)

{

<span class="kwrd">if</span> (objImage != <span class="kwrd">null</span>)

{

com.msn.search.soap.Image image = (com.msn.search.soap.Image)objImage;

<span class="kwrd">return</span> image.ImageURL;

}

<span class="kwrd">return</span> String.Empty;

}

&lt;/script&gt;

&lt;html xmlns=<span class="str">&quot;http://www.w3.org/1999/xhtml&quot;</span> &gt;

&lt;head runat=<span class="str">&quot;server&quot;</span>&gt;

&lt;title&gt;Vanity Search&lt;/title&gt;

&lt;style type=<span class="str">&quot;text/css&quot;</span>&gt;

html 

{

font:12px Verdana;

}

a {text-decoration:none}

.hiLite {background-color:yellow}

&lt;/style&gt;

&lt;/head&gt;

&lt;body&gt;

&lt;form id=<span class="str">&quot;form1&quot;</span> runat=<span class="str">&quot;server&quot;</span>&gt;

&lt;div&gt;

&lt;asp:DataList

id=<span class="str">&quot;lstResponses&quot;</span>

Runat=<span class="str">&quot;server&quot;</span>&gt;

&lt;ItemTemplate&gt;

&lt;h1&gt;&lt;%# Eval(<span class="str">&quot;Source&quot;</span>) %&gt; (&lt;%# Eval(<span class="str">&quot;Total&quot;</span>) %&gt; Results)&lt;/h1&gt;

&lt;asp:Repeater

id=<span class="str">&quot;grdResults&quot;</span>

DataSource=<span class="str">'&lt;%# Eval(&quot;Results&quot;) %&gt;'</span>

Runat=<span class="str">&quot;server&quot;</span>&gt;

&lt;HeaderTemplate&gt;

&lt;ul&gt;

&lt;/HeaderTemplate&gt;

&lt;ItemTemplate&gt;

&lt;li&gt;

&lt;asp:HyperLink 

id=<span class="str">&quot;lnkResult&quot;</span>

ImageUrl=<span class="str">'&lt;%# toImage( Eval(&quot;Image&quot;)) %&gt;'</span>

Text=<span class="str">'&lt;%# hiLite( Eval(&quot;Title&quot;) ) %&gt;'</span>

NavigateUrl=<span class="str">'&lt;%# Eval(&quot;Url&quot;) %&gt;'</span>

Runat=<span class="str">&quot;server&quot;</span> /&gt;

&lt;p&gt;

&lt;%# hiLite( Eval(<span class="str">&quot;Description&quot;</span>) ) %&gt;

&lt;/p&gt;

&lt;/li&gt;

&lt;/ItemTemplate&gt;

&lt;FooterTemplate&gt;

&lt;/ul&gt;

&lt;/FooterTemplate&gt;

&lt;/asp:Repeater&gt;

&lt;/ItemTemplate&gt;

&lt;/asp:DataList&gt;

&lt;/div&gt;

&lt;/form&gt;

&lt;/body&gt;

&lt;/html&gt;

</pre>
</div>
<style type="text/css">
<!--
.csharpcode, .csharpcode 
	{font-size:small;
	color:black;
	font-family:consolas,"Courier New",courier,monospace}
.csharpcode 
	{margin:0em}
.csharpcode .rem
	{color:#008000}
.csharpcode .kwrd
	{color:#0000ff}
.csharpcode .str
	{color:#006080}
.csharpcode .op
	{color:#0000c0}
.csharpcode .preproc
	{color:#cc6633}
.csharpcode .asp
	{background-color:#ffff00}
.csharpcode .html
	{color:#800000}
.csharpcode .attr
	{color:#ff0000}
.csharpcode .alt
	{background-color:#f4f4f4;
	width:100%;
	margin:0em}
.csharpcode .lnum
	{color:#606060}
-->
</style>
<p>Before you use the vanity search page, you should modify two of the constants that appear at the top of the page: the appId and query constants. Assign the App ID that you get from visiting the following URL to the appId constant:
<a href="http://search.msn.com/developer/appids.aspx">http://search.msn.com/developer/appids.aspx</a>. Enter anything you want for the query constant. In the page above, the name Bill Gates (enclosed in quotes) is assigned to the query constant. When you open
 the page in a web browser, you should see a page similar to Figure 2. </p>
<p>&nbsp; </p>
<p><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1855817/image07.png"><img height="240" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1855817/image06.png" width="228" border="0"></a>
</p>
<p><strong>Figure 2 - Image results for Bill Gates vanity search page</strong> </p>
<p>The page displays three different groups of results. First, the page displays a list of images that match the search query. Next, the page displays a list of news articles. Finally, the page displays a list of websites (see Figure 3).
</p>
<p><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1855817/image010.png"><img height="240" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1855817/image09.png" width="228" border="0"></a>
</p>
<p><strong>Figure 3 - Web results&nbsp;for Bill Gates vanity search page</strong> </p>
<p>&nbsp; </p>
<p>The Windows Live Search web service currently supports the following types of searches:
</p>
<p>&nbsp; </p>
<ul>
<li>Image - Returns a list of images that match the search query. </li><li>Inline Answers - Only available for commercial use. This type of search returns information from Encarta, Finance, Weather, and Movie show times.
</li><li>News - Returns results from online news sources. </li><li>Phone Book - Returns results from white and yellow page phone books. </li><li>Query Location - Returns latitude and longitude information associated with a query.
</li><li>Spelling - Returns a list of spelling suggestions. </li><li>Web - Returns a list of websites that match the search query.</li></ul>
<p>&nbsp; </p>
<p>You perform a search by creating an instance of the SearchRequest class. You assign the text of your search query to the SearchRequest class's Query property. This class also includes a Requests collection. You add one or more SourceRequest objects to this
 collection that represent different types of searches (Image, Web, News, and so on). After you get all of the objects ready, you call the MSNSearchService.Search() method to actually perform the search.
</p>
<p>The search results are displayed with the help of a DataList and Repeater control. The DataList displays the source of the search and the number of results for each source returned. The Repeater control is nested in the DataList and it displays the actual
 search results.&nbsp;&nbsp; </p>
<h3>Conclusion</h3>
<p>As I mentioned before, I wrote this article as an excuse to play with the Windows Live SDK. I am very happy that I got the chance to experiment with this SDK since I discovered that it is very easy to work with. I'm looking forward to trying out some of
 the other Windows Live services such as the Virtual Earth and Alerts services over the coming months.
</p>
 <img src="http://m.webtrends.com/dcs1wotjh10000w0irc493s0e_6x1g/njs.gif?dcssip=channel9.msdn.com&dcsuri=http://channel9.msdn.com/Niners/c4f.Stephen-Walther/Posts/RSS&WT.dl=0&WT.entryid=Entry:RSSView:03452b0c9a2e4ef49da49e7600d512db">]]></description>
      <comments>http://channel9.msdn.com/coding4fun/articles/Creating-a-Vanity-Search-Page</comments>
      <itunes:summary>



&amp;nbsp;
It&#39;s all about you. Learn how to call the Windows Live Search service to create a vanity page that displays images, news articles, and websites about you.



Stephen Walther
Superexpert Blog

Difficulty: Easy
Time Required: 
Less than 1 hour
Cost: Free
Software: Visual Web Developer 2005 Express Edition








 
This month, we create a vanity search page. The vanity search page displays any images, news or website entries about a particular person (for example, you). To create this page, we take advantage of the Windows Live Search API. This free API enables you
 to retrieve search results by calling a web service that Microsoft exposes on the web.
 
I decided to write this article because I wanted an excuse to play with the Windows Live SDK (see
http://dev.live.com). The SDK includes documentation and samples for accessing all of the Windows Live web services including the Windows Live Search Web Service, Virtual Earth, and Windows Live Alerts.
 
I fully admit that I&amp;nbsp;was&amp;nbsp;actively avoiding writing this article because I dreaded the thought of needing to learn yet another Application Programming Interface. I was pleasantly surprised to discover that the API for Windows Live Search is both logical and
 painlessly simple to understand. I wrote the code for this article in less than an hour.
 
Before you can access the Windows Live services, you need to get an Application ID. You pass this ID to the Windows Live services to identify yourself. You get an Application ID by signing an agreement at the following URL:
http://search.msn.com/developer/appids.aspx.
 

 
Figure 1 - Adding a Web Reference for Windows&amp;nbsp;Live Search  
After you have an Application ID, you are ready to start calling Windows Live web services. Here are the steps for creating the vanity search page:
 
1. Launch Visual Web Developer and create a new Web Site  
2. Select the menu option Website, Add Web Reference to add a Web Reference to the Windows Live Search web service (see</itunes:summary>
      <link>http://channel9.msdn.com/coding4fun/articles/Creating-a-Vanity-Search-Page</link>
      <pubDate>Sat, 10 Mar 2007 20:09:12 GMT</pubDate>
      <guid isPermaLink="false">http://channel9.msdn.com/coding4fun/articles/Creating-a-Vanity-Search-Page</guid>
      <media:thumbnail url="http://ecn.channel9.msdn.com/o9/c4f/images/1855817_100.jpg" height="75" width="100"></media:thumbnail>
      <media:thumbnail url="http://ecn.channel9.msdn.com/o9/c4f/images/1855817_220.jpg" height="165" width="220"></media:thumbnail>      
      <dc:creator>Stephen Walther</dc:creator>
      <itunes:author>Stephen Walther</itunes:author>
      <slash:comments>8</slash:comments>
      <wfw:commentRss>http://channel9.msdn.com/coding4fun/articles/Creating-a-Vanity-Search-Page/RSS</wfw:commentRss>
      <category>Web</category>
      <category>Web Services</category>
      <category>Mash Up</category>
    </item>
  <item>
      <title>Creating an ASP.NET Hangman Control</title>
      <description><![CDATA[<span id="c4fmetadata">
<table cellspacing="0" cellpadding="1" width="100%" border="0">
<tbody>
<tr class="entry_overview">
<td width="50">&nbsp;</td>
<td><span class="entry_description">In this post, Stephen Walther shows you how to create an ASP.NET Hangman control. This control contains embedded images, sounds, XML, and Javascript.</span></td>
</tr>
<tr>
<td colspan="2">
<div class="entry_author">Stephen Walther</div>
<div class="entry_company"><a href="http://www.superexpert.com">Steve's Blog</a></div>
<br>
<div class="entry_details"><b>Difficulty: </b><span class="entry_details_input">Easy</span></div>
<div class="entry_details"><b>Time Required:</b> <span class="entry_details_input">
Less than 1 hour</span></div>
<div class="entry_details"><b>Cost: </b><span class="entry_details_input">Free</span></div>
<div class="entry_details"><b>Software: </b><span class="entry_details_input"><a href="http://msdn.com/express/">Visual Basic or Visual C# Express Editions</a>,<a href="http://msdn.microsoft.com/vstudio/express/">Visual Web Developer Express</a>,</span></div>
<div class="entry_details"><b>Hardware: </b><span class="entry_details_input"></span></div>
<div class="entry_details"><b>Download: </b><a href="http://channel9.msdn.com/ShowPost.aspx?PostID=285841">Download</a>
<ul>
</ul>
</div>
</td>
</tr>
</tbody>
</table>
</span>
<p>This month, we create an ASP.NET Hangman control. Our control will render all of the necessary images, sounds, and scripts to create a richly interactive hangman game (see Figure 1). Our control will work with the most recent versions of Microsoft Internet
 Explorer, Mozilla Firefox, and Opera. </p>
<p><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1756233/Figure16.png"><img height="496" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1756233/Figure1_thumb4.png" width="368" border="0"></a>
</p>
<p>We tackle several advanced features of the ASP.NET 2.0 framework in this article. You learn how to build custom controls that take advantage of Javascript. You also learn how to embed resources such as images, sound, and XML in an assembly. Finally, you
 learn how to write cross-browser compatible Javascript. </p>
<h3>Using the Hangman Control</h3>
<p>If you are anxious to start playing hangman, you can download the ZIP file that accompanies this article. Click the Download link above.&nbsp;The ZIP file contains two projects: the Visual Basic and the C# versions of the Hangman control. If you are interested
 in viewing or modifying the source code for the Hangman control, you can open the Visual Basic version with Microsoft Visual Basic 2005 Express Edition and the C# version with Microsoft C# 2005 Express Edition.
</p>
<p>Here's how you use the Hangman control. Launch Visual Web Developer 2005 Express Edition and create a new website (select the menu option File, New Web Site). Next, add the control to your Toolbox by right-clicking beneath the General tab on your Toolbox
 and selecting the option Choose Items (see Figure 2). You must have a Web Form Page open in order to modify the Toolbox.&nbsp;
</p>
<p><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1756233/Figure22.png"><img height="417" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1756233/Figure2_thumb.png" width="403" border="0"></a>
</p>
<p>Next, under the .NET Framework Components tab, click the Browse button and browse to the Hangman assembly (dll file). There is both a VB.NET and C# version of this file (it doesn't matter which version you use since you can use a control written in C# with
 a VB.NET website and a control written in VB.NET with a C# website). The files are located in the following subfolders:
</p>
<blockquote>
<p>VB\Hangman\bin\Release\Hangman.dll </p>
<p>CS\Hangman\bin\Release\Hangman.dll</p>
</blockquote>
<p>Click OK a couple of times to close the dialog boxes and the Hangman control should now appear on your Toolbox.
</p>
<p>After you have added to the Hangman control to your Toolbox, you can add the control to any page simply by dragging the control onto a Web Form Page in either Design or Source view. That's all there is to adding this control to a page.
</p>
<p>The Hangman control includes a default set of words included in an embedded XML file (these words are intended to be hard). If you prefer, you can associate a custom list of words with the Hangman control by assigning the path of an XML file to the control's
 WordsUrl property. The XML file should have the following format: </p>
<p>&lt;words&gt; </p>
<p>&lt;word&gt;baby&lt;/word&gt; </p>
<p>&lt;word&gt;easy&lt;/word&gt; </p>
<p>&lt;/words&gt; </p>
<p>The file can contain as many words as you please. </p>
<h3>Creating a Custom Web Control</h3>
<p>The Hangman control is implemented as a custom ASP.NET Web Control. In other words, the control is a class that derives from the base System.Web.UI.WebControls.WebControl class. The Hangman class overrides one method of the base class: the OnPreRender()
 method. </p>
<p>The Hangman control's OnPreRender() method loads the XML, Javascript, sound, and image files. All of these resources are loaded by using the Page.ClientScript.GetWebResourceUrl() method to retrieve a valid URL for the embedded resource.
</p>
<h3>Embedding Images, Sounds, XML, and Javascript</h3>
<p>The Hangman control includes embedded image, sound, XML, and Javascript files. These resources are embedded in the same assembly (dll) as the control so that the control can be distributed with a single assembly.
</p>
<p>There are three steps required for embedding a resource in an assembly: </p>
<p>1) Set the Build Action for the resource to the value Embedded Resource. You set the Build Action for a file by selecting the file, opening the Properties Window, and modifying the Build Action property.
</p>
<p>2) Add a WebResource attribute to the AssemblyInfo file for each embedded resource. When working with Microsoft Visual Basic 2005 Express Edition, select the menu option Project, Show All Files and expand the My Project folder in the Solution Explorer Window
 to view the AssemblyInfo file. When working with Microsoft C# 2005 Express Edition, expand the Properties folder to view the AssemblyInfo file. You need to add the following attribute to embed an image resource named MyImage.gif:
</p>
<p>VB.NET </p>
<p>&lt;Assembly: WebResource(&quot;ProjectNamespace.MyImage.gif&quot;, &quot;image/gif&quot;)&gt; </p>
<p>C# </p>
<p>[Assembly: WebResource(&quot;ProjectNamespace.MyImage.gif&quot;, &quot;image/gif&quot;)] </p>
<p>By default, the ProjectNamespace will be the same as your project name. In the case of the Hangman project, the project namespace is Hangman.
</p>
<p>3) Finally, in your code, you can retrieve a URL to an embedded resource by using the Page.ClientScript.GetWebResourceUrl() method. This method accepts two parameters: a type and a parameter name. Typically, you will pass the type of the current class and
 the name of the embedded resource. For example, you would use the following line of code to get the URL to an image named MyImage.gif located in the Hangman project:
</p>
<p>VB.NET </p>
<p>Dim imageUrl As String = Page.ClientScript.GetWebResourceUrl( this.GetType(), “Hangman.MyImage.gif”)
</p>
<p>C# </p>
<p>string imageUrl = Page.ClientScript.GetWebResourceUrl( me.GetType(), “Hangman.MyImage.gif”);
</p>
<p>Be aware that all resource names are case-sensitive -- even in the case of VB.NET. Make sure that you refer to the name of the resource in the same way with the file name, attribute, and GetWebResourceUrl() method.
</p>
<h3>Cross-Browser Javascript</h3>
<p>All of the logic of the Hangman game is implemented in the Hangman.js Javascript file. When the control loads, the Javascript initializeGame() function is called and all of the game elements are created.
</p>
<p>When you click a letter, the selectLetter() function is called. If a matching letter is found, the display of matching letters is updated. If a matching letter is not found, the badGuessCount variable is updated and the image of the hangman is updated as
 well. </p>
<p>If you win a game, the doWin() function is called and if you lose a game the doLose() function is called. Both functions play a sound and both functions display a link that enables you to restart the game.
</p>
<p>All of the Javascript was written in a cross-browser compatible way. The Javascript code works with Microsoft Internet Explorer, Mozilla Firefox, and Opera. Therefore, the Hangman control works with all three browsers.
</p>
<h3>Conclusion</h3>
<p>The biggest hurdle that I encountered while writing this control was getting the embedded resources to work. Once I resolved the namespace issues and got all of the case-sensitivity issues under control, everything worked out. I was very happy that I was
 able to get all of the resource (including the XML file with the list of words) embedded into one control.
</p>
 <img src="http://m.webtrends.com/dcs1wotjh10000w0irc493s0e_6x1g/njs.gif?dcssip=channel9.msdn.com&dcsuri=http://channel9.msdn.com/Niners/c4f.Stephen-Walther/Posts/RSS&WT.dl=0&WT.entryid=Entry:RSSView:a8ea7fac673445e9af149e7600d59cd4">]]></description>
      <comments>http://channel9.msdn.com/coding4fun/articles/Creating-an-ASPNET-Hangman-Control</comments>
      <itunes:summary>



&amp;nbsp;
In this post, Stephen Walther shows you how to create an ASP.NET Hangman control. This control contains embedded images, sounds, XML, and Javascript.



Stephen Walther
Steve&#39;s Blog

Difficulty: Easy
Time Required: 
Less than 1 hour
Cost: Free
Software: Visual Basic or Visual C# Express Editions,Visual Web Developer Express,
Hardware: 
Download: Download








This month, we create an ASP.NET Hangman control. Our control will render all of the necessary images, sounds, and scripts to create a richly interactive hangman game (see Figure 1). Our control will work with the most recent versions of Microsoft Internet
 Explorer, Mozilla Firefox, and Opera.  

 
We tackle several advanced features of the ASP.NET 2.0 framework in this article. You learn how to build custom controls that take advantage of Javascript. You also learn how to embed resources such as images, sound, and XML in an assembly. Finally, you
 learn how to write cross-browser compatible Javascript.  
Using the Hangman Control
If you are anxious to start playing hangman, you can download the ZIP file that accompanies this article. Click the Download link above.&amp;nbsp;The ZIP file contains two projects: the Visual Basic and the C# versions of the Hangman control. If you are interested
 in viewing or modifying the source code for the Hangman control, you can open the Visual Basic version with Microsoft Visual Basic 2005 Express Edition and the C# version with Microsoft C# 2005 Express Edition.
 
Here&#39;s how you use the Hangman control. Launch Visual Web Developer 2005 Express Edition and create a new website (select the menu option File, New Web Site). Next, add the control to your Toolbox by right-clicking beneath the General tab on your Toolbox
 and selecting the option Choose Items (see Figure 2). You must have a Web Form Page open in order to modify the Toolbox.&amp;nbsp;
 

 
Next, under the .NET Framework Components tab, click the Browse button and browse to the Hangman assembly (dll file). The</itunes:summary>
      <link>http://channel9.msdn.com/coding4fun/articles/Creating-an-ASPNET-Hangman-Control</link>
      <pubDate>Sun, 25 Feb 2007 04:50:59 GMT</pubDate>
      <guid isPermaLink="false">http://channel9.msdn.com/coding4fun/articles/Creating-an-ASPNET-Hangman-Control</guid>
      <media:thumbnail url="http://ecn.channel9.msdn.com/o9/c4f/images/1756233_100.jpg" height="75" width="100"></media:thumbnail>
      <media:thumbnail url="http://ecn.channel9.msdn.com/o9/c4f/images/1756233_220.jpg" height="165" width="220"></media:thumbnail>      
      <dc:creator>Stephen Walther</dc:creator>
      <itunes:author>Stephen Walther</itunes:author>
      <slash:comments>18</slash:comments>
      <wfw:commentRss>http://channel9.msdn.com/coding4fun/articles/Creating-an-ASPNET-Hangman-Control/RSS</wfw:commentRss>
      <category>Web</category>
      <category>Puzzle</category>
    </item>
  <item>
      <title>Creating Loud Websites</title>
      <description><![CDATA[<span id="c4fmetadata">
<table cellspacing="0" cellpadding="1" width="100%" border="0">
<tbody>
<tr class="entry_overview">
<td width="50">&nbsp;</td>
<td><span class="entry_description">In this post, Stephen Walther explains how to make your websites have more noise. You learn how to use Javascript to add sound effects to your ASP.NET pages.</span></td>
</tr>
<tr>
<td colspan="2">
<div class="entry_author">Stephen Walther</div>
<div class="entry_company"><a href="http://superexpert.com">Steve's Blog</a></div>
<br>
<div class="entry_details"><b>Difficulty: </b><span class="entry_details_input">Easy</span></div>
<div class="entry_details"><b>Time Required:</b> <span class="entry_details_input">
Less than 1 hour</span></div>
<div class="entry_details"><b>Cost: </b><span class="entry_details_input">Free</span></div>
<div class="entry_details"><b>Software: </b><span class="entry_details_input"><a href="http://msdn.microsoft.com/vstudio/express/">Visual Web Developer 2005 Express</a></span></div>
</td>
</tr>
</tbody>
</table>
</span>
<p></p>
<p>I want to create noisy websites. All of our desktop applications make sounds. It seems completely unfair that our websites are so quiet.
</p>
<p>For example, when you empty your computer's recycle bin your computer makes the satisfying sound of trash being dumped from a trash can. When you leave the desktop and enter the web, however, the world goes silent (almost like you are under water).
</p>
<p>When you browse a catalog of products displayed on a website, each product should demand to be bought. When you hover your mouse over a picture of a music box, it should play a quiet tune. When you hover your mouse over a picture of a vacuum cleaner, it
 should make a mighty rrrrrrrrrrrrr sound. </p>
<p>Whenever I reveal my secret ambition to make noisy websites, people always groan. Everyone always thinks of all of those MySpace pages with the endlessly looping background music. But I don't mean background music, I mean noise.
</p>
<p>We interact with websites through metaphors. We work with “files” and “folders” on a “desktop”. We grab files and “drag” them to new folders. Under the covers, of course, we are really just flipping massive numbers of bits. But, we understand our complex
 interactions with our computers by projecting metaphors that we've stolen from the physical world onto our machines.
</p>
<p>The more closely our software interactions match our metaphors, the more satisfying the experience becomes. Dropping a file in a recycle bin to delete it makes perfect sense. If the recycle bin looks like a prototypical recycle bin, the experience seems
 more real. If the trash makes a satisfying trash-being-emptied sound, the experience is even more real.
</p>
<p>In this month's post, I'm going to tackle the problem of adding sounds to your ASP.NET websites. The goal is to produce sounds dynamically using Javascript.
</p>
<h3>Methods of Making Sounds </h3>
<p>Let's start with a quick review of the methods of generating sounds in a web page. There are three tags that you can add to a page to generate a sound: the &lt;bgsound&gt; tag, the &lt;embed&gt; tag, and the &lt;object&gt; tag.
</p>
<p>Here's how you add sound with the &lt;bgsound&gt; tag: </p>
<blockquote>
<p>&lt;bgsound src=&quot;test.wav&quot; /&gt; </p>
</blockquote>
<p>The &lt;bgsound&gt; tag is the tag that gave sound a bad name. This is the tag that everyone adds to their websites to create the endlessly looping background music.
</p>
<p>The &lt;bgsound&gt; tag was introduced into the world (in the same month) with the release of Microsoft Internet Explorer 2.0 and Mosaic 2.1. Opera supports the &lt;bgsound&gt; tag, but Firefox does not.
</p>
<p>Since the &lt;bgsound&gt; was never incorporated into any web standards (you won't find any mention of the tag in either the HTML or XHTML standards), most web authors avoid this tag as outdated and dead. Typically, you are encouraged not to use the &lt;bgsound&gt;
 tag in favor of either the &lt;embed&gt; or &lt;object&gt; tag. </p>
<p>However, I use the &lt;bgsound&gt; sound tag in the Javascript that I develop at the end of this post. There is one very important advantage of the &lt;bgsound&gt; tag. The &lt;bgsound&gt; tag does not cause the information bar to popup in Internet Explorer when you use this
 tag in a page. </p>
<p>The Internet Explorer version of this tag has four important properties: </p>
<ul>
<li>Balance -- Enables you to specify the balance between the left and right speaker
</li><li>Loop -- Enables you to specify the number of times that the sound will repeat. The value -1 means loop infinitely
</li><li>Src -- Enables you to specify the URL to the sound file </li><li>Volume -- Enables you to specify the volume of the sound (valid values range from -10,000 to 0)
</li></ul>
<p>As an alternative to the &lt;bgsound&gt; tag, you can use the &lt;embed&gt; tag. The &lt;embed&gt; tag was introduced to the world with the release of Netscape 1.1. The tag is now supported by all modern browsers.
</p>
<p>Here's how you use the &lt;embed&gt; tag: </p>
<blockquote>
<p>&lt;embed src=&quot;test.wav&quot; type=”audio/x-wav” /&gt; </p>
</blockquote>
<p>The src attribute points to the sound file and the type attribute specifies the MIME type of the file. Notice that the MIME type of a .wav sound file is indicated with the MIME type audio/x-wav. The x means that .wav is a custom type. Using the x is necessary
 because the .wav sound file format does not have a registered MIME type at IANA.
</p>
<p>The &lt;embed&gt; tag is not limited to sounds. You can use the &lt;embed&gt; tag to embed a variety of different types of objects in a page including videos and pictures.
</p>
<p>There's no master list of valid attributes for the &lt;embed&gt; tag. Different types of objects that you embed in a document will support different attributes. For example, on my computer, Windows Media Player is mapped to the .wav extension. Therefore, I can
 use Windows Media Player attributes with the &lt;embed&gt; tag. </p>
<p>One problem with using the &lt;embed&gt; tag is that you must have an application mapped to the type of file being downloaded. Unfortunately, on my computer, there was no application mapped to the .wav extension by default. When I initially requested a page that
 contained an embedded .wav file, I got the Internet Explorer information bar. </p>
<p>Since I don't want to inflict the Internet Explorer information bar on users when playing sounds, I don't use the &lt;embed&gt; tag in the Javascript at the end of this article. The &lt;bgsound&gt; element enables us to play .wav files without displaying the information
 bar. </p>
<p>The final -- and generally recommended -- method of adding sound to a web page is to use the &lt;object&gt; tag. The &lt;object&gt; tag is very similar to the &lt;embed&gt; tag. It allows you to embed objects in a page like this:
</p>
<blockquote>
<p>&lt;object data=&quot;test.wav&quot; type=&quot;audio/x-wav&quot; /&gt; </p>
</blockquote>
<p>Notice that the &lt;object&gt; tag uses the data attribute and not the src attribute to point to a file.
</p>
<p>The difference between the &lt;embed&gt; tag and the &lt;object&gt; tag is that the latter tag is supported by W3C web standards. If creating standards compliant websites is important to you, then you should use this tag.
</p>
<p>Just like in the case of the &lt;embed&gt; tag, there is no master list of attributes for the &lt;object&gt; tag. The list of valid attributes all depends on the application or plug-in being used to display the embedded object.
</p>
<p>Unfortunately, when used with Internet Explorer, the &lt;object&gt; tag causes the Internet Explorer information bar to popup just like the &lt;embed&gt; tag. In the Javascript at the end of this article, I use the &lt;bgsound&gt; tag for Internet Explorer and the &lt;object&gt;
 tag for every other browser. </p>
<h3>Generating Sounds with Javascript </h3>
<p>So now that we've finished reviewing the possible methods of generating sound in a page, we are ready to create our Javascript that we'll use in our ASP.NET pages to generate sound. Our script will works with recent versions of all major browsers including
 Internet Explorer, Firefox, and Opera. </p>
<p>Since the script is small, the entire content of the PlaySound.js Javascript file is included right here:
</p>
<p><strong>PlaySound.js<br>
</strong></p>
<pre class="csharpcode"><span class="kwrd">if</span> (window.attachEvent)
    window.attachEvent(<span class="str">&quot;onload&quot;</span>, setupPlaySound);
<span class="kwrd">else</span>
    window.addEventListener(<span class="str">&quot;load&quot;</span>, setupPlaySound, <span class="kwrd">false</span>); 


<span class="kwrd">function</span> setupPlaySound()
{
    <span class="kwrd">if</span> (navigator.appName == <span class="str">&quot;Microsoft Internet Explorer&quot;</span>)
    {
        <span class="kwrd">var</span> snd = document.createElement(<span class="str">&quot;bgsound&quot;</span>);
        document.getElementsByTagName(<span class="str">&quot;body&quot;</span>)[0].appendChild(snd);
        
        playSound = <span class="kwrd">function</span>(url)
        {
        
            snd.src = url;
        }
    }
    <span class="kwrd">else</span>
    {
        playSound = <span class="kwrd">function</span>(url)
        {
            <span class="kwrd">var</span> obj = document.createElement(<span class="str">&quot;object&quot;</span>);
            obj.width=<span class="str">&quot;0px&quot;</span>;
            obj.height=<span class="str">&quot;0px&quot;</span>;
            obj.type = <span class="str">&quot;audio/x-wav&quot;</span>;
            obj.data = url;
            
            <span class="kwrd">var</span> body = document.getElementsByTagName(<span class="str">&quot;body&quot;</span>)[0];
            body.appendChild(obj);
        }
    }
}
</pre>
<style type="text/css">
<!--
.csharpcode, .csharpcode 
	{font-size:small;
	color:black;
	font-family:consolas,"Courier New",courier,monospace;
	background-color:#ffffff}
.csharpcode 
	{margin:0em}
.csharpcode .rem
	{color:#008000}
.csharpcode .kwrd
	{color:#0000ff}
.csharpcode .str
	{color:#006080}
.csharpcode .op
	{color:#0000c0}
.csharpcode .preproc
	{color:#cc6633}
.csharpcode .asp
	{background-color:#ffff00}
.csharpcode .html
	{color:#800000}
.csharpcode .attr
	{color:#ff0000}
.csharpcode .alt
	{background-color:#f4f4f4;
	width:100%;
	margin:0em}
.csharpcode .lnum
	{color:#606060}
-->
</style>
<p>&nbsp;</p>
<p>The first lines of the Javascript create an event handler for the browser window load event. Internet Explorer uses the attachEvent() method to create an event handler and other browsers use the addEventListener() method.
</p>
<p>The setupPlaySounds() method is called after the window is loaded. This method creates the playSound() method. Javascript enables you to conditionally create different versions of a function. There is one version of the playSound() method that is created
 in the case of Internet Explorer and another version that is created in the case of every other browser.
</p>
<p>The Internet Explorer version of the playSound() method takes advantage of the &lt;bgsound&gt; tag to play a sound. The alternative playSound() method takes advantage of the &lt;object&gt; tag.
</p>
<p>If you link the Javascript file above into an ASP.NET page, then you can play a sound by calling the playSound() method and passing the URL of a sound file. You can link the PlaySound.js file to an ASP.NET page by adding the following tag to the page:
</p>
<blockquote>
<p>&lt;script type=&quot;text/javascript&quot; src=&quot;PlaySound.js&quot;&gt;&lt;/script&gt; </p>
</blockquote>
<p>And, adding the following link to a page will cause the sound file ClickHere.wav to play whenever you hover your mouse over the link.
</p>
<blockquote>
<p>&lt;a href=&quot;SomePage.htm&quot; onmouseover=&quot;playSound('ClickHere.wav')&quot;&gt;Click Here!&lt;/a&gt;
</p>
</blockquote>
<p>The playSound() method works with recent versions of Internet Explorer, Firefox, and Opera.
</p>
<p>I did run into one issue when testing this method with Firefox. Firefox uses the Apple QuickTime plug-in to play sound files. However, on my computer, QuickTime was not mapped to .wav files. I fixed this problem by launching the QuickTime Player, and selecting
 the menu option Edit, Preferences, QuickTime Preferences and selecting the File Types tab. Under this tab, I was able to associate .wav files with the QuickTime Player.
</p>
<h3>Conclusion
<h3></h3>
</h3>
<p>I think the web would be a much more enjoyable place if it were only a little louder. In this post, I've provided you with a cross-browser compatible Javascript playSound() method that you can use in your ASP.NET pages to add sound. Please make some noise.
</p>
 <img src="http://m.webtrends.com/dcs1wotjh10000w0irc493s0e_6x1g/njs.gif?dcssip=channel9.msdn.com&dcsuri=http://channel9.msdn.com/Niners/c4f.Stephen-Walther/Posts/RSS&WT.dl=0&WT.entryid=Entry:RSSView:682f3c563a694a4c85d19e7600d64fbf">]]></description>
      <comments>http://channel9.msdn.com/coding4fun/articles/Creating-Loud-Websites</comments>
      <itunes:summary>



&amp;nbsp;
In this post, Stephen Walther explains how to make your websites have more noise. You learn how to use Javascript to add sound effects to your ASP.NET pages.



Stephen Walther
Steve&#39;s Blog

Difficulty: Easy
Time Required: 
Less than 1 hour
Cost: Free
Software: Visual Web Developer 2005 Express





 
I want to create noisy websites. All of our desktop applications make sounds. It seems completely unfair that our websites are so quiet.
 
For example, when you empty your computer&#39;s recycle bin your computer makes the satisfying sound of trash being dumped from a trash can. When you leave the desktop and enter the web, however, the world goes silent (almost like you are under water).
 
When you browse a catalog of products displayed on a website, each product should demand to be bought. When you hover your mouse over a picture of a music box, it should play a quiet tune. When you hover your mouse over a picture of a vacuum cleaner, it
 should make a mighty rrrrrrrrrrrrr sound.  
Whenever I reveal my secret ambition to make noisy websites, people always groan. Everyone always thinks of all of those MySpace pages with the endlessly looping background music. But I don&#39;t mean background music, I mean noise.
 
We interact with websites through metaphors. We work with “files” and “folders” on a “desktop”. We grab files and “drag” them to new folders. Under the covers, of course, we are really just flipping massive numbers of bits. But, we understand our complex
 interactions with our computers by projecting metaphors that we&#39;ve stolen from the physical world onto our machines.
 
The more closely our software interactions match our metaphors, the more satisfying the experience becomes. Dropping a file in a recycle bin to delete it makes perfect sense. If the recycle bin looks like a prototypical recycle bin, the experience seems
 more real. If the trash makes a satisfying trash-being-emptied sound, the experience is even more real.
 
In this month&#39;s post, I&#39;m goin</itunes:summary>
      <link>http://channel9.msdn.com/coding4fun/articles/Creating-Loud-Websites</link>
      <pubDate>Thu, 25 Jan 2007 01:40:43 GMT</pubDate>
      <guid isPermaLink="false">http://channel9.msdn.com/coding4fun/articles/Creating-Loud-Websites</guid>      
      <dc:creator>Stephen Walther</dc:creator>
      <itunes:author>Stephen Walther</itunes:author>
      <slash:comments>24</slash:comments>
      <wfw:commentRss>http://channel9.msdn.com/coding4fun/articles/Creating-Loud-Websites/RSS</wfw:commentRss>
      <category>Web</category>
      <category>web miscellaneous</category>
    </item>
  <item>
      <title>Displaying Gentle Error Messages with ASP.NET</title>
      <description><![CDATA[<span id="c4fmetadata">
<table cellspacing="0" cellpadding="1" width="100%" border="0">
<tbody>
<tr class="entry_overview">
<td width="50">&nbsp;</td>
<td><span class="entry_description">Learn how to display gentler error messages when errors are encountered while developing ASP.NET applications. In this article, Stephen Walther shows you how you can modify the default ASP.NET error page so that it displays
 motivational sounds, messages, and pictures. </span></td>
</tr>
<tr>
<td colspan="2">
<div class="entry_author">Stephen Walther</div>
<div class="entry_company"><a href="http://superexpert.com">Stephen's Blog</a></div>
<br>
<div class="entry_details"><b>Difficulty: </b><span class="entry_details_input">Easy</span></div>
<div class="entry_details"><b>Time Required:</b> <span class="entry_details_input">
Less than 1 hour</span></div>
<div class="entry_details"><b>Cost: </b><span class="entry_details_input">Free</span></div>
<div class="entry_details"><b>Software: </b><span class="entry_details_input"><a href="http://msdn.microsoft.com/vstudio/express/vwd/">Visual Web Developer 2005 Express Edition</a></span></div>
<div class="entry_details"><b>Hardware: </b><span class="entry_details_input"></span></div>
<div class="entry_details"><b>Download: </b><a href="http://channel9.msdn.com/ShowPost.aspx?PostID=269023">Download</a>
<ul>
</ul>
</div>
</td>
</tr>
</tbody>
</table>
</span>
<p></p>
<p>I fly out to companies and teach workshops on building ASP.NET applications to developers new to the ASP.NET framework. Typically a developer starts out excited to learn something new. Unfortunately, a developer's first experience of the ASP.NET framework
 is often the error page -- the angry page with the yellow background and the red error message.
</p>
<p>When a novice developer encounters their first error message, I try to be reassuring. I explain that errors are normal and good and that an ASP.NET developer will view the error page at least half a billion times while developing a project of any reasonable
 complexity. After all, the mark of a good development framework is that it throws a lot of errors at you. A framework that throws a lot of errors prevents you from doing something stupid and deploying a buggy application into production.
</p>
<p>However, the question remains: why does the ASP.NET Framework seem so angry? Why the harsh yellow background and bold red error messages (see Figure 1)? Why can't the error page be more gentle? In other words, why can't the error page be more Myst than Halo?
</p>
<p><b>Figure 1 -- Angry ASP.NET Error Page</b> </p>
<p><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1378666/image08.png"><img height="456" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1378666/image0_thumb2.png" width="423" border="0"></a>
</p>
<p>This question brings us to the topic of this article. The nice thing about the ASP.NET Framework is that you can customize just about any aspect of the framework in any way that you want. This month's project is to build a friendlier, gentler ASP.NET error
 page. Our error page will use nurturing colors such as blues and grays instead of yellows and reds. Furthermore, our custom error page will randomly display different motivational messages and pictures and play different soothing background sounds.
</p>
<p>The Visual Studio Installer file that accompanies this article includes a new VB.NET and C# Project Template named Friendly Errors. If you choose this template when creating a new project, the default error message page will be replaced with a custom error
 message page (see Figure 2). </p>
<p><b>Figure 2 -- Gentle ASP.NET Error Page</b> </p>
<p><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1378666/image05.png"><img height="486" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1378666/image0_thumb1.png" width="463" border="0"></a>
</p>
<h3>Handling Application Exceptions</h3>
<p>I should admit up front that I thought that this would be an extremely easy project. The ASP.NET Framework enables you to easily create a custom error page by adding a &lt;customErrors&gt; section to your application's Web configuration (Web.config) file. For
 example, adding the following Web.config file to the root of your application causes a page named CustomError.aspx to be displayed when there is any error:
</p>
<p>&lt;configuration&gt; </p>
<p>&lt;system.web&gt; </p>
<p>&lt;customErrors mode=&quot;On&quot; defaultRedirect=&quot;~/CustomError.aspx&quot; /&gt; </p>
<p>&lt;/system.web&gt; </p>
<p>&lt;/configuration&gt; </p>
<p>Adding this configuration file to your application works great. Whenever there is an error, the user is redirected to the CustomError.aspx page automatically. You can display any message in this page that you want. For example, you can display the message
 “This site is currently undergoing scheduled maintenance”. </p>
<p>Unfortunately, however, there is no way in the CustomError.aspx page to get information about the error that caused the redirect to the CustomError.aspx page. You can display a message, but you cannot display detailed error information.
</p>
<p>Therefore, in this project, I took another approach. Instead of using the &lt;customErrors&gt; section, I handled the Application Error event. This event is raised whenever there is any unhandled exception in an application. In other words, if any code within
 a page or a component raises an exception, and the code is not wrapped by a Try...Catch block, then the Application Error event is raised.
</p>
<p>There are two ways that you can handle the Application Error event. You can handle the event in the Global.asax file or you can handle the event by creating a custom HTTP Module. I handled the Application Error event in a module named FriendlyErrorsModule.
 The code for the FriendlyErrorsModule is contained in Listing 1. </p>
<p><b>Listing 1 -- FriendlyErrorModule.cs</b> </p>
<pre class="csharpcode"><span class="kwrd">using</span> System; 

<span class="kwrd">using</span> System.Web; 

<span class="kwrd">using</span> System.Web.Configuration; 

<span class="kwrd">namespace</span> Superexpert 

{ 

<span class="rem">/// &lt;summary&gt; </span>

<span class="rem">/// Handles all unhanlded exceptions in an application </span>

<span class="rem">/// &lt;/summary&gt; </span>

<span class="kwrd">public</span> <span class="kwrd">class</span> FriendlyErrorsModule : IHttpModule 

{ 

<span class="kwrd">  public</span> <span class="kwrd">void</span> Init(HttpApplication app) 

  { 

    app.Error &#43;= <span class="kwrd">new</span> EventHandler(app_Error); 

  } 

<span class="rem">  /// &lt;summary&gt; </span>

<span class="rem">  /// When debug mode is enabled, display </span>

<span class="rem">  /// friendly error page </span>

<span class="rem">  /// &lt;/summary&gt; </span>

<span class="kwrd">  void</span> app_Error(<span class="kwrd">object</span> sender, EventArgs e) 

  { 

    HttpApplication app = (HttpApplication)sender; 

    HttpContext context = app.Context; 

    Exception error = context.Server.GetLastError().GetBaseException(); 

    context.Response.Clear(); 

    CompilationSection compilationConfig = (CompilationSection)WebConfigurationManager.GetWebApplicationSection(<span class="str">&quot;system.web/compilation&quot;</span>); 

<span class="kwrd">    if</span> (compilationConfig.Debug) 

      context.Server.Transfer(<span class="str">&quot;~/FriendlyErrors/Debug.aspx&quot;</span>); 

<span class="kwrd">    else</span> 

      context.Server.Transfer(<span class="str">&quot;~/FriendlyErrors/Public.aspx&quot;</span>); 

  } 

<span class="kwrd">  public</span> <span class="kwrd">void</span> Dispose() 

  { 

  } 

} 

} 

</pre>
<style type="text/css">
<!--
.csharpcode, .csharpcode 
	{font-size:small;
	color:black;
	font-family:consolas,"Courier New",courier,monospace;
	background-color:#ffffff}
.csharpcode 
	{margin:0em}
.csharpcode .rem
	{color:#008000}
.csharpcode .kwrd
	{color:#0000ff}
.csharpcode .str
	{color:#006080}
.csharpcode .op
	{color:#0000c0}
.csharpcode .preproc
	{color:#cc6633}
.csharpcode .asp
	{background-color:#ffff00}
.csharpcode .html
	{color:#800000}
.csharpcode .attr
	{color:#ff0000}
.csharpcode .alt
	{background-color:#f4f4f4;
	width:100%;
	margin:0em}
.csharpcode .lnum
	{color:#606060}
-->
</style>
<p><br>
<b>Listing 1 -- FriendlyErrorModule.vb</b> </p>
<p>&nbsp;</p>
<pre class="csharpcode"><span class="kwrd">Imports</span> System 

<span class="kwrd">Imports</span> System.Web 

<span class="kwrd">Imports</span> System.Web.Configuration 

<span class="kwrd">Namespace</span> Superexpert 

<span class="rem">''' &lt;summary&gt; </span>

<span class="rem">''' Handles all unhanlded exceptions in an application </span>

<span class="rem">''' &lt;/summary&gt; </span>

<span class="kwrd">Public</span> <span class="kwrd">Class</span> FriendlyErrorsModule 

<span class="kwrd">Implements</span> IHttpModule 

<span class="kwrd">  Public</span> <span class="kwrd">Sub</span> Init(<span class="kwrd">ByVal</span> app <span class="kwrd">As</span> HttpApplication) <span class="kwrd">Implements</span> IHttpModule.Init 

<span class="kwrd">    AddHandler</span> app.<span class="kwrd">Error</span>, <span class="kwrd">AddressOf</span> app_Error 

<span class="kwrd">  End</span> <span class="kwrd">Sub</span> 

<span class="rem">  ''' &lt;summary&gt; </span>

<span class="rem">  ''' When debug mode is enabled, display </span>

<span class="rem">  ''' friendly error page </span>

<span class="rem">  ''' &lt;/summary&gt; </span>

<span class="kwrd">  Sub</span> app_Error(<span class="kwrd">ByVal</span> sender <span class="kwrd">As</span> <span class="kwrd">Object</span>, <span class="kwrd">ByVal</span> e <span class="kwrd">As</span> EventArgs) 

<span class="kwrd">    Dim</span> app <span class="kwrd">As</span> HttpApplication = <span class="kwrd">CType</span>(sender, HttpApplication) 

<span class="kwrd">    Dim</span> context <span class="kwrd">As</span> HttpContext = app.Context 

    context.Response.Clear() 

<span class="kwrd">    Dim</span> compilationConfig <span class="kwrd">As</span> CompilationSection = <span class="kwrd">CType</span>(WebConfigurationManager.GetWebApplicationSection(<span class="str">&quot;system.web/compilation&quot;</span>), CompilationSection) 

<span class="kwrd">    If</span> (compilationConfig.Debug) <span class="kwrd">Then</span> 

      context.Server.Transfer(<span class="str">&quot;~/FriendlyErrors/Debug.aspx&quot;</span>) 

<span class="kwrd">    Else</span> 

      context.Server.Transfer(<span class="str">&quot;~/FriendlyErrors/Public.aspx&quot;</span>) 

<span class="kwrd">    End</span> <span class="kwrd">If</span> 

<span class="kwrd">  End</span> <span class="kwrd">Sub</span> 

<span class="kwrd">  Public</span> <span class="kwrd">Sub</span> Dispose() <span class="kwrd">Implements</span> IHttpModule.Dispose 

<span class="kwrd">  End</span> <span class="kwrd">Sub</span> 

<span class="kwrd">End</span> <span class="kwrd">Class</span> 

<span class="kwrd">End</span> <span class="kwrd">Namespace</span> 

</pre>
<style type="text/css">
<!--
.csharpcode, .csharpcode 
	{font-size:small;
	color:black;
	font-family:consolas,"Courier New",courier,monospace;
	background-color:#ffffff}
.csharpcode 
	{margin:0em}
.csharpcode .rem
	{color:#008000}
.csharpcode .kwrd
	{color:#0000ff}
.csharpcode .str
	{color:#006080}
.csharpcode .op
	{color:#0000c0}
.csharpcode .preproc
	{color:#cc6633}
.csharpcode .asp
	{background-color:#ffff00}
.csharpcode .html
	{color:#800000}
.csharpcode .attr
	{color:#ff0000}
.csharpcode .alt
	{background-color:#f4f4f4;
	width:100%;
	margin:0em}
.csharpcode .lnum
	{color:#606060}
-->
</style>
<p>The class in Listing 1 implements the IHttpModule interface. This interface has two methods that you must implement: Init() and Dispose(). In Listing 1, the Init() method is used to wire the Application Error event to a handler named app_Error.
</p>
<p>The app_Error handler checks whether debugging is enabled in the Web.config file. If debugging is enabled, then the user is transferred to a page named Debug.aspx whenever there is an error. Otherwise, if debugging is not enabled, the user is transferred
 to a page named Public.aspx. </p>
<h3>Creating a Custom Error Page</h3>
<p>The last part of this project involved creating the error page itself. The custom error page is named Debug.aspx. This page does a number of different things.
</p>
<p>First, the page displays detailed error information. To get detailed error information, you must create an instance of the System.Diagnostics.StackTrace class. You can take advantage of the StackTrace class to get the name of the page associated with the
 error as well as the source code that caused the error. </p>
<p>The Friendly Errors Project Template includes a class named FriendlyError. This class includes methods for retrieving detailed error information. the Debug.aspx page uses the FriendlyError class behind the scenes.
</p>
<p>The Debug.aspx page also displays a random picture. You can modify the pictures that the Debug.aspx page displays by modifying the contents of the FriendlyErrors/Pictures folder. The Debug.aspx page randomly displays one picture from this folder.
</p>
<p>You can add any pictures to this folder that you want. For example, you can add baby pictures and motivational pictures of your favorite foods or persons.
</p>
<p>The Debug.aspx page also displays a random motivational message. You can modify the motivational messages displayed by the Debug.aspx page by modifying the FriendlyErrors/Messages/Messages.xml file. This XML file contains a list of &lt;message&gt; elements that
 contain each of the motivational messages. </p>
<p>Finally, the Debug.aspx page plays a background sound. The page uses the &lt;object&gt; tag so that the background sound will play correctly in both Microsoft Internet Explorer and Mozilla Firefox. You can customize the background sounds used by the Debug.aspx
 page by modifying the contents of the FriendlyErrors/Sounds folder. The Debug.aspx page randomly plays a sound from this folder.
</p>
<p>Again, you can add any sound file to this folder that you please. By default, the folder contains soothing chime sounds. If you want, you could add drop other motivational sounds into this folder such as Homer Simpson saying Doh!
</p>
<h3>Testing the Custom Error Page</h3>
<p>You'll see the custom error page, Debug.aspx, whenever there is any unhandled exception in your project. Don't worry, unless you are the perfect programmer, you'll see the Debug.aspx pretty quickly when developing an application when using the Friendly Errors
 Project Template. </p>
<p>If you insist on intentionally creating an error in your application, then you can use the page in Listing 2. Both the C# and VB.NET versions of this page cause an exception that causes the Debug.aspx page to be displayed.
</p>
<p><b>Listing 2 -- BadPage.aspx (C#)</b> </p>
<pre class="csharpcode">&lt;%@ Page Language=<span class="str">&quot;C#&quot;</span> %&gt; 

&lt;!DOCTYPE html PUBLIC <span class="str">&quot;-//W3C//DTD XHTML 1.0 Transitional//EN&quot;</span> <span class="str">&quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd&quot;</span>&gt; 

&lt;script runat=<span class="str">&quot;server&quot;</span>&gt; 

<span class="kwrd">void</span> Page_Load() 

{ 

<span class="kwrd">  int</span> zero = 0; 

  Response.Write(1/zero); 

} 

&lt;/script&gt; 

&lt;html xmlns=<span class="str">&quot;http://www.w3.org/1999/xhtml&quot;</span> &gt; 

&lt;head runat=<span class="str">&quot;server&quot;</span>&gt; 

&lt;title&gt;Bad Page&lt;/title&gt; 

&lt;/head&gt; 

&lt;body&gt; 

&lt;form id=<span class="str">&quot;form1&quot;</span> runat=<span class="str">&quot;server&quot;</span>&gt; 

&lt;div&gt; 

I am a bad page 

&lt;/div&gt; 

&lt;/form&gt; 

&lt;/body&gt; 

&lt;/html&gt; 

</pre>
<style type="text/css">
<!--
.csharpcode, .csharpcode 
	{font-size:small;
	color:black;
	font-family:consolas,"Courier New",courier,monospace;
	background-color:#ffffff}
.csharpcode 
	{margin:0em}
.csharpcode .rem
	{color:#008000}
.csharpcode .kwrd
	{color:#0000ff}
.csharpcode .str
	{color:#006080}
.csharpcode .op
	{color:#0000c0}
.csharpcode .preproc
	{color:#cc6633}
.csharpcode .asp
	{background-color:#ffff00}
.csharpcode .html
	{color:#800000}
.csharpcode .attr
	{color:#ff0000}
.csharpcode .alt
	{background-color:#f4f4f4;
	width:100%;
	margin:0em}
.csharpcode .lnum
	{color:#606060}
-->
</style>
<p><b>Listing 2 -- BadPage.aspx (VB.NET)</b> </p>
<pre class="csharpcode">&lt;%@ Page Language=<span class="str">&quot;VB&quot;</span> %&gt; 

&lt;!DOCTYPE html <span class="kwrd">PUBLIC</span> <span class="str">&quot;-//W3C//DTD XHTML 1.0 Transitional//EN&quot;</span> <span class="str">&quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd&quot;</span>&gt; 

&lt;script runat=<span class="str">&quot;server&quot;</span>&gt; 

<span class="kwrd">Sub</span> Page_Load() 

<span class="kwrd">  Dim</span> Blow 

  Blow.Up() 

<span class="kwrd">End</span> <span class="kwrd">Sub</span> 

&lt;/script&gt; 

&lt;html xmlns=<span class="str">&quot;http://www.w3.org/1999/xhtml&quot;</span> &gt; 

&lt;head runat=<span class="str">&quot;server&quot;</span>&gt; 

&lt;title&gt;Bad Page&lt;/title&gt; 

&lt;/head&gt; 

&lt;body&gt; 

&lt;form id=<span class="str">&quot;form1&quot;</span> runat=<span class="str">&quot;server&quot;</span>&gt; 

&lt;div&gt; 

I am a bad page 

&lt;/div&gt; 

&lt;/form&gt; 

&lt;/body&gt; 

&lt;/html&gt; 

</pre>
<h3>Conclusion</h3>
<p>The purpose of this month's column is to demonstrate that you can customize just about any aspect of the ASP.NET Framework: including the default error page. If you are going to spend countless hours staring at one particular page (and I've spent an embarrassing
 number of hours of my life staring at the error page) then you might as well make the experience pleasant.</p>
 <img src="http://m.webtrends.com/dcs1wotjh10000w0irc493s0e_6x1g/njs.gif?dcssip=channel9.msdn.com&dcsuri=http://channel9.msdn.com/Niners/c4f.Stephen-Walther/Posts/RSS&WT.dl=0&WT.entryid=Entry:RSSView:3b0fb3d0bb0344cebad29e7600d6c4aa">]]></description>
      <comments>http://channel9.msdn.com/coding4fun/articles/Displaying-Gentle-Error-Messages-with-ASPNET</comments>
      <itunes:summary>



&amp;nbsp;
Learn how to display gentler error messages when errors are encountered while developing ASP.NET applications. In this article, Stephen Walther shows you how you can modify the default ASP.NET error page so that it displays
 motivational sounds, messages, and pictures. 



Stephen Walther
Stephen&#39;s Blog

Difficulty: Easy
Time Required: 
Less than 1 hour
Cost: Free
Software: Visual Web Developer 2005 Express Edition
Hardware: 
Download: Download








 
I fly out to companies and teach workshops on building ASP.NET applications to developers new to the ASP.NET framework. Typically a developer starts out excited to learn something new. Unfortunately, a developer&#39;s first experience of the ASP.NET framework
 is often the error page -- the angry page with the yellow background and the red error message.
 
When a novice developer encounters their first error message, I try to be reassuring. I explain that errors are normal and good and that an ASP.NET developer will view the error page at least half a billion times while developing a project of any reasonable
 complexity. After all, the mark of a good development framework is that it throws a lot of errors at you. A framework that throws a lot of errors prevents you from doing something stupid and deploying a buggy application into production.
 
However, the question remains: why does the ASP.NET Framework seem so angry? Why the harsh yellow background and bold red error messages (see Figure 1)? Why can&#39;t the error page be more gentle? In other words, why can&#39;t the error page be more Myst than Halo?
 
Figure 1 -- Angry ASP.NET Error Page  

 
This question brings us to the topic of this article. The nice thing about the ASP.NET Framework is that you can customize just about any aspect of the framework in any way that you want. This month&#39;s project is to build a friendlier, gentler ASP.NET error
 page. Our error page will use nurturing colors such as blues and grays instead of yellows and reds. Furthermore, ou</itunes:summary>
      <link>http://channel9.msdn.com/coding4fun/articles/Displaying-Gentle-Error-Messages-with-ASPNET</link>
      <pubDate>Fri, 29 Dec 2006 03:51:52 GMT</pubDate>
      <guid isPermaLink="false">http://channel9.msdn.com/coding4fun/articles/Displaying-Gentle-Error-Messages-with-ASPNET</guid>
      <media:thumbnail url="http://ecn.channel9.msdn.com/o9/c4f/images/1378666_100.jpg" height="75" width="100"></media:thumbnail>
      <media:thumbnail url="http://ecn.channel9.msdn.com/o9/c4f/images/1378666_220.jpg" height="165" width="220"></media:thumbnail>      
      <dc:creator>Stephen Walther</dc:creator>
      <itunes:author>Stephen Walther</itunes:author>
      <slash:comments>11</slash:comments>
      <wfw:commentRss>http://channel9.msdn.com/coding4fun/articles/Displaying-Gentle-Error-Messages-with-ASPNET/RSS</wfw:commentRss>
      <category>Web</category>
      <category>web miscellaneous</category>
    </item>    
</channel>
</rss>