<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2titles.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemtitles.css"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" 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:copyright="http://blogs.law.harvard.edu/tech/rss" xmlns:image="http://purl.org/rss/1.0/modules/image/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">
    <channel>
        <title>Stephen Walther on ASP.NET</title>
        <link>http://stephenwalther.com/blog/Default.aspx</link>
        <description />
        <language>en-US</language>
        <copyright>Stephen Walther</copyright>
        <generator>Subtext Version 2.5.1.20</generator>
        <image>
            <title>Stephen Walther on ASP.NET</title>
            <url>http://stephenwalther.com/blog/images/RSS2Image.gif</url>
            <link>http://stephenwalther.com/blog/Default.aspx</link>
            <width>77</width>
            <height>60</height>
        </image>
        <atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/StephenWalther" /><feedburner:info uri="stephenwalther" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><feedburner:feedFlare href="http://add.my.yahoo.com/rss?url=http%3A%2F%2Ffeeds.feedburner.com%2FStephenWalther" src="http://us.i1.yimg.com/us.yimg.com/i/us/my/addtomyyahoo4.gif">Subscribe with My Yahoo!</feedburner:feedFlare><feedburner:feedFlare href="http://www.newsgator.com/ngs/subscriber/subext.aspx?url=http%3A%2F%2Ffeeds.feedburner.com%2FStephenWalther" src="http://www.newsgator.com/images/ngsub1.gif">Subscribe with NewsGator</feedburner:feedFlare><feedburner:feedFlare href="http://www.bloglines.com/sub/http://feeds.feedburner.com/StephenWalther" src="http://www.bloglines.com/images/sub_modern11.gif">Subscribe with Bloglines</feedburner:feedFlare><feedburner:feedFlare href="http://www.netvibes.com/subscribe.php?url=http%3A%2F%2Ffeeds.feedburner.com%2FStephenWalther" src="http://www.netvibes.com/img/add2netvibes.gif">Subscribe with Netvibes</feedburner:feedFlare><feedburner:feedFlare href="http://fusion.google.com/add?feedurl=http%3A%2F%2Ffeeds.feedburner.com%2FStephenWalther" src="http://buttons.googlesyndication.com/fusion/add.gif">Subscribe with Google</feedburner:feedFlare><feedburner:feedFlare href="http://www.pageflakes.com/subscribe.aspx?url=http%3A%2F%2Ffeeds.feedburner.com%2FStephenWalther" src="http://www.pageflakes.com/ImageFile.ashx?instanceId=Static_4&amp;fileName=ATP_blu_91x17.gif">Subscribe with Pageflakes</feedburner:feedFlare><feedburner:feedFlare href="http://www.plusmo.com/add?url=http%3A%2F%2Ffeeds.feedburner.com%2FStephenWalther" src="http://plusmo.com/res/graphics/fbplusmo.gif">Subscribe with Plusmo</feedburner:feedFlare><feedburner:feedFlare href="http://www.live.com/?add=http%3A%2F%2Ffeeds.feedburner.com%2FStephenWalther" src="http://tkfiles.storage.msn.com/x1piYkpqHC_35nIp1gLE68-wvzLZO8iXl_JMledmJQXP-XTBOLfmQv4zhj4MhcWEJh_GtoBIiAl1Mjh-ndp9k47If7hTaFno0mxW9_i3p_5qQw">Subscribe with Live.com</feedburner:feedFlare><feedburner:feedFlare href="http://www.addtoany.com/?linkname=Stephen%20Walther%20on%20ASP.NET&amp;linkurl=http%3A%2F%2Ffeeds.feedburner.com%2FStephenWalther&amp;type=feed" src="http://www.addtoany.com/addfr-b.gif">Add to Any Feed Reader</feedburner:feedFlare><feedburner:browserFriendly>Get the latest news, tips, and articles on ASP.NET MVC by subscribing to Stephen Walther's blog.</feedburner:browserFriendly><item>
            <title>ASP.NET MVC + Selenium + IISExpress</title>
            <category>AJAX</category>
            <category>ASP.NET</category>
            <category>ASP.NET MVC</category>
            <category>JavaScript</category>
            <category>TDD</category>
            <category>jQuery</category>
            <link>http://feedproxy.google.com/~r/StephenWalther/~3/WiMe-WdAPBg/asp-net-mvc-selenium-iisexpress.aspx</link>
            <description>&lt;p&gt;The goal of this blog entry is to explain how you can create integration tests for ASP.NET MVC applications by using a combination of Selenium WebDriver and IISExpress. &lt;/p&gt;  &lt;p&gt;Integration tests are useful when you want to test an entire user story. For example, you might want to test whether a user can successfully add an item to a shopping cart. Adding an item to a shopping cart might require the execution of C# code, database code, and JavaScript code. Using an integration test, you can verify that the entire process of buying an item from your website works. &lt;/p&gt;  &lt;p&gt;Typically, an integration test is contrasted with a &lt;i&gt;unit test&lt;/i&gt;. A unit test is used to test a unit of code in isolation. A unit test is typically used to verify the behavior of a single method (Does the AddNumbers() method return the right value?). An integration test is used to test many components and methods working together (Can a user add an item to a shopping cart?).&lt;/p&gt;  &lt;p&gt;Normally, unit tests are created by developers while they write the code for an application. Integration tests, in contrast, are typically written by Quality Assurance engineers after code has been written.&lt;/p&gt;  &lt;p&gt;Another important difference between unit tests and integration tests are the speed of the tests. Unit tests must be fast. Typically, you run your unit tests each and every time a developer checks in code. Integration tests, in contrast, might be much slower than unit tests. Typically, you run all of your integration tests once a day in the middle of the night. Because integration tests require the execution of actual browsers, integration tests can be agonizingly slow.&lt;/p&gt;  &lt;p&gt;The ASP.NET MVC framework was designed from the ground up to make it easy to write unit tests for your code. For example, you can unit test your controller actions without spinning up a web server. &lt;/p&gt;  &lt;p&gt;On the other hand, the ASP.NET MVC framework has no built-in support for integration tests. If you want to write integration tests then you need a way to simulate the interactions of a web browser with your ASP.NET MVC application. In this blog entry, you learn how to use the open-source Selenium WebDriver testing framework to build integration tests which work with ASP.NET MVC. &lt;/p&gt;  &lt;h3&gt;Spinning Up IISExpress when Executing a Test&lt;/h3&gt;  &lt;p&gt;In an integration test, you perform a test against a live website. Therefore, the first problem that we must solve is how to launch a live website automatically when executing tests with Visual Studio.&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;======== Begin Note ======&lt;/p&gt;    &lt;p&gt;Visual Studio supports a type of test called an ASP.NET Unit Test which starts the ASP.NET Developer Web Server (Cassini) automatically. In other words, an ASP.NET Unit Test does exactly what we want. You create an ASP.NET Unit Test by adding three special attributes to a test method:&lt;/p&gt;    &lt;p&gt;&lt;font face="Consolas"&gt;[TestMethod()]&lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;font face="Consolas"&gt;[HostType("ASP.NET")]&lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;font face="Consolas"&gt;[UrlToTest("http://localhost:25153/Home/Index")]&lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;font face="Consolas"&gt;[AspNetDevelopmentServerHost(@"C:\TestSelenium", "/")]&lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;font face="Consolas"&gt;public void TestMethod1() {&lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;font face="Consolas"&gt;…&lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;font face="Consolas"&gt;}&lt;/font&gt;&lt;/p&gt;    &lt;p&gt;Unfortunately, ASP.NET Unit Tests only work with ASP.NET Web Form applications and not ASP.NET MVC applications. The [URLToTest] attribute must point at an ASP.NET Web Forms page. This attribute does not work with ASP.NET MVC controller actions. Therefore, if we want to launch a web server when performing a test with an ASP.NET MVC application, we must take on the responsibility of launching the web server ourselves. &lt;/p&gt;    &lt;p&gt;========= End Note ==============&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;We’ll start a live website by taking advantage of IISExpress. IISExpress is a lightweight version of IIS that you can start from the command-line. You get IISExpress automatically when you install Visual Studio 2010 Service Pack 1 using the &lt;a href="http://www.microsoft.com/web/downloads/platform.aspx"&gt;Microsoft Web Platform Installer&lt;/a&gt;. IISExpress is also available as a separate download using the Web Platform Installer.&lt;/p&gt;  &lt;p&gt;After you install IISExpress, you can run iisexpress.exe from the command line. Open a command prompt and switch to either your &lt;i&gt;Program Files\IIS Express&lt;/i&gt; or &lt;i&gt;Program Files (x86)\IIS Express&lt;/i&gt; directory (depending on your operating system). Next, enter the following command to launch a website located at the path c:\MyWebsite using port 2020:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;iisexpress /path:c:\MyWebsite /port:2020&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;The IISExpress web server will keep running until you hit Q to quit. Each time you make a request against the MyWebsite site using a web browser, you’ll see the request logged to the window.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://stephenwalther.com/blog/images/StephenWalther_com/blog/Windows-Live-Writer/aaf27dc226dc_A7B1/clip_image002_2.jpg"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="clip_image002" border="0" alt="clip_image002" src="http://stephenwalther.com/blog/images/StephenWalther_com/blog/Windows-Live-Writer/aaf27dc226dc_A7B1/clip_image002_thumb.jpg" width="628" height="218" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Warning: You can only have one instance of IISExpress open at a particular port at a time. If you attempt to open IISExpress with the same port number twice then you will get an error.&lt;/p&gt;  &lt;p&gt;We want to automate this process of starting IISExpress so that we can start IISExpress automatically in our tests. Listing 1 contains a base class named SeleniumTest. &lt;/p&gt;  &lt;p&gt;Listing 1 – SeleniumTest.cs (First Attempt)&lt;/p&gt;  &lt;pre class="brush: csharp;"&gt;using System;
using System.Diagnostics;
using System.IO;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace TestSelenium.Tests {
    
    [TestClass]
    public abstract class SeleniumTest {

        const int iisPort = 2020;
        private string _applicationName;
        private Process _iisProcess;

        protected SeleniumTest(string applicationName) {
            _applicationName = applicationName;
        }

        [TestInitialize]
        public void TestInitialize() {
            // Start IISExpress
            StartIIS();
        }


        [TestCleanup]
        public void TestCleanup() {
            // Ensure IISExpress is stopped
            if (_iisProcess.HasExited == false) {
                _iisProcess.Kill();
            }
        }



        private void StartIIS() {
            var applicationPath = GetApplicationPath(_applicationName);
            var programFiles = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles);

            _iisProcess = new Process();
            _iisProcess.StartInfo.FileName = programFiles + "\\IIS Express\\iisexpress.exe";
            _iisProcess.StartInfo.Arguments = string.Format("/path:\"{0}\" /port:{1}", applicationPath, iisPort);
            _iisProcess.Start();
        }


        protected virtual string GetApplicationPath(string applicationName) {
            var solutionFolder = Path.GetDirectoryName(Path.GetDirectoryName(Path.GetDirectoryName(AppDomain.CurrentDomain.BaseDirectory)));
            return Path.Combine(solutionFolder, applicationName);
        }


        public string GetAbsoluteUrl(string relativeUrl) {
            if (!relativeUrl.StartsWith("/")) {
                relativeUrl = "/" + relativeUrl;
            }
            return String.Format("http://localhost:{0}{1}", iisPort, relativeUrl);
        }


    }
}&lt;/pre&gt;

&lt;p&gt;Notice that the class in Listing 1 has a required parameter for its constructor. You must specify the name of the application being tested. The base class in Listing 1 assumes that your solution contains at least two projects: the MVC project being tested and the test project itself (see Figure 2). The GetApplicationPath() method calculates the path of the ASP.NET MVC application being tested relative to the path of the Test project.&lt;/p&gt;

&lt;p&gt;Figure 2 – Solution Structure&lt;/p&gt;

&lt;p&gt;&lt;a href="http://stephenwalther.com/blog/images/StephenWalther_com/blog/Windows-Live-Writer/aaf27dc226dc_A7B1/clip_image003_2.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="clip_image003" border="0" alt="clip_image003" src="http://stephenwalther.com/blog/images/StephenWalther_com/blog/Windows-Live-Writer/aaf27dc226dc_A7B1/clip_image003_thumb.png" width="274" height="161" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The SeleniumTest class includes a StartIIS() method which uses the .NET framework Process class to start IISExpress in a new process. The StartIIS() method is called by the TestInitialize() method. Immediately before each test is run, a new instance of IISExpress is started. In the TestCleanup() method, after the test completes, the IISExpress instance is stopped.&lt;/p&gt;

&lt;p&gt;The SeleniumTest class is a base class. Listing 2 illustrates how you can use the SeleniumTest base class with an actual test.&lt;/p&gt;

&lt;p&gt;Listing 2 – A simple integration test&lt;/p&gt;

&lt;pre class="brush: csharp;"&gt;using System.Net;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using OpenQA.Selenium;

namespace TestSelenium.Tests.Controllers {

    [TestClass]
    public class HomeControllerTests:SeleniumTest {

        public HomeControllerTests() : base("MyMVCApp") { }

        [TestMethod]
        public void TestMethod1() {
            // Arrange
            var client = new WebClient();
            
            // Act
            var result = client.DownloadString(this.GetAbsoluteUrl("/home/index")
);

            // Assert
            StringAssert.Contains(result, "hello");
        }

    }
}&lt;/pre&gt;

&lt;p&gt;The integration test is contained in the TestMethod1() method. This method creates a new instance of the .NET Framework WebClient class. The WebClient class represents a simple Web Browser. Next, the WebClient class is used to perform a GET request against an ASP.NET MVC controller action named /home/index. If the ASP.NET MVC view returned by the /home/index action includes the string “hello” then the test completes successfully (see Figure 3). &lt;/p&gt;

&lt;p&gt;Figure 3 – An integration test with a successful conclusion&lt;/p&gt;

&lt;p&gt;&lt;a href="http://stephenwalther.com/blog/images/StephenWalther_com/blog/Windows-Live-Writer/aaf27dc226dc_A7B1/clip_image004_2.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="clip_image004" border="0" alt="clip_image004" src="http://stephenwalther.com/blog/images/StephenWalther_com/blog/Windows-Live-Writer/aaf27dc226dc_A7B1/clip_image004_thumb.png" width="502" height="196" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Each time you run the tests in your solution, IISExpress is started automatically. In fact, IISExpress is started and stopped for each test. This can make running the tests slow. However, by stopping and starting IISExpress with each test, you are providing more test isolation. For example, if one test crashes IIS then IIS will work again for the next test.&lt;/p&gt;

&lt;p&gt;In this section, we used the WebClient class to make requests against our ASP.NET MVC application. This is a useful, but limited class. We want to be able to simulate actual browsers such as Internet Explorer, Firefox, and Google Chrome. We want to be able to easily test JavaScript/jQuery code. In the next section, we’ll use Selenium WebDriver to drive actual web browsers in our integration tests.&lt;/p&gt;

&lt;h3&gt;Using Selenium WebDriver&lt;/h3&gt;

&lt;p&gt;Selenium is an open-source browser automation testing framework. You can use Selenium WebDriver to control (drive) browsers such as Internet Explorer, Firefox, and Google Chrome from C# code. It is the most mature integration testing framework.&lt;/p&gt;

&lt;p&gt;The easiest way to install Selenium WebDriver is to use NuGet. Within Visual Studio, select the menu option Tools, Library Package Manager Console to open the Package Manager console. Within the Package Manager Console, make sure that you select your Test project from the dropdown list. Finally, execute the following command to install Selenium Web Driver (see Figure 4):&lt;/p&gt;

&lt;p&gt;Install-Package Selenium.WebDriver&lt;/p&gt;

&lt;p&gt;Figure 4 – Installing Selenium WebDriver&lt;/p&gt;

&lt;p&gt;&lt;a href="http://stephenwalther.com/blog/images/StephenWalther_com/blog/Windows-Live-Writer/aaf27dc226dc_A7B1/clip_image006_2.jpg"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="clip_image006" border="0" alt="clip_image006" src="http://stephenwalther.com/blog/images/StephenWalther_com/blog/Windows-Live-Writer/aaf27dc226dc_A7B1/clip_image006_thumb.jpg" width="628" height="171" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can use Selenium WebDriver to control instances of Internet Explorer, Firefox, Google Chrome, and the Android browser. You don’t need to do any special configuration to start using Selenium Web Driver with Firefox.&lt;/p&gt;

&lt;p&gt;If you want to use Selenium WebDriver with Google Chrome then you first need to download chromedriver.exe from the Chromium website and add chromedriver.exe to your Test project. You can download chromedriver.exe from the Chromium download page here:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;a href="http://code.google.com/p/chromium/downloads/list"&gt;http://code.google.com/p/chromium/downloads/list&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Download the &lt;i&gt;ChromeDriver server for win32&lt;/i&gt; and add chromedriver.exe to your Test project.&lt;/p&gt;

&lt;p&gt;Finally, to get Internet Explorer to work, you need to change the Protected Mode Settings for Internet Explorer. Open Internet Explorer and choose the menu option Tools, Internet Options and select the Security tab (see Figure 5). For each zone – Internet, Local intranet, Trusted sites, Restricted sites – you need to set Protected Mode to the same value (either checked or not checked).&lt;/p&gt;

&lt;p&gt;Listing 5 – Changing Internet Explorer Protected Mode&lt;/p&gt;

&lt;p&gt;&lt;a href="http://stephenwalther.com/blog/images/StephenWalther_com/blog/Windows-Live-Writer/aaf27dc226dc_A7B1/clip_image007_2.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="clip_image007" border="0" alt="clip_image007" src="http://stephenwalther.com/blog/images/StephenWalther_com/blog/Windows-Live-Writer/aaf27dc226dc_A7B1/clip_image007_thumb.png" width="427" height="545" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After you get everything setup, you can use Selenium WebDriver to drive browsers by creating instances of the Selenium FirefoxDriver, ChromeDriver, and InternetExplorerDriver classes. Each of the driver classes implements the IWebDriver interface.&lt;/p&gt;

&lt;p&gt;Imagine, for example, that you want to test the ASP.NET MVC in Listing 3. This view contains a button and a DIV tag. When you click the button, jQuery is used to display the hidden message in the DIV tag.&lt;/p&gt;

&lt;p&gt;Listing 3 – An ASP.NET MVC View with jQuery&lt;/p&gt;

&lt;pre class="brush: xml;"&gt;&amp;lt;button id="btn"&amp;gt;Click&amp;lt;/button&amp;gt;

&amp;lt;div id="msg" style="display:none"&amp;gt;
    hello!
&amp;lt;/div&amp;gt;

&amp;lt;script src="../../Scripts/jquery-1.5.1.min.js" type="text/javascript"&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script type="text/javascript"&amp;gt;

    $("#btn").click(function () {
        $("#msg").show();
    });

&amp;lt;/script&amp;gt;&lt;/pre&gt;

&lt;p&gt;The view in Listing 3 is not a super advanced view, but it does contain features that are difficult to test without running an actual browser. The view requires JavaScript and jQuery.&lt;/p&gt;

&lt;p&gt;In order to test the view, we need to start an instance of a web browser, click the button, and verify that the hidden message is displayed.&lt;/p&gt;

&lt;p&gt;First, we need to modify our TestSelenium base class. The modified version of this class is contained in Listing 4.&lt;/p&gt;

&lt;p&gt;Listing 4 – TestSelenium.cs (final version)&lt;/p&gt;

&lt;pre class="brush: csharp;"&gt;using System;
using System.Diagnostics;
using System.IO;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using OpenQA.Selenium.Chrome;
using OpenQA.Selenium.Firefox;
using OpenQA.Selenium.IE;

namespace TestSelenium.Tests {
    
    [TestClass]
    public abstract class SeleniumTest {

        const int iisPort = 2020;
        private string _applicationName;
        private Process _iisProcess;

        protected SeleniumTest(string applicationName) {
            _applicationName = applicationName;
        }


        public FirefoxDriver FirefoxDriver { get; set; }
        public ChromeDriver ChromeDriver { get; set; }
        public InternetExplorerDriver InternetExplorerDriver { get; set; }


        [TestInitialize]
        public void TestInitialize() {
            // Start IISExpress
            StartIIS();

            // Start Selenium drivers
            this.FirefoxDriver = new FirefoxDriver();
            this.ChromeDriver = new ChromeDriver();
            this.InternetExplorerDriver = new InternetExplorerDriver();
        }


        [TestCleanup]
        public void TestCleanup() {
            // Ensure IISExpress is stopped
            if (_iisProcess.HasExited == false) {
                _iisProcess.Kill();
            }

            // Stop all Selenium drivers
            this.FirefoxDriver.Quit();
            this.ChromeDriver.Quit();
            this.InternetExplorerDriver.Quit();
        }



        private void StartIIS() {
            var applicationPath = GetApplicationPath(_applicationName);
            var programFiles = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles);

            _iisProcess = new Process();
            _iisProcess.StartInfo.FileName = programFiles + "\\IIS Express\\iisexpress.exe";
            _iisProcess.StartInfo.Arguments = string.Format("/path:\"{0}\" /port:{1}", applicationPath, iisPort);
            _iisProcess.Start();
        }


        protected virtual string GetApplicationPath(string applicationName) {
            var solutionFolder = Path.GetDirectoryName(Path.GetDirectoryName(Path.GetDirectoryName(AppDomain.CurrentDomain.BaseDirectory)));
            return Path.Combine(solutionFolder, applicationName);
        }


        public string GetAbsoluteUrl(string relativeUrl) {
            if (!relativeUrl.StartsWith("/")) {
                relativeUrl = "/" + relativeUrl;
            }
            return String.Format("http://localhost:{0}{1}", iisPort, relativeUrl);
        }


    }
}&lt;/pre&gt;

&lt;p&gt;Notice that the TestInitialize() method in Listing 4 has been modified to create an instance of the FirefoxDriver, ChromeDriver, and InternetExplorerDriver Selenium drivers. Instances of these drivers are created in TestInitialize() and then they are shutdown in the TestCleanup() method by calling Quit().&lt;/p&gt;

&lt;p&gt;Listing 5 demonstrates how you can use the FirefoxDriver to test the ASP.NET MVC view using the Firefox web browser.&lt;/p&gt;

&lt;p&gt;Listing 5 – Using the Selenium FirefoxDriver&lt;/p&gt;

&lt;pre class="brush: csharp;"&gt;using System.Net;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using OpenQA.Selenium;

namespace TestSelenium.Tests.Controllers {

    [TestClass]
    public class HomeControllerTests:SeleniumTest {

        public HomeControllerTests() : base("MyMVCApp") { }


        [TestMethod]
        public void IndexFirefoxTest() {
            // Act
            this.FirefoxDriver.Navigate().GoToUrl(this.GetAbsoluteUrl("/home/index"));
            this.FirefoxDriver.FindElement(By.Id("btn")).Click();

            // Assert
            Assert.IsTrue(this.FirefoxDriver.FindElement(By.Id("msg")).Displayed);
        }


    }
}&lt;/pre&gt;

&lt;p&gt;When you run the IndexFirefoxTest() in Listing 5, an instance of IISExpress is started. Next, instances of Firefox, Chrome, and Internet Explorer are created. The test is run and the instances of the browsers are closed.&lt;/p&gt;

&lt;p&gt;Typically, you want to run a test using an instance of all three browsers. The test in Listing 6 illustrates how you can run the same test for multiple types of browsers.&lt;/p&gt;

&lt;p&gt;Listing 6 – Running the same test for multiple browsers&lt;/p&gt;

&lt;pre class="brush: csharp;"&gt;using System.Net;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using OpenQA.Selenium;

namespace TestSelenium.Tests.Controllers {

    [TestClass]
    public class HomeControllerTests:SeleniumTest {

        public HomeControllerTests() : base("MyMVCApp") { }



        [TestMethod]
        public void IndexTest() {
            IndexTestByDriver(this.FirefoxDriver);
            IndexTestByDriver(this.ChromeDriver);
            IndexTestByDriver(this.InternetExplorerDriver);
        }

        private void IndexTestByDriver(IWebDriver driver) {
            // Act
            driver.Navigate().GoToUrl(this.GetAbsoluteUrl("/home/index"));
            driver.FindElement(By.Id("btn")).Click();

            // Assert
            Assert.IsTrue(driver.FindElement(By.Id("msg")).Displayed, driver.GetType().ToString());
        }


    }
}&lt;/pre&gt;

&lt;p&gt;In Listing 6, the IndexTest is broken into two methods. The IndexTest() method is decorated with the [TestMethod] attribute and it is this method which is called by the Visual Studio test runner. This method calls the IndexTestByDriver() method three times passing the Firefox, Chrome, and Internet Explorer Selenium drivers. &lt;/p&gt;

&lt;p&gt;Fortunately, all of the Selenium drivers implement the same IWebDriver interface. This makes it easy to write a single test which can be used with multiple types of browsers. &lt;/p&gt;

&lt;p&gt;The IWebDriver interface exposes all of the methods for controlling a web browser. For example, you can use the IWebDriver Navigate() method to navigate to a particular URL, refresh a browser, or move back and forth in browser history.&lt;/p&gt;

&lt;p&gt;You can use the IWebDriver FindElement() method to find elements by a number of different criteria including element Id, element name, class name, tag name, and link text.&lt;/p&gt;

&lt;p&gt;After you retrieve an element with FindElement(), you can use methods such as Click(), SendKeys(), and Submit() to interact with forms and links in a view. &lt;/p&gt;

&lt;h3&gt;Summary&lt;/h3&gt;

&lt;p&gt;In this blog entry, I discussed how you can use Selenium WebDriver in combination with IISExpress to create integration tests for ASP.NET MVC applications. You can use integration tests to test complex user interactions with an ASP.NET MVC application such as the entire experience of adding an item to a shopping cart.&lt;/p&gt;

&lt;p&gt;The advantage of using Selenium WebDriver is that you can use WebDriver to drive actual browser instances such as Firefox, Internet Explorer, and Google Chrome. Because actual browser instances are used, you are able to test your ASP.NET MVC applications against real browsers with all of their warts and quirks.&lt;/p&gt;&lt;img src="http://stephenwalther.com/blog/aggbug/176.aspx" width="1" height="1" /&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/StephenWalther?a=WiMe-WdAPBg:YXccTf7HJnY:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StephenWalther?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/StephenWalther/~4/WiMe-WdAPBg" height="1" width="1"/&gt;</description>
            <dc:creator>Stephen Walther</dc:creator>
            <guid isPermaLink="false">http://stephenwalther.com/blog/archive/2011/12/22/asp-net-mvc-selenium-iisexpress.aspx</guid>
            <pubDate>Thu, 22 Dec 2011 20:11:55 GMT</pubDate>
            <comments>http://stephenwalther.com/blog/archive/2011/12/22/asp-net-mvc-selenium-iisexpress.aspx#feedback</comments>
            <slash:comments>5</slash:comments>
            <wfw:commentRss>http://stephenwalther.com/blog/comments/commentRss/176.aspx</wfw:commentRss>
        <feedburner:origLink>http://stephenwalther.com/blog/archive/2011/12/22/asp-net-mvc-selenium-iisexpress.aspx</feedburner:origLink></item>
        <item>
            <title>Ajax Control Toolkit November 2011 Release</title>
            <category>ACT</category>
            <category>AJAX</category>
            <category>ASP.NET</category>
            <category>JavaScript</category>
            <link>http://feedproxy.google.com/~r/StephenWalther/~3/DQTtPXIospM/ajax-control-toolkit-november-2011-release.aspx</link>
            <description>&lt;p&gt;I’m happy to announce the November 2011 Release of the Ajax Control Toolkit. This release introduces a new Balloon Popup control and several enhancements to the existing Tabs control including support for on-demand loading of tab content, support for vertical tabs, and support for keyboard tab navigation. We also fixed the top-voted bugs associated with the Tabs control reported at CodePlex.com.&lt;/p&gt;  &lt;p&gt;You can download the new release by visiting the CodePlex website:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;a href="http://AjaxControlToolkit.CodePlex.com"&gt;http://AjaxControlToolkit.CodePlex.com&lt;/a&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Alternatively, the fast and easy way to get the latest release of the Ajax Control Toolkit is to use &lt;a href="http://nuget.org/"&gt;NuGet&lt;/a&gt;. Open your Library Package Manager console in Visual Studio 2010 and type:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://stephenwalther.com/blog/images/StephenWalther_com/blog/Windows-Live-Writer/f05c471a20b7_10C10/clip_image002_2.jpg"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image002" border="0" alt="clip_image002" src="http://stephenwalther.com/blog/images/StephenWalther_com/blog/Windows-Live-Writer/f05c471a20b7_10C10/clip_image002_thumb.jpg" width="628" height="86" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;After you install the Ajax Control Toolkit through NuGet, please do a Rebuild of your project (the menu option Build, Rebuild). After you do a Rebuild, the ajaxToolkit prefix will appear in Intellisense:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://stephenwalther.com/blog/images/StephenWalther_com/blog/Windows-Live-Writer/f05c471a20b7_10C10/clip_image003_2.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image003" border="0" alt="clip_image003" src="http://stephenwalther.com/blog/images/StephenWalther_com/blog/Windows-Live-Writer/f05c471a20b7_10C10/clip_image003_thumb.png" width="521" height="324" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;h3&gt;Using the Balloon Popup Control&lt;/h3&gt;  &lt;p&gt;Why a new Balloon Popup control? The Balloon Popup control is the second most requested new feature for the Ajax Control Toolkit according to CodePlex votes:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://stephenwalther.com/blog/images/StephenWalther_com/blog/Windows-Live-Writer/f05c471a20b7_10C10/clip_image004_2.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image004" border="0" alt="clip_image004" src="http://stephenwalther.com/blog/images/StephenWalther_com/blog/Windows-Live-Writer/f05c471a20b7_10C10/clip_image004_thumb.png" width="420" height="142" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;The Balloon Popup displays a message in a balloon when you shift focus to a control, click a control, or hover over a control. You can use the Balloon Popup, for example, to display instructions for TextBoxes which appear in a form:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://stephenwalther.com/blog/images/StephenWalther_com/blog/Windows-Live-Writer/f05c471a20b7_10C10/clip_image005_2.gif"&gt;&lt;img style="display: inline" title="clip_image005" alt="clip_image005" src="http://stephenwalther.com/blog/images/StephenWalther_com/blog/Windows-Live-Writer/f05c471a20b7_10C10/clip_image005_thumb.gif" width="456" height="272" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Here’s the code used to create the Balloon Popup:&lt;/p&gt;  &lt;pre class="brush: xml;"&gt;&amp;lt;ajaxToolkit:ToolkitScriptManager ID="tsm1" runat="server" /&amp;gt;

&amp;lt;asp:TextBox
    ID="txtFirstName"
    Runat="server" /&amp;gt;

&amp;lt;asp:Panel ID="pnlFirstNameHelp" runat="server"&amp;gt;
    Please enter your first name    
&amp;lt;/asp:Panel&amp;gt;

&amp;lt;ajaxToolkit:BalloonPopupExtender 
    TargetControlID="txtFirstName" 
    BalloonPopupControlID="pnlFirstNameHelp"
    BalloonSize="Small"
    UseShadow="true"
    runat="server" /&amp;gt;&lt;/pre&gt;

&lt;p&gt;You also can use the Balloon Popup to explain hard to understand words in a text document:&lt;/p&gt;

&lt;p&gt;&lt;a href="http://stephenwalther.com/blog/images/StephenWalther_com/blog/Windows-Live-Writer/f05c471a20b7_10C10/clip_image006_2.gif"&gt;&lt;img style="display: inline" title="clip_image006" alt="clip_image006" src="http://stephenwalther.com/blog/images/StephenWalther_com/blog/Windows-Live-Writer/f05c471a20b7_10C10/clip_image006_thumb.gif" width="732" height="308" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here’s how you display the Balloon Popup when you hover over the link:&lt;/p&gt;

&lt;pre class="brush: xml;"&gt;The point of the conversation was 
&amp;lt;asp:HyperLink ID="lnkObfuscate" Text="obfuscated" CssClass="hardWord" runat="server" /&amp;gt; 
by his incessant coughing.

&amp;lt;ajaxToolkit:ToolkitScriptManager ID="tsm1" runat="server" /&amp;gt;
&amp;lt;asp:Panel id="pnlObfuscate" Runat="server"&amp;gt;
    To bewilder or render something obscure
&amp;lt;/asp:Panel&amp;gt;
&amp;lt;ajaxToolkit:BalloonPopupExtender
    TargetControlID="lnkObfuscate"
    BalloonPopupControlID="pnlObfuscate"
    BalloonStyle="Cloud"
    UseShadow="true"
    DisplayOnMouseOver="true"
    Runat="server" /&amp;gt;&lt;/pre&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;There are four important properties which you need to know about when using the Balloon Popup control:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;BalloonSize – The three balloon sizes are Small, Medium, and Large. &lt;/p&gt;
  &lt;/li&gt;

  &lt;li&gt;
    &lt;p&gt;BalloonStyle -- The two built-in styles are Rectangle and Cloud. &lt;/p&gt;
  &lt;/li&gt;

  &lt;li&gt;
    &lt;p&gt;UseShadow – When true, a drop shadow appears behind the popup. &lt;/p&gt;
  &lt;/li&gt;

  &lt;li&gt;
    &lt;p&gt;Position – Can have the values Auto, BottomLeft, BottomRight, TopLeft, TopRight. When set to Auto, which is the default, the Balloon Popup will appear where it has the most screen real estate.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The following screenshots illustrates how these settings affect the appearance of the Balloon Popup:&lt;/p&gt;

&lt;p&gt;&lt;a href="http://stephenwalther.com/blog/images/StephenWalther_com/blog/Windows-Live-Writer/f05c471a20b7_10C10/clip_image007_2.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image007" border="0" alt="clip_image007" src="http://stephenwalther.com/blog/images/StephenWalther_com/blog/Windows-Live-Writer/f05c471a20b7_10C10/clip_image007_thumb.png" width="651" height="448" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="http://stephenwalther.com/blog/images/StephenWalther_com/blog/Windows-Live-Writer/f05c471a20b7_10C10/clip_image009_2.jpg"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image009" border="0" alt="clip_image009" src="http://stephenwalther.com/blog/images/StephenWalther_com/blog/Windows-Live-Writer/f05c471a20b7_10C10/clip_image009_thumb.jpg" width="628" height="409" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="http://stephenwalther.com/blog/images/StephenWalther_com/blog/Windows-Live-Writer/f05c471a20b7_10C10/clip_image010_2.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image010" border="0" alt="clip_image010" src="http://stephenwalther.com/blog/images/StephenWalther_com/blog/Windows-Live-Writer/f05c471a20b7_10C10/clip_image010_thumb.png" width="482" height="337" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;Customizing the Balloon Popup&lt;/h4&gt;

&lt;p&gt;You can customize the appearance of the Balloon Popup by creating your own Cascading Style Sheet and Sprite. The Ajax Control Toolkit sample site includes a sample of a custom Oval Balloon Popup style: &lt;/p&gt;

&lt;p&gt;&lt;a href="http://stephenwalther.com/blog/images/StephenWalther_com/blog/Windows-Live-Writer/f05c471a20b7_10C10/clip_image011_2.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image011" border="0" alt="clip_image011" src="http://stephenwalther.com/blog/images/StephenWalther_com/blog/Windows-Live-Writer/f05c471a20b7_10C10/clip_image011_thumb.png" width="505" height="275" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This custom style was created by using a custom Cascading Style Sheet and image. You point the Balloon Popup at a custom Cascading Style Sheet and Cascading Style Sheet class by using the CustomCssUrl and CustomClassName properties like this:&lt;/p&gt;

&lt;pre class="brush: xml;"&gt;&amp;lt;asp:TextBox ID="txtCustom" autocomplete="off" runat="server" /&amp;gt;
&amp;lt;br /&amp;gt;
&amp;lt;asp:Panel ID="Panel3" runat="server"&amp;gt;
    This is a custom BalloonPopupExtender style created with a custom 
    Cascading Style Sheet. 
&amp;lt;/asp:Panel&amp;gt;
&amp;lt;ajaxToolkit:BalloonPopupExtender 
    ID="bpe1" 
    TargetControlID="txtCustom"
    BalloonPopupControlID="Panel3" 
    BalloonStyle="Custom"    
    CustomCssUrl="CustomStyle/BalloonPopupOvalStyle.css"
    CustomClassName="oval" 
    UseShadow="true" 
    runat="server" /&amp;gt;&lt;/pre&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h4&gt;Learn More about the Balloon Popup&lt;/h4&gt;

&lt;p&gt;To learn more about the Balloon Popup control, visit the sample page for the Balloon Popup at the Ajax Control Toolkit sample site:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;a href="http://www.asp.net/ajaxLibrary/AjaxControlToolkitSampleSite/BalloonPopup/BalloonPopupExtender.aspx"&gt;http://www.asp.net/ajaxLibrary/AjaxControlToolkitSampleSite/BalloonPopup/BalloonPopupExtender.aspx&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;Improvements to the Tabs Control&lt;/h3&gt;

&lt;p&gt;In this release, we introduced several important new features for the existing Tabs control. We also fixed all of the top-voted bugs for the Tabs control.&lt;/p&gt;

&lt;h4&gt;On-Demand Loading of Tab Content&lt;/h4&gt;

&lt;p&gt;Here is the scenario. Imagine that you are using the Tabs control in a Web Forms page. The Tabs control displays two tabs: Customers and Products. When you click the Customers tab then you want to see a list of customers and when you click on the Products tab then you want to see a list of products.&lt;/p&gt;

&lt;p&gt;In this scenario, you don’t want the list of customers and products to be retrieved from the database when the page is initially opened. The user might never click on the Products tab and all of the work to load the list of products from the database would be wasted.&lt;/p&gt;

&lt;p&gt;In this scenario, you want the content of a tab panel to be loaded on demand. The products should only be loaded from the database and rendered to the browser when you click the Products tab and not before.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://stephenwalther.com/blog/images/StephenWalther_com/blog/Windows-Live-Writer/f05c471a20b7_10C10/clip_image012_2.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image012" border="0" alt="clip_image012" src="http://stephenwalther.com/blog/images/StephenWalther_com/blog/Windows-Live-Writer/f05c471a20b7_10C10/clip_image012_thumb.png" width="320" height="377" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Tabs control in the November 2011 Release of the Ajax Control Toolkit includes a new property named OnDemand. When OnDemand is set to the value True, a tab panel won’t be loaded until you click its associated tab.&lt;/p&gt;

&lt;p&gt;Here is the code for the aspx page:&lt;/p&gt;

&lt;pre class="brush: xml;"&gt;&amp;lt;ajaxToolkit:ToolkitScriptManager ID="tsm1" runat="server" /&amp;gt;

&amp;lt;ajaxToolkit:TabContainer ID="tabs" OnDemand=”true" runat="server"&amp;gt;
    &amp;lt;ajaxToolkit:TabPanel HeaderText="Customers" runat="server"&amp;gt;
    &amp;lt;ContentTemplate&amp;gt;
        &amp;lt;h2&amp;gt;Customers&amp;lt;/h2&amp;gt;
        
        &amp;lt;asp:GridView ID="grdCustomers" DataSourceID="srcCustomers" runat="server" /&amp;gt;
        &amp;lt;asp:SqlDataSource 
            ID="srcCustomers" 
            SelectCommand="SELECT * FROM Customers"
            ConnectionString="&amp;lt;%$ ConnectionStrings:StoreDB %&amp;gt;"
            runat="server" /&amp;gt;

    &amp;lt;/ContentTemplate&amp;gt;    
    &amp;lt;/ajaxToolkit:TabPanel&amp;gt;
    &amp;lt;ajaxToolkit:TabPanel HeaderText="Products" runat="server"&amp;gt;
    &amp;lt;ContentTemplate&amp;gt;
        &amp;lt;h2&amp;gt;Products&amp;lt;/h2&amp;gt;
                 
        &amp;lt;asp:GridView ID="grdProducts" DataSourceID="srcProducts" runat="server" /&amp;gt;
        &amp;lt;asp:SqlDataSource 
            ID="srcProducts" 
            SelectCommand="SELECT * FROM Products"
            ConnectionString="&amp;lt;%$ ConnectionStrings:StoreDB %&amp;gt;"
            runat="server" /&amp;gt;
         
    &amp;lt;/ContentTemplate&amp;gt;
    &amp;lt;/ajaxToolkit:TabPanel&amp;gt;
&amp;lt;/ajaxToolkit:TabContainer&amp;gt;&lt;/pre&gt;

&lt;p&gt;Notice that the TabContainer includes an OnDemand=”True” property. The Tabs control contains two Tab Panels. The first tab panel uses a DataGrid and SqlDataSource to display a list of customers and the second tab panel uses a DataGrid and SqlDataSource to display a list of products.&lt;/p&gt;

&lt;p&gt;And here is the code-behind for the page:&lt;/p&gt;

&lt;pre class="brush: csharp;"&gt;using System;
using System.Diagnostics;
using System.Web.UI.WebControls;

namespace ACTSamples {
    public partial class TabsOnDemand : System.Web.UI.Page {

        protected override void OnInit(EventArgs e) {
            srcProducts.Selecting += new SqlDataSourceSelectingEventHandler(srcProducts_Selecting);
        }

        void srcProducts_Selecting(object sender, SqlDataSourceSelectingEventArgs e) {
            Debugger.Break();
        }
    }
}&lt;/pre&gt;

&lt;p&gt;The code-behind file includes an event handler for the Products SqlDataSource Selecting event. The handler breaks into the debugger by calling the Debugger.Break() method. That way, we can know when the Products SqlDataSource actually retrieves the list of products.&lt;/p&gt;

&lt;p&gt;When the OnDemand property has the value False then the Selecting event handler is called immediately when the page is first loaded. The contents of all of the tabs are loaded (and the contents of the unselected tabs are hidden) when the page is first loaded.&lt;/p&gt;

&lt;p&gt;When the OnDemand property has the value True then the Selecting event handler is not called when the page is first loaded. The event handler is not called until you click on the Products tab. If you never click on the Products tab then the list of products is never retrieved from the database. &lt;/p&gt;

&lt;p&gt;If you want even more control over when the contents of a tab panel gets loaded then you can use the TabPanel OnDemandMode property. This property accepts the following three values:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;None – Never load the contents of the tab panel again after the page is first loaded. &lt;/p&gt;
  &lt;/li&gt;

  &lt;li&gt;
    &lt;p&gt;Once – Wait until the tab is selected to load the contents of the tab panel&lt;/p&gt;
  &lt;/li&gt;

  &lt;li&gt;
    &lt;p&gt;Always – Load the contents of the tab panel each and every time you select the tab.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There is a live demonstration of the OnDemandMode property here in the sample page for the Tabs control:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;a href="http://www.asp.net/ajaxLibrary/AjaxControlToolkitSampleSite/Tabs/Tabs.aspx"&gt;http://www.asp.net/ajaxLibrary/AjaxControlToolkitSampleSite/Tabs/Tabs.aspx&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;Displaying Vertical Tabs&lt;/h4&gt;

&lt;p&gt;With the November 2011 Release, the Tabs control now supports vertical tabs.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://stephenwalther.com/blog/images/StephenWalther_com/blog/Windows-Live-Writer/f05c471a20b7_10C10/clip_image013_2.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image013" border="0" alt="clip_image013" src="http://stephenwalther.com/blog/images/StephenWalther_com/blog/Windows-Live-Writer/f05c471a20b7_10C10/clip_image013_thumb.png" width="637" height="602" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To create vertical tabs, just set the TabContainer UserVerticalStripPlacement property to the value True like this:&lt;/p&gt;

&lt;pre class="brush: xml;"&gt;&amp;lt;ajaxToolkit:TabContainer ID="tabs" OnDemand="false" UseVerticalStripPlacement="true" runat="server"&amp;gt;
    &amp;lt;ajaxToolkit:TabPanel ID="TabPanel1" HeaderText="First Tab" runat="server"&amp;gt;
    &amp;lt;ContentTemplate&amp;gt;
    &amp;lt;p&amp;gt;
    Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas porttitor congue massa. Fusce posuere, magna sed pulvinar ultricies, purus lectus malesuada libero, sit amet commodo magna eros quis urna.
    &amp;lt;/p&amp;gt;
    &amp;lt;/ContentTemplate&amp;gt;    
    &amp;lt;/ajaxToolkit:TabPanel&amp;gt;
    &amp;lt;ajaxToolkit:TabPanel ID="TabPanel2" HeaderText="Second Tab" runat="server"&amp;gt;
    &amp;lt;ContentTemplate&amp;gt;
    &amp;lt;p&amp;gt;
    Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas porttitor congue massa. Fusce posuere, magna sed pulvinar ultricies, purus lectus malesuada libero, sit amet commodo magna eros quis urna.
    &amp;lt;/p&amp;gt;
         
    &amp;lt;/ContentTemplate&amp;gt;
    &amp;lt;/ajaxToolkit:TabPanel&amp;gt;
&amp;lt;/ajaxToolkit:TabContainer&amp;gt;&lt;/pre&gt;

&lt;p&gt;In addition, you can use the TabStripPlacement property to control whether the tab strip appears at the left or right or top or bottom of the tab panels:&lt;/p&gt;

&lt;p&gt;&lt;a href="http://stephenwalther.com/blog/images/StephenWalther_com/blog/Windows-Live-Writer/f05c471a20b7_10C10/clip_image014_2.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image014" border="0" alt="clip_image014" src="http://stephenwalther.com/blog/images/StephenWalther_com/blog/Windows-Live-Writer/f05c471a20b7_10C10/clip_image014_thumb.png" width="637" height="602" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;Tab Keyboard Navigation&lt;/h4&gt;

&lt;p&gt;Another highly requested feature for the Tabs control is support for keyboard navigation. The Tabs control now supports the arrow keys and the Home and End keys.&lt;/p&gt;

&lt;p&gt;In order for the arrow keys to work, you must first move focus to the tab control on the page by either clicking on a tab with your mouse or repeatedly hitting the Tab key.&lt;/p&gt;

&lt;p&gt;You can try out the new keyboard navigation support by trying any of the demos included in the Tabs sample page:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;a href="http://www.asp.net/ajaxLibrary/AjaxControlToolkitSampleSite/Tabs/Tabs.aspx"&gt;http://www.asp.net/ajaxLibrary/AjaxControlToolkitSampleSite/Tabs/Tabs.aspx&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;Summary&lt;/h3&gt;

&lt;p&gt;I hope that you take advantage of the new Balloon Popup control and the new features which we introduced for the Tabs control. We added a lot of new features to the Tabs control in this release including support for on-demand tabs, support for vertical tabs, and support for tab keyboard navigation.&lt;/p&gt;

&lt;p&gt;I want to thank the developers on the &lt;a href="http://superexpert.com/"&gt;Superexpert&lt;/a&gt; team for all of the hard work which they put into this release. &lt;/p&gt;&lt;img src="http://stephenwalther.com/blog/aggbug/175.aspx" width="1" height="1" /&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/StephenWalther?a=DQTtPXIospM:B3yObnfLJX8:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StephenWalther?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/StephenWalther/~4/DQTtPXIospM" height="1" width="1"/&gt;</description>
            <dc:creator>Stephen Walther</dc:creator>
            <guid isPermaLink="false">http://stephenwalther.com/blog/archive/2011/11/16/ajax-control-toolkit-november-2011-release.aspx</guid>
            <pubDate>Thu, 17 Nov 2011 03:48:29 GMT</pubDate>
            <comments>http://stephenwalther.com/blog/archive/2011/11/16/ajax-control-toolkit-november-2011-release.aspx#feedback</comments>
            <slash:comments>2</slash:comments>
            <wfw:commentRss>http://stephenwalther.com/blog/comments/commentRss/175.aspx</wfw:commentRss>
        <feedburner:origLink>http://stephenwalther.com/blog/archive/2011/11/16/ajax-control-toolkit-november-2011-release.aspx</feedburner:origLink></item>
        <item>
            <title>ASP.NET Connections Fall 2011 Slides and Code</title>
            <category>Talks</category>
            <category>ACT</category>
            <category>jQuery</category>
            <category>JavaScript</category>
            <link>http://feedproxy.google.com/~r/StephenWalther/~3/rjAreCcDge8/asp-net-connections-fall-2011-slides-and-code.aspx</link>
            <description>&lt;p&gt;Thanks everyone who came to my talks at ASP.NET Connections in Las Vegas!  There was a definite theme to my talks this year…taking advantage of JavaScript to build a rich presentation layer. I gave the following three talks:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;JsRender Templates – Originally, I was scheduled to give a talk on jQuery Templates.  However, jQuery Templates has been deprecated and JsRender is the new technology which replaces jQuery Templates. In the talk, I give plenty of code samples of using JsRender.  You can download the slides and code samples &lt;a href="/downloads/Talks/ASPNETConnectionsFall2011/JsRenderTemplates.zip"&gt;RIGHT HERE&lt;/a&gt;&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt; &lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;HTML5 – In this talk, I focused on the features of HTML5 which are the most interesting to developers building database-driven Web applications. In particular, I discussed Web Sockets,  Web workers, Web Storage, Indexed DB, and the Offline Application Cache. All of these features are supported by Safari, Chrome, and Firefox today and they will be supported by Internet Explorer 10. You can download the slides and code samples &lt;a href="/downloads/Talks/ASPNETConnectionsFall2011/Walther_HTML5.zip"&gt;RIGHT HERE&lt;/a&gt;&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt; &lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Ajax Control Toolkit – My company, &lt;strong&gt;&lt;a href="http://Superexpert.com"&gt;Superexpert&lt;/a&gt;&lt;/strong&gt;, is responsible for developing and maintaining the Ajax Control Toolkit. In this talk, I discuss all of the bug fixes and new features which the developers on the Superexpert team have added to the Ajax Control Toolkit over the previous six months. We also had a good discussion of the features which people want in future releases of the Ajax Control Toolkit. The slides and code samples for this talk can be downloaded &lt;a href="/downloads/Talks/ASPNETConnectionsFall2011/Walther_AjaxControlToolkit.zip"&gt;RIGHT HERE&lt;/a&gt;&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt; &lt;/p&gt;  &lt;p&gt;I had a great time in Las Vegas!  Good questions, friendly audience, and lots of opportunities for me to learn new things!&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;p&gt;   -- Stephen&lt;/p&gt;&lt;img src="http://stephenwalther.com/blog/aggbug/173.aspx" width="1" height="1" /&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/StephenWalther?a=rjAreCcDge8:PghqP7Mh4o4:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StephenWalther?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/StephenWalther/~4/rjAreCcDge8" height="1" width="1"/&gt;</description>
            <dc:creator>Stephen Walther</dc:creator>
            <guid isPermaLink="false">http://stephenwalther.com/blog/archive/2011/11/06/asp-net-connections-fall-2011-slides-and-code.aspx</guid>
            <pubDate>Mon, 07 Nov 2011 02:00:39 GMT</pubDate>
            <comments>http://stephenwalther.com/blog/archive/2011/11/06/asp-net-connections-fall-2011-slides-and-code.aspx#feedback</comments>
            <wfw:commentRss>http://stephenwalther.com/blog/comments/commentRss/173.aspx</wfw:commentRss>
        <feedburner:origLink>http://stephenwalther.com/blog/archive/2011/11/06/asp-net-connections-fall-2011-slides-and-code.aspx</feedburner:origLink></item>
        <item>
            <title>September 2011 Release of the Ajax Control Toolkit</title>
            <category>ACT</category>
            <category>AJAX</category>
            <category>ASP.NET</category>
            <link>http://feedproxy.google.com/~r/StephenWalther/~3/1UWSpC91gXk/september-2011-release-of-the-ajax-control-toolkit.aspx</link>
            <description>&lt;p&gt;I’m happy to announce the release of the September 2011 Ajax Control Toolkit. This release has several important new features including:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;     &lt;p&gt;&lt;b&gt;Date ranges&lt;/b&gt; – When using the Calendar extender, you can specify a start and end date and a user can pick only those dates which fall within the specified range. This was the fourth top-voted feature request for the Ajax Control Toolkit at CodePlex.&lt;/p&gt;   &lt;/li&gt;    &lt;li&gt;     &lt;p&gt;&lt;b&gt;Twitter Control&lt;/b&gt; – You can use the new Twitter control to display recent tweets associated with a particular Twitter user or tweets which match a search query.&lt;/p&gt;   &lt;/li&gt;    &lt;li&gt;     &lt;p&gt;&lt;b&gt;Gravatar Control &lt;/b&gt;– You can use the new Gravatar control to display a unique image for each user of your website. Users can upload custom images to the Gravatar.com website or the Gravatar control can display a unique, auto-generated, image for a user.&lt;/p&gt;   &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;You can download this release this very minute by visiting CodePlex:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;a href="http://AjaxControlToolkit.CodePlex.com"&gt;http://AjaxControlToolkit.CodePlex.com&lt;/a&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Alternatively, you can execute the following command from the Visual Studio NuGet console:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://stephenwalther.com/blog/images/StephenWalther_com/blog/Windows-Live-Writer/71f42a58c034_14507/clip_image001_2.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image001" border="0" alt="clip_image001" src="http://stephenwalther.com/blog/images/StephenWalther_com/blog/Windows-Live-Writer/71f42a58c034_14507/clip_image001_thumb.png" width="552" height="110" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;h3&gt;Improvements to the Ajax Control Toolkit Calendar Control&lt;/h3&gt;  &lt;p&gt;The Ajax Control Toolkit Calendar extender control is one of the most heavily used controls from the Ajax Control Toolkit. The developers on the Superexpert team spent the last sprint focusing on improving this control. There are three important changes that we made to the Calendar control: we added support for date ranges, we added support for highlighting today’s date, and we made fixes to several bugs related to time zones and daylight savings.&lt;/p&gt;  &lt;h4&gt;Using Calendar Date Ranges&lt;/h4&gt;  &lt;p&gt;One of the top-voted feature requests for the Ajax Control Toolkit was a request to add support for date ranges to the Calendar control (this was the fourth most voted feature request at CodePlex). With the latest release of the Ajax Control Toolkit, the Calendar extender now supports date ranges.&lt;/p&gt;  &lt;p&gt;For example, the following page illustrates how you can create a popup calendar which allows a user only to pick dates between March 2, 2009 and May 16, 2009.&lt;/p&gt;  &lt;pre class="brush: xml;"&gt;&amp;lt;%@ Page Language="C#" AutoEventWireup="true" CodeBehind="CalendarDateRange.aspx.cs" Inherits="WebApplication1.CalendarDateRange" %&amp;gt;
&amp;lt;%@ Register TagPrefix="asp" Namespace="AjaxControlToolkit" Assembly="AjaxControlToolkit" %&amp;gt;
&amp;lt;html&amp;gt;
&amp;lt;head runat="server"&amp;gt;
    &amp;lt;title&amp;gt;Calendar Date Range&amp;lt;/title&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
    &amp;lt;form id="form1" runat="server"&amp;gt;

        &amp;lt;asp:ToolkitScriptManager 
            ID="tsm" 
            runat="server" /&amp;gt;

        &amp;lt;asp:TextBox 
            ID="txtHotelReservationDate" 
            runat="server" /&amp;gt; 
        
        &amp;lt;asp:CalendarExtender 
            ID="Calendar1" 
            TargetControlID="txtHotelReservationDate" 
            StartDate="3/2/2009"
            EndDate="5/16/2009"
            SelectedDate="3/2/2009"
            runat="server" /&amp;gt; 

    &amp;lt;/form&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/pre&gt;

&lt;p&gt;This page contains three controls: an Ajax Control Toolkit ToolkitScriptManager control, a standard ASP.NET TextBox control, and an Ajax Control Toolkit CalendarExtender control. Notice that the Calendar control includes StartDate and EndDate properties which restrict the range of valid dates.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://stephenwalther.com/blog/images/StephenWalther_com/blog/Windows-Live-Writer/71f42a58c034_14507/clip_image002_2.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image002" border="0" alt="clip_image002" src="http://stephenwalther.com/blog/images/StephenWalther_com/blog/Windows-Live-Writer/71f42a58c034_14507/clip_image002_thumb.png" width="479" height="411" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Calendar control shows days, months, and years outside of the valid range as struck out. You cannot select days, months, or years which fall outside of the range. The following video illustrates interacting with the new date range feature:&lt;/p&gt;

&lt;p&gt;&lt;a href="http://stephenwalther.com/blog/images/StephenWalther_com/blog/Windows-Live-Writer/71f42a58c034_14507/clip_image003_2.gif"&gt;&lt;img style="display: inline" title="clip_image003" alt="clip_image003" src="http://stephenwalther.com/blog/images/StephenWalther_com/blog/Windows-Live-Writer/71f42a58c034_14507/clip_image003_thumb.gif" width="476" height="408" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you want to experiment with a live version of the Ajax Control Toolkit Calendar extender control then you can visit the &lt;a href="http://www.asp.net/ajaxLibrary/AjaxControlToolkitSampleSite/Calendar/Calendar.aspx"&gt;Calendar Sample Page&lt;/a&gt; at the Ajax Control Toolkit Sample Site.&lt;/p&gt;

&lt;h4 /&gt;

&lt;h4&gt;Highlighted Today’s Date&lt;/h4&gt;

&lt;p&gt;Another highly requested feature for the Calendar control was support for highlighting today’s date. The Calendar control now highlights the user’s current date regardless of the user’s time zone.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://stephenwalther.com/blog/images/StephenWalther_com/blog/Windows-Live-Writer/71f42a58c034_14507/clip_image004_2.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image004" border="0" alt="clip_image004" src="http://stephenwalther.com/blog/images/StephenWalther_com/blog/Windows-Live-Writer/71f42a58c034_14507/clip_image004_thumb.png" width="479" height="411" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;Fixes to Time Zone and Daylight Savings Time Bugs&lt;/h4&gt;

&lt;p&gt;We fixed several significant Calendar extender bugs related to time zones and daylight savings time. For example, previously, when you set the Calendar control’s SelectedDate property to the value 1/1/2007 then the selected data would appear as 12/31/2006 or 1/1/2007 or 1/2/2007 depending on the server time zone.&lt;/p&gt;

&lt;p&gt;For example, if your server time zone was set to Samoa (UTC-11:00), then setting SelectedDate=”1/1/2007” would result in “12/31/2006” being selected in the Calendar. Users of the Calendar extender control found this behavior confusing. &lt;/p&gt;

&lt;p&gt;After careful consideration, we decided to change the Calendar extender so that it interprets all dates as UTC dates. In other words, if you set StartDate=”1/1/2007” then the Calendar extender parses the date as 1/1/2007 UTC instead of parsing the date according to the server time zone.&lt;/p&gt;

&lt;p&gt;By interpreting all dates as UTC dates, we avoid all of the reported issues with the SelectedDate property showing the wrong date. Furthermore, when you set the StartDate and EndDate properties, you know that the same StartDate and EndDate will be selected regardless of the time zone associated with the server or associated with the browser. The date 1/1/2007 will always be the date 1/1/2007.&lt;/p&gt;

&lt;h3&gt;The New Twitter Control&lt;/h3&gt;

&lt;p&gt;This release of the Ajax Control Toolkit introduces a new twitter control. You can use the Twitter control to display recent tweets associated with a particular twitter user. You also can use this control to show the results of a twitter search.&lt;/p&gt;

&lt;p&gt;The following page illustrates how you can use the Twitter control to display recent tweets made by Scott Hanselman:&lt;/p&gt;

&lt;pre class="brush: xml;"&gt;&amp;lt;%@ Page Language="C#" AutoEventWireup="true" CodeBehind="TwitterProfile.aspx.cs" Inherits="WebApplication1.TwitterProfile" %&amp;gt;
&amp;lt;%@ Register TagPrefix="asp" Namespace="AjaxControlToolkit" Assembly="AjaxControlToolkit" %&amp;gt;
&amp;lt;html xmlns="http://www.w3.org/1999/xhtml"&amp;gt;
&amp;lt;head runat="server"&amp;gt;
    &amp;lt;title&amp;gt;Twitter Profile&amp;lt;/title&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
    &amp;lt;form id="form1" runat="server"&amp;gt;
    
        &amp;lt;asp:ToolkitScriptManager 
            ID="tsm" 
            runat="server" /&amp;gt;

        &amp;lt;asp:Twitter 
            ID="Twitter1"
            ScreenName="shanselman"
            runat="server" /&amp;gt;

    &amp;lt;/form&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/pre&gt;

&lt;p&gt;This page includes two Ajax Control Toolkit controls: the ToolkitScriptManager control and the Twitter control. The Twitter control is set to display tweets from Scott Hanselman (shanselman):&lt;/p&gt;

&lt;p&gt;&lt;a href="http://stephenwalther.com/blog/images/StephenWalther_com/blog/Windows-Live-Writer/71f42a58c034_14507/clip_image005_2.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image005" border="0" alt="clip_image005" src="http://stephenwalther.com/blog/images/StephenWalther_com/blog/Windows-Live-Writer/71f42a58c034_14507/clip_image005_thumb.png" width="464" height="688" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You also can use the Twitter control to display the results of a search query. For example, the following page displays all recent tweets related to the Ajax Control Toolkit:&lt;/p&gt;

&lt;p&gt;&lt;a href="http://stephenwalther.com/blog/images/StephenWalther_com/blog/Windows-Live-Writer/71f42a58c034_14507/clip_image006_2.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image006" border="0" alt="clip_image006" src="http://stephenwalther.com/blog/images/StephenWalther_com/blog/Windows-Live-Writer/71f42a58c034_14507/clip_image006_thumb.png" width="489" height="677" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Twitter limits the number of times that you can interact with their API in an hour. Twitter recommends that you cache results on the server (https://dev.twitter.com/docs/rate-limiting). By default, the Twitter control caches results on the server for a duration of 5 minutes. You can modify the cache duration by assigning a value (in seconds) to the Twitter control's CacheDuration property.&lt;/p&gt;

&lt;p&gt;The Twitter control wraps a standard ASP.NET ListView control. You can customize the appearance of the Twitter control by modifying its LayoutTemplate, StatusTemplate, AlternatingStatusTemplate, and EmptyDataTemplate.&lt;/p&gt;

&lt;p&gt;To learn more about the new Twitter control, visit the live &lt;a href="http://www.asp.net/ajaxLibrary/AjaxControlToolkitSampleSite/Twitter/Twitter.aspx"&gt;Twitter Sample Page&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;The New Gravatar Control&lt;/h3&gt;

&lt;p&gt;The September 2011 release of the Ajax Control Toolkit also includes a new Gravatar control. This control makes it easy to display a unique image for each user of your website.&lt;/p&gt;

&lt;p&gt;A Gravatar is associated with an email address. You can visit Gravatar.com and upload an image and associate the image with your email address. That way, every website which uses Gravatars (such as the &lt;a href="http://www.ASP.NET"&gt;www.ASP.NET&lt;/a&gt; website) will display your image next to your name.&lt;/p&gt;

&lt;p&gt;For example, I visited the Gravatar.com website and associated an image of a Koala Bear with the email address &lt;a href="mailto:Test@Superexpert.com"&gt;Test@Superexpert.com&lt;/a&gt;. The following page illustrates how you can use the Gravatar control to display the Gravatar image associated with the &lt;a href="mailto:Test@superexpert.com"&gt;Test@superexpert.com&lt;/a&gt; email address:&lt;/p&gt;

&lt;pre class="brush: xml;"&gt;&amp;lt;%@ Page Language="C#" AutoEventWireup="true" CodeBehind="GravatarDemo.aspx.cs" Inherits="WebApplication1.GravatarDemo" %&amp;gt;
&amp;lt;%@ Register TagPrefix="asp" Namespace="AjaxControlToolkit" Assembly="AjaxControlToolkit" %&amp;gt;
&amp;lt;html xmlns="http://www.w3.org/1999/xhtml"&amp;gt;
&amp;lt;head id="Head1" runat="server"&amp;gt;
    &amp;lt;title&amp;gt;Gravatar Demo&amp;lt;/title&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
    &amp;lt;form id="form1" runat="server"&amp;gt;
    
        &amp;lt;asp:ToolkitScriptManager 
            ID="tsm" 
            runat="server" /&amp;gt;

        &amp;lt;asp:Gravatar 
            ID="Gravatar1"
            Email="test@superexpert.com"
            runat="server" /&amp;gt;

    &amp;lt;/form&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/pre&gt;

&lt;p&gt;The page above simply displays the Gravatar image associated with the &lt;a href="mailto:Test@superexpert.com"&gt;Test@superexpert.com&lt;/a&gt; email address:&lt;/p&gt;

&lt;p&gt;&lt;a href="http://stephenwalther.com/blog/images/StephenWalther_com/blog/Windows-Live-Writer/71f42a58c034_14507/clip_image007_2.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image007" border="0" alt="clip_image007" src="http://stephenwalther.com/blog/images/StephenWalther_com/blog/Windows-Live-Writer/71f42a58c034_14507/clip_image007_thumb.png" width="211" height="244" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If a user has not uploaded an image to Gravatar.com then you can auto-generate a unique image for the user from the user email address. The Gravatar control supports four types of auto-generated images:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;Identicon -- A different geometric pattern is generated for each unrecognized email.&lt;/p&gt;
  &lt;/li&gt;

  &lt;li&gt;
    &lt;p&gt;MonsterId -- A different image of a monster is generated for each unrecognized email.&lt;/p&gt;
  &lt;/li&gt;

  &lt;li&gt;
    &lt;p&gt;Wavatar -- A different image of a face is generated for each unrecognized email.&lt;/p&gt;
  &lt;/li&gt;

  &lt;li&gt;
    &lt;p&gt;Retro -- A different 8-bit arcade-style face is generated for each unrecognized email.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For example, there is no Gravatar image associated with the email address &lt;a href="mailto:someone@somewhere.com"&gt;someone@somewhere.com&lt;/a&gt;. The following page displays an auto-generated MonsterId for this email address:&lt;/p&gt;

&lt;pre class="brush: xml;"&gt;&amp;lt;%@ Page Language="C#" AutoEventWireup="true" CodeBehind="GravatarMonster.aspx.cs" Inherits="WebApplication1.GravatarMonster" %&amp;gt;
&amp;lt;%@ Register TagPrefix="asp" Namespace="AjaxControlToolkit" Assembly="AjaxControlToolkit" %&amp;gt;
&amp;lt;html xmlns="http://www.w3.org/1999/xhtml"&amp;gt;
&amp;lt;head id="Head1" runat="server"&amp;gt;
    &amp;lt;title&amp;gt;Gravatar Monster&amp;lt;/title&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
    &amp;lt;form id="form1" runat="server"&amp;gt;
    
        &amp;lt;asp:ToolkitScriptManager 
            ID="tsm" 
            runat="server" /&amp;gt;

        &amp;lt;asp:Gravatar 
            ID="Gravatar1"
            Email="someone@somewhere.com"
            DefaultImageBehavior="MonsterId"
            runat="server" /&amp;gt;

    &amp;lt;/form&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/pre&gt;

&lt;p&gt;The page above generates the following image automatically from the supplied email address:&lt;/p&gt;

&lt;p&gt;&lt;a href="http://stephenwalther.com/blog/images/StephenWalther_com/blog/Windows-Live-Writer/71f42a58c034_14507/clip_image008_2.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image008" border="0" alt="clip_image008" src="http://stephenwalther.com/blog/images/StephenWalther_com/blog/Windows-Live-Writer/71f42a58c034_14507/clip_image008_thumb.png" width="217" height="244" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To learn more about the properties of the new Gravatar control, visit the live &lt;a href="http://www.asp.net/ajaxLibrary/AjaxControlToolkitSampleSite/Gravatar/Gravatar.aspx"&gt;Gravatar Sample Page&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;ASP.NET Connections Talk on the Ajax Control Toolkit&lt;/h3&gt;

&lt;p&gt;If you are interested in learning more about the changes that we are making to the Ajax Control Toolkit then please come to my talk on the Ajax Control Toolkit at the upcoming ASP.NET Connections conference. In the talk, I will present a summary of the changes that we have made to the Ajax Control Toolkit over the last several months and discuss our future plans.&lt;/p&gt;

&lt;p&gt;Do you have ideas for new Ajax Control Toolkit controls? Ideas for improving the toolkit? Come to my talk – I would love to hear from you.&lt;/p&gt;

&lt;p&gt;You can register for the ASP.NET Connections conference by visiting the following website:&lt;/p&gt;

&lt;p&gt;&lt;a href="http://devconnections.com/shows/fall2011/default.aspx?s=177&amp;amp;cid=spkrtwitter"&gt;Register for ASP.NET Connections&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="http://stephenwalther.com/blog/images/StephenWalther_com/blog/Windows-Live-Writer/71f42a58c034_14507/clip_image009_2.jpg"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image009" border="0" alt="clip_image009" src="http://stephenwalther.com/blog/images/StephenWalther_com/blog/Windows-Live-Writer/71f42a58c034_14507/clip_image009_thumb.jpg" width="184" height="154" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h1&gt;Summary&lt;/h1&gt;

&lt;p&gt;The previous release of the Ajax Control Toolkit – &lt;a href="http://ajaxcontroltoolkit.codeplex.com/releases/view/71000"&gt;the July 2011 Release&lt;/a&gt; – has had over 100,000 downloads. That is a huge number of developers who are working with the Ajax Control Toolkit. We are really excited about the new features which we added to the Ajax Control Toolkit in the latest September sprint. We hope that you find the updated Calender control, the new Twitter control, and the new Gravatar control valuable when building your ASP.NET Web Forms applications. &lt;/p&gt;&lt;img src="http://stephenwalther.com/blog/aggbug/171.aspx" width="1" height="1" /&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/StephenWalther?a=1UWSpC91gXk:XjFZLMJ1ed0:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StephenWalther?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/StephenWalther/~4/1UWSpC91gXk" height="1" width="1"/&gt;</description>
            <dc:creator>Stephen Walther</dc:creator>
            <guid isPermaLink="false">http://stephenwalther.com/blog/archive/2011/09/27/september-2011-release-of-the-ajax-control-toolkit.aspx</guid>
            <pubDate>Tue, 27 Sep 2011 21:28:43 GMT</pubDate>
            <comments>http://stephenwalther.com/blog/archive/2011/09/27/september-2011-release-of-the-ajax-control-toolkit.aspx#feedback</comments>
            <slash:comments>14</slash:comments>
            <wfw:commentRss>http://stephenwalther.com/blog/comments/commentRss/171.aspx</wfw:commentRss>
        <feedburner:origLink>http://stephenwalther.com/blog/archive/2011/09/27/september-2011-release-of-the-ajax-control-toolkit.aspx</feedburner:origLink></item>
        <item>
            <title>Adding the New HTML Editor Extender to a Web Forms Application using NuGet</title>
            <category>ACT</category>
            <category>AJAX</category>
            <category>ASP.NET</category>
            <link>http://feedproxy.google.com/~r/StephenWalther/~3/3T1vIK39yrA/adding-the-new-html-editor-extender-to-a-web-forms.aspx</link>
            <description>&lt;p&gt;The July 2011 release of the Ajax Control Toolkit includes a new, lightweight, HTML5 compatible HTML Editor extender. In this blog entry, I explain how you can take advantage of NuGet to quickly add the new HTML Editor control extender to a new or existing ASP.NET Web Forms application.&lt;/p&gt;  &lt;h3&gt;Installing the Latest Version of the Ajax Control Toolkit with NuGet&lt;/h3&gt;  &lt;p&gt;NuGet is a package manager. It enables you to quickly install new software directly from within Visual Studio 2010. You can use NuGet to install additional software when building any type of .NET application including ASP.NET Web Forms and ASP.NET MVC applications.&lt;/p&gt;  &lt;p&gt;If you have not already installed NuGet then you can install NuGet by navigating to the following address and clicking the giant install button:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;a href="http://nuget.org/"&gt;http://nuget.org/&lt;/a&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;After you install NuGet, you can add the Ajax Control Toolkit to a new or existing ASP.NET Web Forms application by selecting the Visual Studio menu option &lt;b&gt;Tools, Library Package Manager, Package Manager Console&lt;/b&gt;:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://stephenwalther.com/blog/images/StephenWalther_com/blog/Windows-Live-Writer/9a9abbd15d99_D78D/clip_image002_2.jpg"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image002" border="0" alt="clip_image002" src="http://stephenwalther.com/blog/images/StephenWalther_com/blog/Windows-Live-Writer/9a9abbd15d99_D78D/clip_image002_thumb.jpg" width="628" height="217" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Selecting this menu option opens the Package Manager Console. You can enter the command &lt;b&gt;Install-Package AjaxControlToolkit&lt;/b&gt; in the console to install the Ajax Control Toolkit:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://stephenwalther.com/blog/images/StephenWalther_com/blog/Windows-Live-Writer/9a9abbd15d99_D78D/clip_image003_2.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image003" border="0" alt="clip_image003" src="http://stephenwalther.com/blog/images/StephenWalther_com/blog/Windows-Live-Writer/9a9abbd15d99_D78D/clip_image003_thumb.png" width="555" height="143" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;After you install the Ajax Control Toolkit with NuGet, your application will include an assembly reference to the AjaxControlToolkit.dll and SanitizerProviders.dll assemblies:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://stephenwalther.com/blog/images/StephenWalther_com/blog/Windows-Live-Writer/9a9abbd15d99_D78D/clip_image004_2.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image004" border="0" alt="clip_image004" src="http://stephenwalther.com/blog/images/StephenWalther_com/blog/Windows-Live-Writer/9a9abbd15d99_D78D/clip_image004_thumb.png" width="307" height="507" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Furthermore, your Web.config file will be updated to contain a new tag prefix for the Ajax Control Toolkit controls:&lt;/p&gt;  &lt;pre class="brush: xml;"&gt;&amp;lt;configuration&amp;gt;
  &amp;lt;system.web&amp;gt;
    &amp;lt;compilation debug="true" targetFramework="4.0" /&amp;gt;
    &amp;lt;pages&amp;gt;
      &amp;lt;controls&amp;gt;
        &amp;lt;add tagPrefix="ajaxToolkit" assembly="AjaxControlToolkit" namespace="AjaxControlToolkit" /&amp;gt;
      &amp;lt;/controls&amp;gt;
    &amp;lt;/pages&amp;gt;
  &amp;lt;/system.web&amp;gt;
&amp;lt;/configuration&amp;gt;&lt;/pre&gt;

&lt;p&gt;The configuration file installed by NuGet adds the prefix ajaxToolkit for all of the Ajax Control Toolkit controls. You can type &lt;b&gt;&lt;i&gt;ajaxToolkit:&lt;/i&gt;&lt;/b&gt; in source view to get auto-complete in Source view. You can, of course, change this prefix to anything you want.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://stephenwalther.com/blog/images/StephenWalther_com/blog/Windows-Live-Writer/9a9abbd15d99_D78D/clip_image005_2.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image005" border="0" alt="clip_image005" src="http://stephenwalther.com/blog/images/StephenWalther_com/blog/Windows-Live-Writer/9a9abbd15d99_D78D/clip_image005_thumb.png" width="512" height="425" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;Using the HTML Editor Extender&lt;/h3&gt;

&lt;p&gt;After you install the Ajax Control Toolkit, you can use the HTML Editor Extender with the standard ASP.NET TextBox control to enable users to enter rich formatting such as bold, underline, italic, different fonts, and different background and foreground colors. &lt;/p&gt;

&lt;p&gt;For example, the following page can be used for entering comments. The page contains a standard ASP.NET TextBox, Button, and Label control. When you click the button, any text entered into the TextBox is displayed in the Label control. It is a pretty boring page:&lt;/p&gt;

&lt;p&gt;&lt;a href="http://stephenwalther.com/blog/images/StephenWalther_com/blog/Windows-Live-Writer/9a9abbd15d99_D78D/clip_image006_2.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image006" border="0" alt="clip_image006" src="http://stephenwalther.com/blog/images/StephenWalther_com/blog/Windows-Live-Writer/9a9abbd15d99_D78D/clip_image006_thumb.png" width="491" height="418" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let’s make this page fancier by extending the standard ASP.NET TextBox with the HTML Editor extender control:&lt;/p&gt;

&lt;p&gt;&lt;a href="http://stephenwalther.com/blog/images/StephenWalther_com/blog/Windows-Live-Writer/9a9abbd15d99_D78D/clip_image007_2.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image007" border="0" alt="clip_image007" src="http://stephenwalther.com/blog/images/StephenWalther_com/blog/Windows-Live-Writer/9a9abbd15d99_D78D/clip_image007_thumb.png" width="491" height="418" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Notice that the ASP.NET TextBox now has a toolbar which includes buttons for performing various kinds of formatting. For example, you can change the size and font used for the text. You also can change the foreground and background color – and make many other formatting changes.&lt;/p&gt;

&lt;p&gt;You can customize the toolbar buttons which the HTML Editor extender displays. To learn how to customize the toolbar, see the HTML Editor Extender sample page here:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;a href="http://www.asp.net/ajaxLibrary/AjaxControlToolkitSampleSite/HTMLEditorExtender/HTMLEditorExtender.aspx"&gt;http://www.asp.net/ajaxLibrary/AjaxControlToolkitSampleSite/HTMLEditorExtender/HTMLEditorExtender.aspx&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Here’s the source code for the ASP.NET page:&lt;/p&gt;

&lt;pre class="brush: xml;"&gt;&amp;lt;%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="WebApplication1.Default" %&amp;gt;
&amp;lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&amp;gt;
&amp;lt;html xmlns="http://www.w3.org/1999/xhtml"&amp;gt;
&amp;lt;head runat="server"&amp;gt;
    &amp;lt;title&amp;gt;Add Comments&amp;lt;/title&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
    &amp;lt;form id="form1" runat="server"&amp;gt;
    &amp;lt;div&amp;gt;
    
    &amp;lt;ajaxToolkit:ToolkitScriptManager 
        ID="TSM1" 
        runat="server" /&amp;gt;

    &amp;lt;asp:TextBox
        ID="txtComments"
        TextMode="MultiLine"
        Columns="50"
        Rows="8"
        Runat="server" /&amp;gt;

    &amp;lt;ajaxToolkit:HtmlEditorExtender
        ID="hee"
        TargetControlID="txtComments"
        Runat="server" /&amp;gt;

    &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;

    &amp;lt;asp:Button 
        ID="btnSubmit"
        Text="Add Comment"
        Runat="server" onclick="btnSubmit_Click" /&amp;gt;


    &amp;lt;hr /&amp;gt;

    &amp;lt;asp:Label
        ID="lblComment"
        Runat="server" /&amp;gt;


    &amp;lt;/div&amp;gt;
    &amp;lt;/form&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/pre&gt;

&lt;p&gt;Notice that the page above contains 5 controls. The page contains a standard ASP.NET TextBox, Button, and Label control. However, the page also contains an Ajax Control Toolkit ToolkitScriptManager control and HtmlEditorExtender control. &lt;/p&gt;

&lt;p&gt;The HTML Editor extender control &lt;i&gt;extends&lt;/i&gt; the standard ASP.NET TextBox control. The HTML Editor TargetID attribute points at the TextBox control.&lt;/p&gt;

&lt;p&gt;Here’s the code-behind for the page above:&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;pre class="brush: csharp;"&gt;using System;

namespace WebApplication1 {
    public partial class Default : System.Web.UI.Page {

        protected void btnSubmit_Click(object sender, EventArgs e) {
            lblComment.Text = txtComments.Text;
        }
    }
}&lt;/pre&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h3&gt;Preventing XSS/JavaScript Injection Attacks&lt;/h3&gt;

&lt;p&gt;If you use an HTML Editor -- any HTML Editor -- in a public facing web page then you are opening your website up to Cross-Site Scripting (XSS) attacks. An evil hacker could submit HTML using the HTML Editor which contains JavaScript that steals private information such as other user’s passwords.&lt;/p&gt;

&lt;p&gt;Imagine, for example, that you create a web page which enables your customers to post comments about your website. Furthermore, imagine that you decide to redisplay the comments so every user can see them. In that case, a malicious user could submit JavaScript which displays a dialog asking for a user name and password. When an unsuspecting customer enters their secret password, the script could transfer the password to the hacker’s website.&lt;/p&gt;

&lt;p&gt;So how do you accept HTML content without opening your website up to JavaScript injection attacks? The Ajax Control Toolkit HTML Editor supports the Anti-XSS library. You can use the Anti-XSS library to sanitize any HTML content. The Anti-XSS library, for example, strips away all JavaScript automatically.&lt;/p&gt;

&lt;p&gt;You can download the Anti-XSS library from NuGet. Open the Package Manager Console and execute the command &lt;b&gt;&lt;i&gt;Install-Package AntiXSS&lt;/i&gt;&lt;/b&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="http://stephenwalther.com/blog/images/StephenWalther_com/blog/Windows-Live-Writer/9a9abbd15d99_D78D/clip_image008_2.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image008" border="0" alt="clip_image008" src="http://stephenwalther.com/blog/images/StephenWalther_com/blog/Windows-Live-Writer/9a9abbd15d99_D78D/clip_image008_thumb.png" width="658" height="206" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Adding the Anti-XSS library to your application adds two assemblies to your application named AntiXssLibrary.dll and HtmlSanitizationLibrary.dll.&lt;/p&gt;

&lt;p&gt;After you install the Anti-XSS library, you can configure the HTML Editor extender to use the Anti-XSS library your application’s web.config file:&lt;/p&gt;

&lt;pre class="brush: xml;"&gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;
&amp;lt;configuration&amp;gt;

    &amp;lt;configSections&amp;gt;
        &amp;lt;sectionGroup name="system.web"&amp;gt;
            &amp;lt;section name="sanitizer" requirePermission="false" type="AjaxControlToolkit.Sanitizer.ProviderSanitizerSection, AjaxControlToolkit"/&amp;gt;
        &amp;lt;/sectionGroup&amp;gt;
    &amp;lt;/configSections&amp;gt;

    &amp;lt;system.web&amp;gt;

        &amp;lt;sanitizer defaultProvider="AntiXssSanitizerProvider"&amp;gt;
            &amp;lt;providers&amp;gt;
                &amp;lt;add name="AntiXssSanitizerProvider" 
                     type="AjaxControlToolkit.Sanitizer.AntiXssSanitizerProvider"&amp;gt;&amp;lt;/add&amp;gt;
            &amp;lt;/providers&amp;gt;
        &amp;lt;/sanitizer&amp;gt;


        &amp;lt;compilation debug="true" targetFramework="4.0" /&amp;gt;
        &amp;lt;pages&amp;gt;
            &amp;lt;controls&amp;gt;
                &amp;lt;add tagPrefix="ajaxToolkit" assembly="AjaxControlToolkit" namespace="AjaxControlToolkit" /&amp;gt;
            &amp;lt;/controls&amp;gt;
        &amp;lt;/pages&amp;gt;

    &amp;lt;/system.web&amp;gt;
&amp;lt;/configuration&amp;gt;&lt;/pre&gt;

&lt;h3&gt;Summary&lt;/h3&gt;

&lt;p&gt;In this blog entry, I described how you can quickly get started using the new HTML Editor extender – included with the July 2011 release of the Ajax Control Toolkit – by installing the Ajax Control Toolkit with NuGet. If you want to learn more about the HTML Editor then please take a look at the Ajax Control Toolkit sample site:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;a href="http://www.asp.net/ajaxLibrary/AjaxControlToolkitSampleSite/HTMLEditorExtender/HTMLEditorExtender.aspx"&gt;http://www.asp.net/ajaxLibrary/AjaxControlToolkitSampleSite/HTMLEditorExtender/HTMLEditorExtender.aspx&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;img src="http://stephenwalther.com/blog/aggbug/170.aspx" width="1" height="1" /&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/StephenWalther?a=3T1vIK39yrA:DftEQ52CJy4:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StephenWalther?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/StephenWalther/~4/3T1vIK39yrA" height="1" width="1"/&gt;</description>
            <dc:creator>Stephen Walther</dc:creator>
            <guid isPermaLink="false">http://stephenwalther.com/blog/archive/2011/08/17/adding-the-new-html-editor-extender-to-a-web-forms.aspx</guid>
            <pubDate>Wed, 17 Aug 2011 22:29:19 GMT</pubDate>
            <comments>http://stephenwalther.com/blog/archive/2011/08/17/adding-the-new-html-editor-extender-to-a-web-forms.aspx#feedback</comments>
            <slash:comments>1</slash:comments>
            <wfw:commentRss>http://stephenwalther.com/blog/comments/commentRss/170.aspx</wfw:commentRss>
        <feedburner:origLink>http://stephenwalther.com/blog/archive/2011/08/17/adding-the-new-html-editor-extender-to-a-web-forms.aspx</feedburner:origLink></item>
    </channel>
</rss>

