<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>SpinOneSolutions &#187; AJAX ASP.NET</title>
	<atom:link href="http://www.spinonesolutions.com/tag/ajax-aspnet/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.spinonesolutions.com</link>
	<description>I waste my time so that you don't have to...</description>
	<lastBuildDate>Fri, 16 Apr 2010 21:39:11 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>Wrap AJAX Updates with Client Side Notifications</title>
		<link>http://www.spinonesolutions.com/2008/12/wrap-ajax-updates-with-client-side-notifications/</link>
		<comments>http://www.spinonesolutions.com/2008/12/wrap-ajax-updates-with-client-side-notifications/#comments</comments>
		<pubDate>Tue, 23 Dec 2008 00:43:22 +0000</pubDate>
		<dc:creator>Will Wright</dc:creator>
				<category><![CDATA[AJAX]]></category>
		<category><![CDATA[ASP.NET]]></category>
		<category><![CDATA[AJAX ASP.NET]]></category>

		<guid isPermaLink="false">http://www.spinonesolutions.com/?p=4</guid>
		<description><![CDATA[The Problem Loading in content using AJAX is definitely, totally awesome.  A feature that I appreciate, when I see it, is client side notification of what&#8217;s going on asynchronously.  Of course; it&#8217;s not always appropriate since we are are, after all, trying to lighten up the users experience.  When you&#8217;re loading big chunks, that might [...]]]></description>
			<content:encoded><![CDATA[<h3>The Problem</h3>
<p>Loading in content using AJAX is definitely, totally awesome.  A feature that I appreciate, when I see it, is client side notification of what&#8217;s going on asynchronously.  Of course; it&#8217;s not always appropriate since we are are, after all, trying to lighten up the users experience.  When you&#8217;re loading big chunks, that might take a while, or fulfilling requests, like update or delete, I think that providing some feedback is good practice.</p>
<p>Let&#8217;s say that I have a big block of heavy content that will be interactive.  For shameless self-promotion I&#8217;ll use my photo gallery on <a href="http://www.willwrightphotography.com">WillWrightPhotography.com</a> as the example.</p>
<p style="text-align: center;"><img class="size-medium wp-image-37 aligncenter" title="Will Wright Photography" src="http://www.spinonesolutions.com/wp-content/uploads/2008/12/willwrightphotography-300x203.jpg" alt="Will Wright Photography" width="300" height="203" /></p>
<p>Here we have a more or less static header and footer, with a center content well that is interative.  This interface provides an excellent opportunity to use AJAX for two reasons.</p>
<p>First, if I were to let the page load procedurally the whole site would be unavailable until the gallery was done loading.  Although you can&#8217;t see it from the front end, the gallery is cached on the server.  This is great for someone who&#8217;s coming to the site after the application has been started, but not so great for the person who&#8217;s request started the application in the first place.</p>
<p>Secondly, the user is able to filter the gallery by clicking on the &#8220;More&#8221; tab and selecting a keyword to filter by.  This results in a Postback in order to retrieve the new center well content.  The only thing changing is the gallery in the middle, so AJAX will provide the user with a much smoother experience.</p>
<p>Now, if I go ahead and take my own advice and use AJAX to load in the photo gallery asynchronously the user experience would be:</p>
<ol>
<li>User initiates Request</li>
<li>Server Returns Header and Footer</li>
<li>Server starts asynchronous request for photo gallery</li>
<li>User thinks page (blank gallery) is done loading</li>
<li>User leaves because you give them no return on their investment</li>
<li>Server never gets to Respond the gallery</li>
</ol>
<p>What we need to do is notify the user that something is going on behind the scenes.  Practically, I think that can be done by notifying the user when something has started and when something has ended.</p>
<p>So, let&#8217;s do that!</p>
<h3>The Solution</h3>
<p>Here&#8217;s a high level overview of what I want to accomplish.</p>
<ol>
<li>User initiates Request</li>
<li>Server Responds with UI (basically header and footer)</li>
<li>Start asynchronous request for the gallery</li>
<li>Notify the user that an asynchronous request has been made</li>
<li>Server Responds with the gallery</li>
<li>Notify the user that the asynchronous request has completed</li>
</ol>
<p><strong>Number one</strong> is taken care of for us. (Awesome)</p>
<p><strong>Number two</strong> is also taken care of for us.  (Why am reading this again?)</p>
<p><strong>Number three</strong>; finally, something I can expound upon!  I&#8217;m using master pages for my solution so what you&#8217;re seeing here is just the content page.</p>
<p>Default.aspx</p>
<pre name="code" class="html">
&lt;asp:Content ContentPlaceHolderID="body" runat='server'>
    &lt;asp:UpdatePanel ID="upGallery" OnLoad="upGallery_Load" runat="server">
        &lt;ContentTemplate>
            &lt;asp:Repeater runat="server" ID="gallery" OnItemDataBound="gallery_ItemDataBound">
                &lt;HeaderTemplate>
                    &lt;table cellpadding="0" cellspacing="0" border="0" class="gallery">
                        &lt;tr>
                &lt;/HeaderTemplate>
                &lt;ItemTemplate>
                    &lt;td>
                        &lt;uc:photo runat="server" ID="photoColumn1" file='<%# DataBinder.Eval(Container.DataItem, "file") %>' />
                    &lt;/td>
                &lt;/ItemTemplate>

                &lt;FooterTemplate>
                        &lt;/tr>
                    &lt;/table>
                &lt;/FooterTemplate>
            &lt;/asp:Repeater>
        &lt;/ContentTemplate>
    &lt;/asp:UpdatePanel>
&lt;/asp:Content>
</pre>
<p>Default.aspx.cs</p>
<pre name="code" class="c-sharp">
    protected void Page_Load(object sender, EventArgs e)
    {
            //Load the Gallery in Asyncronously
            string script = "window.addEvent('domready', function() {";
            script += "__doPostBack('" + upGallery.ClientID + "','');";
            script += "});";
            ScriptManager.RegisterClientScriptBlock(this, this.GetType(), System.Guid.NewGuid().ToString(), script, true);
        }
    }

    protected void upGallery_Load(object sender, EventArgs e)
    {
        if (IsPostBack)
        {
            BindData();
        }
    }
</pre>
<p>Let&#8217;s go through it.  The markup is pretty self-explanatory, just take note of the OnLoad function wireup.  When the UpdatePanel Load event fires it will be handled by upGallery_Load.</p>
<p>Let&#8217;s look at the code behind.  On Page_Load I&#8217;m registering some client side JavaScript that will run once the DOM has fully loaded.  I&#8217;m using <a href="http://www.mootools.net">MooTools</a> which explains the syntax shown above.  Once the DOM has fully loaded the client will initiate a Postback (Asynchronous) for the UpdatePanel.  Thanks to Encosia for writing an article on how to <a href="http://encosia.com/2007/07/13/easily-refresh-an-updatepanel-using-javascript/">Easily refresh an UpdatePanel, using JavaScript</a>.</p>
<p>Since we&#8217;ve wired up an event handler for the UpdatePanel&#8217;s OnLoad event and IsPostBack will be true, the server side code is going to call BindData().  Put you&#8217;re cycle hungry code in here and it&#8217;ll be run after the UI has already rendered.</p>
<p>Now when someone makes a request for the page the user will get some immediate feedback in the form of the UI, and the time consuming request for the gallery is now running in the background.  Eventually BindData() will finish and the Server will respond with the gallery.  </p>
<p>We could stop right here, but let&#8217;s get fancy and add some client side notifications so that the user knows something is happening and should wait around for the results.</p>
<p><strong>Number four</strong> notify the user that an asynchronous request has been made.  We can do this with a couple of modifications.</p>
<p>Default.master (partial)</p>
<pre name="code" class="html">
&lt;head runat="server">
    &lt;meta http-equiv="Content-type" content="text/html;charset=UTF-8" />
    &lt;script type="text/javascript" language="javascript">
        function BeginRequestHandler(sender, args) {
            alert("Loading Gallery");
        }
    &lt;/script>
&lt;/head>
</pre>
<p>Default.aspx.cs</p>
<pre name="code" class="c-sharp">
    protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            //Register the aync begin request handler
            //Load the Gallery in Asyncronously
            string script = "window.addEvent('domready', function() {";
            script += "Sys.WebForms.PageRequestManager.getInstance().add_beginRequest(BeginRequestHandler);";
            script += "__doPostBack('" + upGallery.ClientID + "','');";
            script += "});";
            ScriptManager.RegisterClientScriptBlock(this, this.GetType(), System.Guid.NewGuid().ToString(), script, true);
        }
    }
</pre>
<p>I&#8217;ve defined a JavaScript function on the master page called BeginRequestHandler, and I&#8217;m registering it as an event handler for PageRequestManager&#8217;s beginRequest event.  Check out MSDN&#8217;s <a href="http://msdn.microsoft.com/en-us/library/bb311028.aspx">documentation</a> for more info on that.  Make sure you wire up the event handler <strong>before</strong> you call __doPostBack().  If you don&#8217;t your handler won&#8217;t be called and you&#8217;re user won&#8217;t be notified.</p>
<p>From MSDN, the description for Sys.WebForms.PageRequestManager beginRequest Event is</p>
<blockquote><p>
Raised before processing of an asynchronous postback starts and the postback request is sent to the server.
</p></blockquote>
<p>In other words, when the Request for my gallery is made show an Alert to the user.</p>
<p><strong>Number five</strong>, well, we&#8217;ve already taken care of that with BindData().</p>
<p><strong>Number Six</strong> notify the user that the asynchronous request has ended.  We&#8217;ve already seen how to write for the beginRequest event and I&#8217;m sure you followed my link to the MSDN documentation for PageRequestManager, so this is going to be easy.  Let&#8217;s make two more modifications:</p>
<p>Default.master (partial)</p>
<pre name="code" class="html">
&lt;head runat="server">
    &lt;meta http-equiv="Content-type" content="text/html;charset=UTF-8" />
    &lt;script type="text/javascript" language="javascript">
        function BeginRequestHandler(sender, args) {
            alert("Loading Gallery");
        }

        function EndRequestHandler(sender, args) {
            alert("Done");
        }
    &lt;/script>
&lt;/head>
</pre>
<p>Default.aspx.cs</p>
<pre name="code" class="c-sharp">
    protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            //Register the aync begin/end request handlers
            //Load the Gallery in Asyncronously
            string script = "window.addEvent('domready', function() {";
            script += "Sys.WebForms.PageRequestManager.getInstance().add_beginRequest(BeginRequestHandler);";
            script += "Sys.WebForms.PageRequestManager.getInstance().add_endRequest(EndRequestHandler);";
            script += "__doPostBack('" + upGallery.ClientID + "','');";
            script += "});";
            ScriptManager.RegisterClientScriptBlock(this, this.GetType(), System.Guid.NewGuid().ToString(), script, true);
        }
    }
</pre>
<p>Now I&#8217;ve got two handlers wired to two events, beginRequest and endRequest.  That&#8217;s really all there is to it.  You could extend this to as many events provided by PageRequestManager as you&#8217;d like!</p>
<h3>Aesthetics</h3>
<p>As it stands I&#8217;ve got a JavaScript Alert popping up twice every time the gallery UpdatePanel is updated.  Not so aesthetically pleasing.  Something that is aesthetically pleasing is a Macintosh.  Let&#8217;s pull a Jobs and rip off someone else&#8217;s idea, dress it up, and resell it as our own (I&#8217;m not even going to do THAT really).</p>
<p>Head over to <a href="http://digitarald.de">digitarald.de</a> and check out the <a href="http://digitarald.de/project/roar/">Roar Notifications</a> project.</p>
<p>Lets implement this solution real quick so that our site not only functions well but looks hot too.</p>
<p>Default.master (partial)</p>
<pre name="code" class="html">
&lt;head runat="server">
    &lt;meta http-equiv="Content-type" content="text/html;charset=UTF-8" />
    &lt;link rel="stylesheet" href="../styles/roar.css" type="text/css" />
    &lt;script type="text/javascript" src="js/roar.js"></script>
    &lt;script type="text/javascript" language="javascript">
        var oRoar = new Roar({position:'upperRight',duration:4000});

        function BeginRequestHandler(sender, args) {
            oRoar.alert("Loading Gallery", "One moment please...");
        }

        function EndRequestHandler(sender, args) {
            oRoar.alert("Done", "Thank You!");
        }
    &lt;/script>
&lt;/head>
</pre>
<p>That&#8217;s it, we&#8217;re done!</p>
<h3>The Particulars</h3>
<p>I&#8217;m using the <a href="http://www.mootools.net">MooTools</a> framework which is why my JavaScript looks the way it does.  It&#8217;s also why I&#8217;ve used this <a href="http://digitarald.de/project/roar/">Roar Notifications</a> project.  You could surely use whatever notifications you want with whatever framework you want.</p>
<p>I&#8217;ve also written the JavaScript straight into my master page.  That&#8217;s cool for now but it might be more elegant to encapsulate it into it&#8217;s own .js file and then register that with the ScriptManager.  I had problems getting everything to load in the correct order, which is why I&#8217;ve done it the way I have, but I&#8217;m sure this is not an insurmountable issue and would only take the proper application of gray matter and space-time.</p>
<p>As always, questions and comments are welcome!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.spinonesolutions.com/2008/12/wrap-ajax-updates-with-client-side-notifications/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>
