<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:pingback="http://madskills.com/public/xml/rss/module/pingback/" 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:dc="http://purl.org/dc/elements/1.1/" version="2.0">
  <channel>
    <title>My Fried Tech! - Ajax</title>
    <link>http://www.myfriedmind.com/techBlog/</link>
    <description>oddities from my work</description>
    <language>en-us</language>
    <copyright>Matt Mcknight</copyright>
    <lastBuildDate>Mon, 21 Sep 2009 15:40:37 GMT</lastBuildDate>
    <generator>newtelligence dasBlog 2.3.9074.18820</generator>
    <managingEditor>matt@em.org</managingEditor>
    <webMaster>matt@em.org</webMaster>
    <item>
      <trackback:ping>http://www.myfriedmind.com/techBlog/Trackback.aspx?guid=fd211b39-bd6c-4a44-9e93-5a67ca4d0b74</trackback:ping>
      <pingback:server>http://www.myfriedmind.com/techBlog/pingback.aspx</pingback:server>
      <pingback:target>http://www.myfriedmind.com/techBlog/PermaLink,guid,fd211b39-bd6c-4a44-9e93-5a67ca4d0b74.aspx</pingback:target>
      <dc:creator>papabear</dc:creator>
      <wfw:comment>http://www.myfriedmind.com/techBlog/CommentView,guid,fd211b39-bd6c-4a44-9e93-5a67ca4d0b74.aspx</wfw:comment>
      <wfw:commentRss>http://www.myfriedmind.com/techBlog/SyndicationService.asmx/GetEntryCommentsRss?guid=fd211b39-bd6c-4a44-9e93-5a67ca4d0b74</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Part 1 - <a href="http://www.myfriedmind.com/techBlog/2009/06/30/AjaxHistoryAHowToPart1.aspx"><font color="#5c80b1">Introduction</font></a><br />
Part 2 - <a href="http://www.myfriedmind.com/techBlog/2009/07/01/AjaxHistoryAHowToPart2ABasicExample.aspx"><font color="#5c80b1">Basic
Example</font></a><br />
Part 3 - <a href="http://www.myfriedmind.com/techBlog/2009/07/09/AjaxHistoryAHowToPart3ComplexExampleC.aspx"><font color="#5c80b1">Complex
Example</font></a><br />
Part 4 - <a href="http://www.myfriedmind.com/techBlog/2009/07/09/AjaxHistoryAHowToPart4FinalNotes.aspx"><font color="#5c80b1">Final
Notes</font></a><br />
Bonus - <a href="http://www.myfriedmind.com/techBlog/2009/05/20/AjaxHistoryAndTheMementoPattern.aspx"><font color="#5c80b1">Ajax
History and the Memento Pattern</font></a><br />
Extra Bonus - <a href="http://www.myfriedmind.com/techBlog/2009/09/21/Opera9x10xFailingOnAjaxHistoryAndTheHackToFixIt.aspx">Issues
with Opera</a></p>
        <p>
I dedicate this blog to Tomi, who brought this issue to my attention. Without I would
be blissfully unaware that my ajax examples did not work with Opera.
</p>
        <p>
To make a long story short, the basic Ajax history points that are demonstrated starting
in <a href="http://www.myfriedmind.com/techBlog/2009/06/30/AjaxHistoryAHowToPart1.aspx">this
blog entry</a> and on <a href="http://www.myfriedmind.com/AjaxExamples/AjaxSimpleHistory.aspx">the
site</a> here fail miserably when used by Opera, even the most recent v 10. It would
go forward once and then fail on either the next history point or going backwards.
It worked fine if history was not stored.
</p>
        <p>
At first I thought that it might have to do with Validation, so I turned off
Event Validation and ValidateRequests but no dice. I tried modifying the LoadScriptBeforeUI
setting on the ScriptManager thinking that maybe Opera was attempting to access the
controls before they were instantiated. No dice.
</p>
        <p>
Looking at the "Error Console" in Opera gave this confusing information:
</p>
        <blockquote dir="ltr" style="MARGIN-RIGHT: 0px">
          <p>
JavaScript - <a href="http://www.myfriedmind.com/ajaxexamples/AjaxSimplehistory.aspx">http://www.myfriedmind.com/ajaxexamples/AjaxSimplehistory.aspx</a><br />
Unknown thread<br />
Error:<br />
name: Sys.WebForms.PageRequestManagerServerErrorException<br />
message: Sys.WebForms.PageRequestManagerServerErrorException: An unknown error occurred
while processing the request on the server. The status code returned from the server
was: 400<br />
stacktrace:   Line 5 of linked script <a href="http://www.myfriedmind.com/ScriptResource.axd?d=Ca9Q30sQJzQkznL95cxsbDyIKgsvVPJZcb1rw8ROyNsMckgQG68w3ACHnEiANPBR_VaW0NUFhahnNTwkTQZ39NfZ8sEeH0NKN9NzfqKtjhs1&amp;t=40a63f28">http://www.myfriedmind.com/ScriptResource.axd?d=Ca9Q30sQJzQkznL95cxsbDyIKgsvVPJZcb1rw8ROyNsMckgQG68w3ACHnEiANP<br />
BR_VaW0NUFhahnNTwkTQZ39NfZ8sEeH0NKN9NzfqKtjhs1&amp;t=40a63f28</a><br />
    function(a,d,f){if(this._request===d.get_webRequest()){this._processingRequest=false;this._additionalInput=null;this._request=null}var
e=this._get_eventHandlerList().getHandler("endRequest"),b=false;if(e){var c=new Sys.WebForms.EndRequestEventArgs(a,f?f.dataItems:{},d);e(this,c);b=c.get_errorHandled()}if(a&amp;&amp;!b)throw
a}<br />
.....<br /></p>
        </blockquote>
        <p>
The key is that it was not returning the 200 that we all know and love, but a 400
status. Per <a href="http://support.microsoft.com/kb/247249">this Msoft article (kb
247249)</a> - 
</p>
        <blockquote dir="ltr" style="MARGIN-RIGHT: 0px">
          <p>
If the contents of a GET request are corrupt, then the server is unable to determine
the URL or the host to which the GET request should be sent. IIS is unable to retrieve
the host information from the GET request packet in order to look up the meta data
for the custom error. This is by design. Errors that result from severely corrupted
GET requests are not customizable.
</p>
        </blockquote>
        <p>
Now I KNOW that they are not corrupt. It works perfectly fine with IE and Firefox.
When I run it on Fiddler (<a href="http://www.fiddler2.com/">http://www.fiddler2.com/</a>)
- my go-to tool for troubleshooting odd Ajax problems I do see the 400 returned. Note
in the picture that the first three are for IE which work (all 200s) the second set
of three is for opera - the final one being the 400 error. 
</p>
        <p>
          <img src="http://www.myfriedmind.com/techBlog/content/binary/fiddlerOperAjaxError1.JPG" border="0" />
        </p>
        <p>
When I look at the raw data of that entry it tells me that the response is that it
is getting a Bad Request &lt;Invalid URL&gt; (see below). hmmmmm, should I trust it?
</p>
        <p>
          <img src="http://www.myfriedmind.com/techBlog/content/binary/fiddlerOperAjaxError2.JPG" border="0" />
        </p>
        <p>
Hunting and pecking I find various entries dealing with Opera and its issues with
Ajax, most of them from years ago. And then I discover this gem: <a href="http://www.webmasterworld.com/javascript/3195000.htm">http://www.webmasterworld.com/javascript/3195000.htm</a> which
has this notation near the end (italics mine)
</p>
        <blockquote dir="ltr" style="MARGIN-RIGHT: 0px">
          <p>
opera has a rather annoying bug. This occurred in both 8 and 9: If the URL is exactly
the same, the PHP file results are cached, and all the requests terminate as soon
as the first result is returned. IE does the same, but I was able to fix it by spitting
out a couple of "no-cache" headers. opera ignores these headers.
</p>
          <p>
            <em>
              <strong>I fixed that by adding an "id=" parameter to the URL, which made each
URL unique. This forced opera to stop caching. </strong>
            </em>
          </p>
        </blockquote>
        <p>
Wha??? So I added a querystring to the end of my url (it does not matter what it is)
and it worked! In other words <a href="http://www.myfriedmind.com/ajaxexamples/AjaxSimplehistory.aspx?x=y">http://www.myfriedmind.com/ajaxexamples/AjaxSimplehistory.aspx?x=y</a> will
work in Opera but <a href="http://www.myfriedmind.com/ajaxexamples/AjaxSimplehistory.aspx">http://www.myfriedmind.com/ajaxexamples/AjaxSimplehistory.aspx</a> will
not. 
</p>
        <p>
Now here is the odd part, and to display it I am going to direct you to a slight different
simple ajax example I just whipped up -&gt; <a href="http://www.myfriedmind.com/ajaxexamples/AjaxSimpleOpera.aspx">http://www.myfriedmind.com/ajaxexamples/AjaxSimpleOpera.aspx</a>.
I am also going to give you a behind the scenes look (via fiddler) as to what, exactly,
Opera is 'requesting'. The main modification I did was to change the length of the
text used for the history point (I am only going to store hour, minutes, seconds to
expedite this) to make it shorter and easier to view. 
</p>
        <p>
Again <a href="http://www.myfriedmind.com/ajaxexamples/AjaxSimpleOpera.aspx">http://www.myfriedmind.com/ajaxexamples/AjaxSimpleOpera.aspx</a> works
for the first one and fails for the second.
</p>
        <p>
First, let us look at what happens in IE per Fiddler (note that I only include the
querystring here for comparison, this example works in IE without it).
</p>
        <ul>
          <li>
clicking on <a href="http://www.myfriedmind.com/ajaxexamples/AjaxSimpleOpera.aspx?x=y">http://www.myfriedmind.com/ajaxexamples/AjaxSimpleOpera.aspx?x=y</a> <br />
Post /ajaxexamples/AjaxSimpleOpera.aspx 
<br />
new url: <a href="http://www.myfriedmind.com/ajaxexamples/AjaxSimpleOpera.aspx?x=y#&amp;&amp;myTime=042004">http://www.myfriedmind.com/ajaxexamples/AjaxSimpleOpera.aspx?x=y#&amp;&amp;myTime=042004</a></li>
          <li>
clicking on <a href="http://www.myfriedmind.com/ajaxexamples/AjaxSimpleOpera.aspx#&amp;&amp;myTime=042004">http://www.myfriedmind.com/ajaxexamples/AjaxSimpleOpera.aspx#&amp;&amp;myTime=042004</a> <br />
Post /ajaxexamples/AjaxSimpleOpera.aspx 
<br />
new url: <a href="http://www.myfriedmind.com/ajaxexamples/AjaxSimpleOpera.aspx#&amp;&amp;myTime=042006">http://www.myfriedmind.com/ajaxexamples/AjaxSimpleOpera.aspx#&amp;&amp;myTime=042006</a></li>
          <li>
clicking on <a href="http://www.myfriedmind.com/ajaxexamples/AjaxSimpleOpera.aspx#&amp;&amp;myTime=042006">http://www.myfriedmind.com/ajaxexamples/AjaxSimpleOpera.aspx#&amp;&amp;myTime=042006</a>  <br />
Post /ajaxexamples/AjaxSimpleOpera.aspx 
<br />
new url: <a href="http://www.myfriedmind.com/ajaxexamples/AjaxSimpleOpera.aspx#&amp;&amp;myTime=042007">http://www.myfriedmind.com/ajaxexamples/AjaxSimpleOpera.aspx#&amp;&amp;myTime=042007</a></li>
          <li>
clicking on <a href="http://www.myfriedmind.com/ajaxexamples/AjaxSimpleOpera.aspx#&amp;&amp;myTime=042007">http://www.myfriedmind.com/ajaxexamples/AjaxSimpleOpera.aspx#&amp;&amp;myTime=042007</a><br />
Post /ajaxexamples/AjaxSimpleOpera.aspx 
<br />
new url: <a href="http://www.myfriedmind.com/ajaxexamples/AjaxSimpleOpera.aspx#&amp;&amp;myTime=042008">http://www.myfriedmind.com/ajaxexamples/AjaxSimpleOpera.aspx#&amp;&amp;myTime=042008</a></li>
        </ul>
        <p>
Now the Opera per Fiddler - 
</p>
        <ul>
          <li>
Now adding a querystring on to the end - ex: <a href="http://www.myfriedmind.com/ajaxexamples/AjaxSimpleOpera.aspx?x=y">http://www.myfriedmind.com/ajaxexamples/AjaxSimpleOpera.aspx?x=y</a> works.
But notice what is happening behind the scenes with each click 
</li>
          <li>
click on <a href="http://www.myfriedmind.com/ajaxexamples/AjaxSimpleOpera.aspx?x=y">http://www.myfriedmind.com/ajaxexamples/AjaxSimpleOpera.aspx?x=y</a><br />
POST /ajaxexamples/AjaxSimpleOpera.aspx?x=y<br />
new url: <a href="http://www.myfriedmind.com/ajaxexamples/AjaxSimpleOpera.aspx?x=y#&amp;&amp;myTime=041426">http://www.myfriedmind.com/ajaxexamples/AjaxSimpleOpera.aspx?x=y#&amp;&amp;myTime=041426</a><a href="http://www.myfriedmind.com/ajaxexamples/AjaxSimpleOpera.aspx?x=y#&amp;&amp;myTime=041052"></a></li>
          <li>
click on <a href="http://www.myfriedmind.com/ajaxexamples/AjaxSimpleOpera.aspx?x=y#&amp;&amp;myTime=041426">http://www.myfriedmind.com/ajaxexamples/AjaxSimpleOpera.aspx?x=y#&amp;&amp;myTime=041426</a><br />
POST /ajaxexamples/AjaxSimpleOpera.aspx?x=y#&amp;&amp;myTime=041426<br />
new url: <a href="http://www.myfriedmind.com/ajaxexamples/AjaxSimpleOpera.aspx?x=y#&amp;&amp;myTime=041443">http://www.myfriedmind.com/ajaxexamples/AjaxSimpleOpera.aspx?x=y#&amp;&amp;myTime=041443</a><a href="http://www.myfriedmind.com/ajaxexamples/AjaxSimpleOpera.aspx?x=y#&amp;&amp;myTime=041118"></a></li>
          <li>
click on <a href="http://www.myfriedmind.com/ajaxexamples/AjaxSimpleOpera.aspx?x=y#&amp;&amp;myTime=041443">http://www.myfriedmind.com/ajaxexamples/AjaxSimpleOpera.aspx?x=y#&amp;&amp;myTime=041443</a><br />
POST /ajaxexamples/AjaxSimpleOpera.aspx?x=y%23&amp;&amp;myTime=041426#&amp;&amp;myTime=041443<br />
new url: <a href="http://www.myfriedmind.com/ajaxexamples/AjaxSimpleOpera.aspx?x=y#&amp;&amp;myTime=041443">http://www.myfriedmind.com/ajaxexamples/AjaxSimpleOpera.aspx?x=y#&amp;&amp;myTime=041443</a></li>
          <li>
click on <a href="http://www.myfriedmind.com/ajaxexamples/AjaxSimpleOpera.aspx?x=y#&amp;&amp;myTime=041443">http://www.myfriedmind.com/ajaxexamples/AjaxSimpleOpera.aspx?x=y#&amp;&amp;myTime=041443</a><br />
POST /ajaxexamples/AjaxSimpleOpera.aspx?x=y%23&amp;&amp;&amp;myTime=041426%23&amp;myTime=041443#&amp;&amp;myTime=041535<br />
new url: <a href="http://www.myfriedmind.com/ajaxexamples/AjaxSimpleOpera.aspx?x=y#&amp;&amp;myTime=0414535">http://www.myfriedmind.com/ajaxexamples/AjaxSimpleOpera.aspx?x=y#&amp;&amp;myTime=0414535</a></li>
          <li>
click on <a href="http://www.myfriedmind.com/ajaxexamples/AjaxSimpleOpera.aspx?x=y#&amp;&amp;myTime=0414535">http://www.myfriedmind.com/ajaxexamples/AjaxSimpleOpera.aspx?x=y#&amp;&amp;myTime=0414535</a><br />
POST /ajaxexamples/AjaxSimpleOpera.aspx?x=y%23&amp;&amp;&amp;&amp;myTime=041426%23&amp;myTime=041443%23&amp;myTime=041535#&amp;&amp;myTime=041537<br />
new url: <a href="http://www.myfriedmind.com/ajaxexamples/AjaxSimpleOpera.aspx?x=y#&amp;&amp;myTime=041542">http://www.myfriedmind.com/ajaxexamples/AjaxSimpleOpera.aspx?x=y#&amp;&amp;myTime=041542</a></li>
        </ul>
        <p>
Okay, okay, there was a long time between clicks (I was pasting it over), but do you
notice anything different between the two (pay attention to the POST that is done
via Ajax)? Internet Explorer ALWAYS Posts to the same URL - it ignores the hash entry.
Opera prepends the previous hash entry after encoding it for the url, and so it gets
longer and longer. 
</p>
        <p>
What is really, really odd is that Opera keeps prepending EVEN WHEN YOU HIT THE BACK
BUTTON! So moving back and forth in your ajax history means that you are getting a
longer and longer request entry. If you want to see this, snag fiddler -&gt; <a href="http://www.fiddler2.com">http://www.fiddler2.com</a> and
try it. Your POST request gets longer and longer due to the prepending, but the URL
does not reflect this at all. This ALL happens under the covers.
</p>
        <p>
I finally went into Opera and tried turning off ALL caching (disk and otherwise).
No luck! And when I set it to pretend to be IE it threw an error on the history point
setting, claiming it was not asynchronous. I even went into opera:config under User
Prefs and set the "History Navigation Mode" to 1 per this article <a href="http://www.opera.com/support/kb/view/827/">http://www.opera.com/support/kb/view/827/</a> to
prevent what it calls "fast history navigation". Still no dice! I even set the Opera
to "Always Reload Https In History" and then connected via https to the page and that
failed as well.
</p>
        <p>
So why does adding a query string work? I honestly don't know. But this might be a
clue - when it succeeded the hash was passed as a query string variable in Opera.
When it failed, no query string was passed at all. There are a number of posts all
over the web that refer to Opera caching when it should not, so I suspect that
that may indeed be the issue - Opera is caching the page regardless of what it
is told. Only by including the query string can you force Opera to not do whatever
it is doing.
</p>
        <p dir="ltr">
So there appear to be three solutions
</p>
        <ol>
          <li>
Don't use Ajax history for Opera unless you use a query string (it might work in systems
other than .net, I have not tested this) 
</li>
          <li>
Get Opera to fix the issue (good luck!) 
</li>
          <li>
Make sure you have a querystring, even a nonsense one, if your users will be using
Opera...</li>
        </ol>
        <p>
Happy coding!
</p>
        <p>
----------
</p>
        <p>
Further notes:
</p>
        <p>
This article -&gt; <a href="http://cfis.savagexi.com/2007/06/12/opera-ajax-and-bugs">http://cfis.savagexi.com/2007/06/12/opera-ajax-and-bugs</a> talks
about an issue with Opera rejecting status codes other than 200. However that is probably
not the issue since it should be returning a 200 code anyway. Just something to keep
in mind.
</p>
        <p>
Now I should note assuming that it was a caching issue I added a bunch of code to
prevent caching - including the ones below:
</p>
        <blockquote dir="ltr" style="MARGIN-RIGHT: 0px">
          <p>
Response.ClearHeaders();<br />
Response.AppendHeader("Cache-Control", "no-cache"); 
<br />
Response.AppendHeader("Cache-Control", "private"); 
<br />
Response.AppendHeader("Cache-Control", "no-store"); 
<br />
Response.AppendHeader("Cache-Control", "must-revalidate"); 
<br />
Response.AppendHeader("Cache-Control", "max-stale=0");  
<br />
Response.AppendHeader("Cache-Control", "post-check=0");  
<br />
Response.AppendHeader("Cache-Control", "pre-check=0");  
<br />
Response.AppendHeader("Pragma", "no-cache");  
<br />
Response.AppendHeader("Keep-Alive", "timeout=3, max=993");  
<br />
Response.AppendHeader("Expires", "Mon, 26 Jul 1997 05:00:00 GMT"); 
<br />
Response.Cache.SetExpires(DateTime.UtcNow.AddMinutes(-1));<br />
Response.Cache.SetCacheability(HttpCacheability.NoCache);<br />
Response.Cache.SetNoStore();
</p>
        </blockquote>
        <p dir="ltr">
But again, the only thing that appears to resolve the issue is the inclusion of a
query string.
</p>
        <img width="0" height="0" src="http://www.myfriedmind.com/techBlog/aggbug.ashx?id=fd211b39-bd6c-4a44-9e93-5a67ca4d0b74" />
      </body>
      <title>Opera 9.x, 10.x failing on Ajax history and the hack to fix it</title>
      <guid isPermaLink="false">http://www.myfriedmind.com/techBlog/PermaLink,guid,fd211b39-bd6c-4a44-9e93-5a67ca4d0b74.aspx</guid>
      <link>http://www.myfriedmind.com/techBlog/2009/09/21/Opera9x10xFailingOnAjaxHistoryAndTheHackToFixIt.aspx</link>
      <pubDate>Mon, 21 Sep 2009 15:40:37 GMT</pubDate>
      <description>&lt;p&gt;
Part 1 - &lt;a href="http://www.myfriedmind.com/techBlog/2009/06/30/AjaxHistoryAHowToPart1.aspx"&gt;&lt;font color=#5c80b1&gt;Introduction&lt;/font&gt;&lt;/a&gt;
&lt;br&gt;
Part 2 - &lt;a href="http://www.myfriedmind.com/techBlog/2009/07/01/AjaxHistoryAHowToPart2ABasicExample.aspx"&gt;&lt;font color=#5c80b1&gt;Basic
Example&lt;/font&gt;&lt;/a&gt;
&lt;br&gt;
Part 3 - &lt;a href="http://www.myfriedmind.com/techBlog/2009/07/09/AjaxHistoryAHowToPart3ComplexExampleC.aspx"&gt;&lt;font color=#5c80b1&gt;Complex
Example&lt;/font&gt;&lt;/a&gt;
&lt;br&gt;
Part 4 - &lt;a href="http://www.myfriedmind.com/techBlog/2009/07/09/AjaxHistoryAHowToPart4FinalNotes.aspx"&gt;&lt;font color=#5c80b1&gt;Final
Notes&lt;/font&gt;&lt;/a&gt;
&lt;br&gt;
Bonus - &lt;a href="http://www.myfriedmind.com/techBlog/2009/05/20/AjaxHistoryAndTheMementoPattern.aspx"&gt;&lt;font color=#5c80b1&gt;Ajax
History and the Memento Pattern&lt;/font&gt;&lt;/a&gt;
&lt;br&gt;
Extra Bonus - &lt;a href="http://www.myfriedmind.com/techBlog/2009/09/21/Opera9x10xFailingOnAjaxHistoryAndTheHackToFixIt.aspx"&gt;Issues
with Opera&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
I dedicate this blog to Tomi, who brought this issue to my attention. Without I would
be blissfully unaware that my ajax examples did not work with Opera.
&lt;/p&gt;
&lt;p&gt;
To make a long story short, the basic Ajax history points that are demonstrated starting
in &lt;a href="http://www.myfriedmind.com/techBlog/2009/06/30/AjaxHistoryAHowToPart1.aspx"&gt;this
blog entry&lt;/a&gt; and on &lt;a href="http://www.myfriedmind.com/AjaxExamples/AjaxSimpleHistory.aspx"&gt;the
site&lt;/a&gt; here fail miserably when used by Opera, even the most recent v 10. It would
go forward once and then fail on either the next history point or going backwards.
It worked fine if history was not stored.
&lt;/p&gt;
&lt;p&gt;
At first I thought that&amp;nbsp;it might have to do with Validation, so I turned off
Event Validation and ValidateRequests but no dice. I tried modifying the LoadScriptBeforeUI
setting on the ScriptManager thinking that maybe Opera was attempting to access the
controls before they were instantiated. No dice.
&lt;/p&gt;
&lt;p&gt;
Looking at the "Error Console" in Opera gave this confusing information:
&lt;/p&gt;
&lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&gt; 
&lt;p&gt;
JavaScript - &lt;a href="http://www.myfriedmind.com/ajaxexamples/AjaxSimplehistory.aspx"&gt;http://www.myfriedmind.com/ajaxexamples/AjaxSimplehistory.aspx&lt;/a&gt;
&lt;br&gt;
Unknown thread&lt;br&gt;
Error:&lt;br&gt;
name: Sys.WebForms.PageRequestManagerServerErrorException&lt;br&gt;
message: Sys.WebForms.PageRequestManagerServerErrorException: An unknown error occurred
while processing the request on the server. The status code returned from the server
was: 400&lt;br&gt;
stacktrace:&amp;nbsp;&amp;nbsp; Line 5 of linked script &lt;a href="http://www.myfriedmind.com/ScriptResource.axd?d=Ca9Q30sQJzQkznL95cxsbDyIKgsvVPJZcb1rw8ROyNsMckgQG68w3ACHnEiANPBR_VaW0NUFhahnNTwkTQZ39NfZ8sEeH0NKN9NzfqKtjhs1&amp;amp;t=40a63f28"&gt;http://www.myfriedmind.com/ScriptResource.axd?d=Ca9Q30sQJzQkznL95cxsbDyIKgsvVPJZcb1rw8ROyNsMckgQG68w3ACHnEiANP&lt;br&gt;
BR_VaW0NUFhahnNTwkTQZ39NfZ8sEeH0NKN9NzfqKtjhs1&amp;amp;t=40a63f28&lt;/a&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; function(a,d,f){if(this._request===d.get_webRequest()){this._processingRequest=false;this._additionalInput=null;this._request=null}var
e=this._get_eventHandlerList().getHandler("endRequest"),b=false;if(e){var c=new Sys.WebForms.EndRequestEventArgs(a,f?f.dataItems:{},d);e(this,c);b=c.get_errorHandled()}if(a&amp;amp;&amp;amp;!b)throw
a}&lt;br&gt;
.....&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
The key is that it was not returning the 200 that we all know and love, but a 400
status. Per &lt;a href="http://support.microsoft.com/kb/247249"&gt;this Msoft article (kb
247249)&lt;/a&gt;&amp;nbsp;- 
&lt;/p&gt;
&lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&gt; 
&lt;p&gt;
If the contents of a GET request are corrupt, then the server is unable to determine
the URL or the host to which the GET request should be sent. IIS is unable to retrieve
the host information from the GET request packet in order to look up the meta data
for the custom error. This is by design. Errors that result from severely corrupted
GET requests are not customizable.
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
Now I KNOW that they are not corrupt. It works perfectly fine with IE and Firefox.
When I run it on Fiddler (&lt;a href="http://www.fiddler2.com/"&gt;http://www.fiddler2.com/&lt;/a&gt;)
- my go-to tool for troubleshooting odd Ajax problems I do see the 400 returned. Note
in the picture that the first three are for IE which work (all 200s) the second set
of three is for opera - the final one being the 400 error. 
&lt;/p&gt;
&lt;p&gt;
&lt;img src="http://www.myfriedmind.com/techBlog/content/binary/fiddlerOperAjaxError1.JPG" border=0&gt;
&lt;/p&gt;
&lt;p&gt;
When I look at the raw data of that entry it tells me that the response is that it
is getting a Bad Request &amp;lt;Invalid URL&amp;gt; (see below). hmmmmm, should I trust it?
&lt;/p&gt;
&lt;p&gt;
&lt;img src="http://www.myfriedmind.com/techBlog/content/binary/fiddlerOperAjaxError2.JPG" border=0&gt;
&lt;/p&gt;
&lt;p&gt;
Hunting and pecking I find various entries dealing with Opera and its issues with
Ajax, most of them from years ago. And then I discover this gem: &lt;a href="http://www.webmasterworld.com/javascript/3195000.htm"&gt;http://www.webmasterworld.com/javascript/3195000.htm&lt;/a&gt;&amp;nbsp;which
has this notation near the end (italics mine)
&lt;/p&gt;
&lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&gt; 
&lt;p&gt;
opera has a rather annoying bug. This occurred in both 8 and 9: If the URL is exactly
the same, the PHP file results are cached, and all the requests terminate as soon
as the first result is returned. IE does the same, but I was able to fix it by spitting
out a couple of "no-cache" headers. opera ignores these headers.
&lt;/p&gt;
&lt;p&gt;
&lt;em&gt;&lt;strong&gt;I fixed that by adding an "id=" parameter to the URL, which made each
URL unique. This forced opera to stop caching. &lt;/strong&gt;&lt;/em&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
Wha??? So I added a querystring to the end of my url (it does not matter what it is)
and it worked! In other words &lt;a href="http://www.myfriedmind.com/ajaxexamples/AjaxSimplehistory.aspx?x=y"&gt;http://www.myfriedmind.com/ajaxexamples/AjaxSimplehistory.aspx?x=y&lt;/a&gt; will
work in Opera&amp;nbsp;but &lt;a href="http://www.myfriedmind.com/ajaxexamples/AjaxSimplehistory.aspx"&gt;http://www.myfriedmind.com/ajaxexamples/AjaxSimplehistory.aspx&lt;/a&gt;&amp;nbsp;will
not. 
&lt;/p&gt;
&lt;p&gt;
Now here is the odd part, and to display it I am going to direct you to a slight different
simple ajax example I just whipped up -&amp;gt; &lt;a href="http://www.myfriedmind.com/ajaxexamples/AjaxSimpleOpera.aspx"&gt;http://www.myfriedmind.com/ajaxexamples/AjaxSimpleOpera.aspx&lt;/a&gt;.
I am also going to give you a behind the scenes look (via fiddler) as to what, exactly,
Opera is 'requesting'. The main modification I did was to change the length of the
text used for the history point (I am only going to store hour, minutes, seconds to
expedite this) to make it shorter and easier to view. 
&lt;/p&gt;
&lt;p&gt;
Again &lt;a href="http://www.myfriedmind.com/ajaxexamples/AjaxSimpleOpera.aspx"&gt;http://www.myfriedmind.com/ajaxexamples/AjaxSimpleOpera.aspx&lt;/a&gt;&amp;nbsp;works
for the first one and fails for the second.
&lt;/p&gt;
&lt;p&gt;
First, let us look at what happens in IE per Fiddler (note that I only include the
querystring here for comparison, this example works in IE without it).
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
clicking&amp;nbsp;on &lt;a href="http://www.myfriedmind.com/ajaxexamples/AjaxSimpleOpera.aspx?x=y"&gt;http://www.myfriedmind.com/ajaxexamples/AjaxSimpleOpera.aspx?x=y&lt;/a&gt;&amp;nbsp;&lt;br&gt;
Post /ajaxexamples/AjaxSimpleOpera.aspx 
&lt;br&gt;
new url: &lt;a href="http://www.myfriedmind.com/ajaxexamples/AjaxSimpleOpera.aspx?x=y#&amp;amp;&amp;amp;myTime=042004"&gt;http://www.myfriedmind.com/ajaxexamples/AjaxSimpleOpera.aspx?x=y#&amp;amp;&amp;amp;myTime=042004&lt;/a&gt; 
&lt;li&gt;
clicking&amp;nbsp;on &lt;a href="http://www.myfriedmind.com/ajaxexamples/AjaxSimpleOpera.aspx#&amp;amp;&amp;amp;myTime=042004"&gt;http://www.myfriedmind.com/ajaxexamples/AjaxSimpleOpera.aspx#&amp;amp;&amp;amp;myTime=042004&lt;/a&gt;&amp;nbsp;&lt;br&gt;
Post /ajaxexamples/AjaxSimpleOpera.aspx 
&lt;br&gt;
new url: &lt;a href="http://www.myfriedmind.com/ajaxexamples/AjaxSimpleOpera.aspx#&amp;amp;&amp;amp;myTime=042006"&gt;http://www.myfriedmind.com/ajaxexamples/AjaxSimpleOpera.aspx#&amp;amp;&amp;amp;myTime=042006&lt;/a&gt; 
&lt;li&gt;
clicking&amp;nbsp;on &lt;a href="http://www.myfriedmind.com/ajaxexamples/AjaxSimpleOpera.aspx#&amp;amp;&amp;amp;myTime=042006"&gt;http://www.myfriedmind.com/ajaxexamples/AjaxSimpleOpera.aspx#&amp;amp;&amp;amp;myTime=042006&lt;/a&gt; &amp;nbsp;&lt;br&gt;
Post /ajaxexamples/AjaxSimpleOpera.aspx 
&lt;br&gt;
new url: &lt;a href="http://www.myfriedmind.com/ajaxexamples/AjaxSimpleOpera.aspx#&amp;amp;&amp;amp;myTime=042007"&gt;http://www.myfriedmind.com/ajaxexamples/AjaxSimpleOpera.aspx#&amp;amp;&amp;amp;myTime=042007&lt;/a&gt; 
&lt;li&gt;
clicking&amp;nbsp;on &lt;a href="http://www.myfriedmind.com/ajaxexamples/AjaxSimpleOpera.aspx#&amp;amp;&amp;amp;myTime=042007"&gt;http://www.myfriedmind.com/ajaxexamples/AjaxSimpleOpera.aspx#&amp;amp;&amp;amp;myTime=042007&lt;/a&gt;
&lt;br&gt;
Post /ajaxexamples/AjaxSimpleOpera.aspx 
&lt;br&gt;
new url: &lt;a href="http://www.myfriedmind.com/ajaxexamples/AjaxSimpleOpera.aspx#&amp;amp;&amp;amp;myTime=042008"&gt;http://www.myfriedmind.com/ajaxexamples/AjaxSimpleOpera.aspx#&amp;amp;&amp;amp;myTime=042008&lt;/a&gt; 
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
Now the Opera per&amp;nbsp;Fiddler&amp;nbsp;- 
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
Now adding a querystring on to the end - ex: &lt;a href="http://www.myfriedmind.com/ajaxexamples/AjaxSimpleOpera.aspx?x=y"&gt;http://www.myfriedmind.com/ajaxexamples/AjaxSimpleOpera.aspx?x=y&lt;/a&gt; works.
But notice what is happening behind the scenes with each click 
&lt;li&gt;
click on &lt;a href="http://www.myfriedmind.com/ajaxexamples/AjaxSimpleOpera.aspx?x=y"&gt;http://www.myfriedmind.com/ajaxexamples/AjaxSimpleOpera.aspx?x=y&lt;/a&gt;
&lt;br&gt;
POST /ajaxexamples/AjaxSimpleOpera.aspx?x=y&lt;br&gt;
new url: &lt;a href="http://www.myfriedmind.com/ajaxexamples/AjaxSimpleOpera.aspx?x=y#&amp;amp;&amp;amp;myTime=041426"&gt;http://www.myfriedmind.com/ajaxexamples/AjaxSimpleOpera.aspx?x=y#&amp;amp;&amp;amp;myTime=041426&lt;/a&gt;&lt;a href="http://www.myfriedmind.com/ajaxexamples/AjaxSimpleOpera.aspx?x=y#&amp;amp;&amp;amp;myTime=041052"&gt;&lt;/a&gt; 
&lt;li&gt;
click on &lt;a href="http://www.myfriedmind.com/ajaxexamples/AjaxSimpleOpera.aspx?x=y#&amp;amp;&amp;amp;myTime=041426"&gt;http://www.myfriedmind.com/ajaxexamples/AjaxSimpleOpera.aspx?x=y#&amp;amp;&amp;amp;myTime=041426&lt;/a&gt;
&lt;br&gt;
POST /ajaxexamples/AjaxSimpleOpera.aspx?x=y#&amp;amp;&amp;amp;myTime=041426&lt;br&gt;
new url: &lt;a href="http://www.myfriedmind.com/ajaxexamples/AjaxSimpleOpera.aspx?x=y#&amp;amp;&amp;amp;myTime=041443"&gt;http://www.myfriedmind.com/ajaxexamples/AjaxSimpleOpera.aspx?x=y#&amp;amp;&amp;amp;myTime=041443&lt;/a&gt;&lt;a href="http://www.myfriedmind.com/ajaxexamples/AjaxSimpleOpera.aspx?x=y#&amp;amp;&amp;amp;myTime=041118"&gt;&lt;/a&gt; 
&lt;li&gt;
click on &lt;a href="http://www.myfriedmind.com/ajaxexamples/AjaxSimpleOpera.aspx?x=y#&amp;amp;&amp;amp;myTime=041443"&gt;http://www.myfriedmind.com/ajaxexamples/AjaxSimpleOpera.aspx?x=y#&amp;amp;&amp;amp;myTime=041443&lt;/a&gt;
&lt;br&gt;
POST /ajaxexamples/AjaxSimpleOpera.aspx?x=y%23&amp;amp;&amp;amp;myTime=041426#&amp;amp;&amp;amp;myTime=041443&lt;br&gt;
new url: &lt;a href="http://www.myfriedmind.com/ajaxexamples/AjaxSimpleOpera.aspx?x=y#&amp;amp;&amp;amp;myTime=041443"&gt;http://www.myfriedmind.com/ajaxexamples/AjaxSimpleOpera.aspx?x=y#&amp;amp;&amp;amp;myTime=041443&lt;/a&gt; 
&lt;li&gt;
click on &lt;a href="http://www.myfriedmind.com/ajaxexamples/AjaxSimpleOpera.aspx?x=y#&amp;amp;&amp;amp;myTime=041443"&gt;http://www.myfriedmind.com/ajaxexamples/AjaxSimpleOpera.aspx?x=y#&amp;amp;&amp;amp;myTime=041443&lt;/a&gt;
&lt;br&gt;
POST /ajaxexamples/AjaxSimpleOpera.aspx?x=y%23&amp;amp;&amp;amp;&amp;amp;myTime=041426%23&amp;amp;myTime=041443#&amp;amp;&amp;amp;myTime=041535&lt;br&gt;
new url: &lt;a href="http://www.myfriedmind.com/ajaxexamples/AjaxSimpleOpera.aspx?x=y#&amp;amp;&amp;amp;myTime=0414535"&gt;http://www.myfriedmind.com/ajaxexamples/AjaxSimpleOpera.aspx?x=y#&amp;amp;&amp;amp;myTime=0414535&lt;/a&gt; 
&lt;li&gt;
click on &lt;a href="http://www.myfriedmind.com/ajaxexamples/AjaxSimpleOpera.aspx?x=y#&amp;amp;&amp;amp;myTime=0414535"&gt;http://www.myfriedmind.com/ajaxexamples/AjaxSimpleOpera.aspx?x=y#&amp;amp;&amp;amp;myTime=0414535&lt;/a&gt;
&lt;br&gt;
POST /ajaxexamples/AjaxSimpleOpera.aspx?x=y%23&amp;amp;&amp;amp;&amp;amp;&amp;amp;myTime=041426%23&amp;amp;myTime=041443%23&amp;amp;myTime=041535#&amp;amp;&amp;amp;myTime=041537&lt;br&gt;
new url: &lt;a href="http://www.myfriedmind.com/ajaxexamples/AjaxSimpleOpera.aspx?x=y#&amp;amp;&amp;amp;myTime=041542"&gt;http://www.myfriedmind.com/ajaxexamples/AjaxSimpleOpera.aspx?x=y#&amp;amp;&amp;amp;myTime=041542&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
Okay, okay, there was a long time between clicks (I was pasting it over), but do you
notice anything different between the two (pay attention to the POST that is done
via Ajax)? Internet Explorer ALWAYS Posts to the same URL - it ignores the hash entry.
Opera prepends the previous hash entry after encoding it for the url, and so it gets
longer and longer. 
&lt;/p&gt;
&lt;p&gt;
What is really, really odd is that Opera keeps prepending EVEN WHEN YOU HIT THE BACK
BUTTON! So moving back and forth in your ajax history means that you are getting a
longer and longer request entry. If you want to see this, snag fiddler -&amp;gt; &lt;a href="http://www.fiddler2.com"&gt;http://www.fiddler2.com&lt;/a&gt; and
try it. Your POST request gets longer and longer due to the prepending, but the URL
does not reflect this at all. This ALL happens under the covers.
&lt;/p&gt;
&lt;p&gt;
I finally went into Opera and tried turning off ALL caching (disk and otherwise).
No luck! And when I set it to pretend to be IE it threw an error on the history point
setting, claiming it was not asynchronous. I even went into opera:config under User
Prefs and set the "History Navigation Mode" to 1 per this article &lt;a href="http://www.opera.com/support/kb/view/827/"&gt;http://www.opera.com/support/kb/view/827/&lt;/a&gt;&amp;nbsp;to
prevent what it calls "fast history navigation". Still no dice! I even set the Opera
to "Always Reload Https In History" and then connected via https to the page and that
failed as well.
&lt;/p&gt;
&lt;p&gt;
So why does adding a query string work? I honestly don't know. But this might be a
clue - when it succeeded the hash was passed as a query string variable in Opera.
When it failed, no query string was passed at all. There are a number of posts all
over the web that refer to Opera caching when it should not, so&amp;nbsp;I suspect that
that may indeed be the issue&amp;nbsp;- Opera is caching the page regardless of what it
is told. Only by including the query string can you force Opera to not do whatever
it is doing.
&lt;/p&gt;
&lt;p dir=ltr&gt;
So there appear to be three solutions
&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
Don't use Ajax history for Opera unless you use a query string (it might work in systems
other than .net, I have not tested this) 
&lt;li&gt;
Get Opera to fix the issue (good luck!) 
&lt;li&gt;
Make sure you have a querystring, even a nonsense one, if your users will be using
Opera...&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;
Happy coding!
&lt;/p&gt;
&lt;p&gt;
----------
&lt;/p&gt;
&lt;p&gt;
Further notes:
&lt;/p&gt;
&lt;p&gt;
This article -&amp;gt; &lt;a href="http://cfis.savagexi.com/2007/06/12/opera-ajax-and-bugs"&gt;http://cfis.savagexi.com/2007/06/12/opera-ajax-and-bugs&lt;/a&gt;&amp;nbsp;talks
about an issue with Opera rejecting status codes other than 200. However that is probably
not the issue since it should be returning a 200 code anyway. Just something to keep
in mind.
&lt;/p&gt;
&lt;p&gt;
Now I should note assuming that it was a caching issue I added a bunch of code to
prevent caching - including the ones below:
&lt;/p&gt;
&lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&gt; 
&lt;p&gt;
Response.ClearHeaders();&lt;br&gt;
Response.AppendHeader("Cache-Control", "no-cache"); 
&lt;br&gt;
Response.AppendHeader("Cache-Control", "private"); 
&lt;br&gt;
Response.AppendHeader("Cache-Control", "no-store"); 
&lt;br&gt;
Response.AppendHeader("Cache-Control", "must-revalidate"); 
&lt;br&gt;
Response.AppendHeader("Cache-Control", "max-stale=0");&amp;nbsp; 
&lt;br&gt;
Response.AppendHeader("Cache-Control", "post-check=0");&amp;nbsp; 
&lt;br&gt;
Response.AppendHeader("Cache-Control", "pre-check=0");&amp;nbsp; 
&lt;br&gt;
Response.AppendHeader("Pragma", "no-cache");&amp;nbsp; 
&lt;br&gt;
Response.AppendHeader("Keep-Alive", "timeout=3, max=993");&amp;nbsp; 
&lt;br&gt;
Response.AppendHeader("Expires", "Mon, 26 Jul 1997 05:00:00 GMT"); 
&lt;br&gt;
Response.Cache.SetExpires(DateTime.UtcNow.AddMinutes(-1));&lt;br&gt;
Response.Cache.SetCacheability(HttpCacheability.NoCache);&lt;br&gt;
Response.Cache.SetNoStore();
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p dir=ltr&gt;
But again, the only thing that appears to resolve the issue is the inclusion of a
query string.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.myfriedmind.com/techBlog/aggbug.ashx?id=fd211b39-bd6c-4a44-9e93-5a67ca4d0b74" /&gt;</description>
      <comments>http://www.myfriedmind.com/techBlog/CommentView,guid,fd211b39-bd6c-4a44-9e93-5a67ca4d0b74.aspx</comments>
      <category>Ajax</category>
      <category>Asp.Net</category>
      <category>Coding Tricks</category>
    </item>
    <item>
      <trackback:ping>http://www.myfriedmind.com/techBlog/Trackback.aspx?guid=2a008128-730b-4dd5-9cfa-e336a0b0a568</trackback:ping>
      <pingback:server>http://www.myfriedmind.com/techBlog/pingback.aspx</pingback:server>
      <pingback:target>http://www.myfriedmind.com/techBlog/PermaLink,guid,2a008128-730b-4dd5-9cfa-e336a0b0a568.aspx</pingback:target>
      <dc:creator>papabear</dc:creator>
      <wfw:comment>http://www.myfriedmind.com/techBlog/CommentView,guid,2a008128-730b-4dd5-9cfa-e336a0b0a568.aspx</wfw:comment>
      <wfw:commentRss>http://www.myfriedmind.com/techBlog/SyndicationService.asmx/GetEntryCommentsRss?guid=2a008128-730b-4dd5-9cfa-e336a0b0a568</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Part 1 - <a href="http://www.myfriedmind.com/techBlog/2009/06/30/AjaxHistoryAHowToPart1.aspx">Introduction</a><br />
Part 2 - <a href="http://www.myfriedmind.com/techBlog/2009/07/01/AjaxHistoryAHowToPart2ABasicExample.aspx">Basic
Example</a><br />
Part 3 - <a href="http://www.myfriedmind.com/techBlog/2009/07/09/AjaxHistoryAHowToPart3ComplexExampleC.aspx">Complex
Example</a><br />
Part 4 - <a href="http://www.myfriedmind.com/techBlog/2009/07/09/AjaxHistoryAHowToPart4FinalNotes.aspx">Final
Notes</a><br />
Bonus - <a href="http://www.myfriedmind.com/techBlog/2009/05/20/AjaxHistoryAndTheMementoPattern.aspx">Ajax
History and the Memento Pattern</a></p>
        <p>
There is some clean up I need to do in regards to my posts for Ajax History. 
</p>
        <p>
Where can I see an example?
</p>
        <p>
You can download the zipped files here -&gt; <a href="http://www.myfriedmind.com/techBlog/content/binary/AjaxExamples.zip">AjaxExamples.zip</a> or
go to <a href="http://www.myfriedmind.com/AjaxExamples">http://www.myfriedmind.com/AjaxExamples</a> and
poke around
</p>
        <h3>What version of .net do I need?
</h3>
        <p>
I want to reiterate that you must be using .net 3.5 (or higher) for this to function.
The methods and properties that are used are packaged into .net 3.5 (as is Ajax itself).
</p>
        <h3>How long does my history last (ie going back/forward)?
</h3>
        <p>
Your history lasts only as long as you are on that particular page. You can go forward
and backward over your Ajax history all you want, but once you got to a different
page, either preceding or following, you lose your pathway. This does not mean that
if you get one of the intermediate URIs either through bookmarks, links, manually
typing, etc that it will not return that particular page. It will. But the tracking
of the entries in your browser history will be lost. 
</p>
        <p>
This also means that if the user modifies the URI manuallyto change what is in
the has, it will lose that history since it considers you having gone to a new
page.
</p>
        <h3>What if I need to keep a perfect snapshot of the page itself? 
</h3>
        <p>
If that is the case then you are going to need to look at a different way to store/retrieve
the data. You will probably need to store each page, as it appears, into the database
and then recall it from there. Do NOT store it in the History Points Remember,
what is stored in the History Points must be tiny!
</p>
        <h3>Why does Opera NOT WORK???
</h3>
        <p>
          <a href="http://www.myfriedmind.com/techBlog/2009/09/21/Opera9x10xFailingOnAjaxHistoryAndTheHackToFixIt.aspx">http://www.myfriedmind.com/techBlog/2009/09/21/Opera9x10xFailingOnAjaxHistoryAndTheHackToFixIt.aspx</a> (thanks
to Tomi for discovering this issue)
</p>
        <img width="0" height="0" src="http://www.myfriedmind.com/techBlog/aggbug.ashx?id=2a008128-730b-4dd5-9cfa-e336a0b0a568" />
      </body>
      <title>Ajax History - a how to - Part 4 - final notes</title>
      <guid isPermaLink="false">http://www.myfriedmind.com/techBlog/PermaLink,guid,2a008128-730b-4dd5-9cfa-e336a0b0a568.aspx</guid>
      <link>http://www.myfriedmind.com/techBlog/2009/07/09/AjaxHistoryAHowToPart4FinalNotes.aspx</link>
      <pubDate>Thu, 09 Jul 2009 16:57:00 GMT</pubDate>
      <description>&lt;p&gt;
Part 1 - &lt;a href="http://www.myfriedmind.com/techBlog/2009/06/30/AjaxHistoryAHowToPart1.aspx"&gt;Introduction&lt;/a&gt;
&lt;br&gt;
Part 2 - &lt;a href="http://www.myfriedmind.com/techBlog/2009/07/01/AjaxHistoryAHowToPart2ABasicExample.aspx"&gt;Basic
Example&lt;/a&gt;
&lt;br&gt;
Part 3 - &lt;a href="http://www.myfriedmind.com/techBlog/2009/07/09/AjaxHistoryAHowToPart3ComplexExampleC.aspx"&gt;Complex
Example&lt;/a&gt;
&lt;br&gt;
Part 4 - &lt;a href="http://www.myfriedmind.com/techBlog/2009/07/09/AjaxHistoryAHowToPart4FinalNotes.aspx"&gt;Final
Notes&lt;/a&gt;
&lt;br&gt;
Bonus - &lt;a href="http://www.myfriedmind.com/techBlog/2009/05/20/AjaxHistoryAndTheMementoPattern.aspx"&gt;Ajax
History and the Memento Pattern&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
There is some clean up I need to do in regards to my posts for Ajax History. 
&lt;/p&gt;
&lt;p&gt;
Where can I see an example?
&lt;/p&gt;
&lt;p&gt;
You can download the zipped files here -&amp;gt; &lt;a href="http://www.myfriedmind.com/techBlog/content/binary/AjaxExamples.zip"&gt;AjaxExamples.zip&lt;/a&gt;&amp;nbsp;or
go to &lt;a href="http://www.myfriedmind.com/AjaxExamples"&gt;http://www.myfriedmind.com/AjaxExamples&lt;/a&gt; and
poke around
&lt;/p&gt;
&lt;h3&gt;What version of .net do I need?
&lt;/h3&gt;
&lt;p&gt;
I want to reiterate that you must be using .net 3.5 (or higher) for this to function.
The methods and properties that are used are packaged into .net 3.5 (as is Ajax itself).
&lt;/p&gt;
&lt;h3&gt;How long does my history last (ie going back/forward)?
&lt;/h3&gt;
&lt;p&gt;
Your history lasts only as long as you are on that particular page. You can go forward
and backward over your Ajax history all you want, but once you got to a different
page, either preceding or following, you lose your pathway. This does not mean that
if you get one of the intermediate URIs either through bookmarks, links, manually
typing, etc that it will not return that particular page. It will. But the tracking
of the entries in your browser history will be lost. 
&lt;/p&gt;
&lt;p&gt;
This also means that if the user modifies the URI manuallyto change what is&amp;nbsp;in
the has,&amp;nbsp;it will lose that history since it considers you having gone to a new
page.
&lt;/p&gt;
&lt;h3&gt;What if I need to keep a perfect snapshot of the page itself? 
&lt;/h3&gt;
&lt;p&gt;
If that is the case then you are going to need to look at a different way to store/retrieve
the data. You will probably need to store each page, as it appears, into the database
and then recall it from there. Do NOT store it in the History Points&amp;nbsp;Remember,
what is stored in the History Points must be tiny!
&lt;/p&gt;
&lt;h3&gt;Why does Opera NOT WORK???
&lt;/h3&gt;
&lt;p&gt;
&lt;a href="http://www.myfriedmind.com/techBlog/2009/09/21/Opera9x10xFailingOnAjaxHistoryAndTheHackToFixIt.aspx"&gt;http://www.myfriedmind.com/techBlog/2009/09/21/Opera9x10xFailingOnAjaxHistoryAndTheHackToFixIt.aspx&lt;/a&gt;&amp;nbsp;(thanks
to Tomi for discovering this issue)
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.myfriedmind.com/techBlog/aggbug.ashx?id=2a008128-730b-4dd5-9cfa-e336a0b0a568" /&gt;</description>
      <comments>http://www.myfriedmind.com/techBlog/CommentView,guid,2a008128-730b-4dd5-9cfa-e336a0b0a568.aspx</comments>
      <category>Ajax</category>
      <category>Asp.Net</category>
      <category>c#</category>
      <category>Coding Tricks</category>
      <category>VB.Net</category>
    </item>
    <item>
      <trackback:ping>http://www.myfriedmind.com/techBlog/Trackback.aspx?guid=823a3232-19ab-4ee1-ac9b-fbdf605e557b</trackback:ping>
      <pingback:server>http://www.myfriedmind.com/techBlog/pingback.aspx</pingback:server>
      <pingback:target>http://www.myfriedmind.com/techBlog/PermaLink,guid,823a3232-19ab-4ee1-ac9b-fbdf605e557b.aspx</pingback:target>
      <dc:creator>papabear</dc:creator>
      <wfw:comment>http://www.myfriedmind.com/techBlog/CommentView,guid,823a3232-19ab-4ee1-ac9b-fbdf605e557b.aspx</wfw:comment>
      <wfw:commentRss>http://www.myfriedmind.com/techBlog/SyndicationService.asmx/GetEntryCommentsRss?guid=823a3232-19ab-4ee1-ac9b-fbdf605e557b</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Part 1 - <a href="http://www.myfriedmind.com/techBlog/2009/06/30/AjaxHistoryAHowToPart1.aspx"><font color="#5c80b1">Introduction</font></a><br />
Part 2 - <a href="http://www.myfriedmind.com/techBlog/2009/07/01/AjaxHistoryAHowToPart2ABasicExample.aspx"><font color="#5c80b1">Basic
Example</font></a><br />
Part 3 - <a href="http://www.myfriedmind.com/techBlog/2009/07/09/AjaxHistoryAHowToPart3ComplexExampleC.aspx"><font color="#5c80b1">Complex
Example</font></a><br />
Part 4 - <a href="http://www.myfriedmind.com/techBlog/2009/07/09/AjaxHistoryAHowToPart4FinalNotes.aspx"><font color="#5c80b1">Final
Notes</font></a><br />
Bonus - <a href="http://www.myfriedmind.com/techBlog/2009/05/20/AjaxHistoryAndTheMementoPattern.aspx"><font color="#5c80b1">Ajax
History and the Memento Pattern</font></a><br />
Extra Bonus - <a href="http://www.myfriedmind.com/techBlog/2009/09/21/Opera9x10xFailingOnAjaxHistoryAndTheHackToFixIt.aspx"><font color="#5c80b1">Issues
with Opera</font></a></p>
        <p>
This is the third in a series looking at using Ajax History in .net 3.5. I would recommend
you look at <a href="http://www.myfriedmind.com/techBlog/2009/06/30/AjaxHistoryAHowToPart1.aspx">Part
1</a> and <a href="http://www.myfriedmind.com/techBlog/2009/07/01/AjaxHistoryAHowToPart2ABasicExample.aspx">Part
2</a> if you have not already done so.
</p>
        <p>
Ajax out of the box is wonderful in that it reduces page reloads, but it is not wonderful
in that it does not treat each Ajax call as a unique URI. As a result all Ajax modified
changes are lost when the Back or refresh button are clicked. In addition there is
no way to store the URL of the page in such a way that it will display the results
of Ajax changes. I explain much of this in <a href="http://www.myfriedmind.com/techBlog/2009/06/30/AjaxHistoryAHowToPart1.aspx">Part
1</a>. In <a href="http://www.myfriedmind.com/techBlog/2009/07/01/AjaxHistoryAHowToPart2ABasicExample.aspx">Part
2</a> I provide (very) basic example of storing/retrieving Ajax changes. However in
the real world we do not live with simple pages. Most of what we want to reconstruct
are complex systems. This post will attempt to give a real-life example of such a
functionality.
</p>
        <p>
Many people use mapping pages as an example of how to do Ajax history functionality.
That is very nice because, especially for retrieving the pages, because the world
generally changes very little geographically. Longitude and Latitude have been fairly
constant since the early explorers. GPS does not change from year to year. So it is
the perfect example of how you can use a small portion of data (GPS coords for example)
to return a large complex data (a map). This is similar to the Memento pattern (take
a look at <a href="http://www.myfriedmind.com/techBlog/2009/05/20/AjaxHistoryAndTheMementoPattern.aspx">http://www.myfriedmind.com/techBlog/2009/05/20/AjaxHistoryAndTheMementoPattern.aspx</a> for
more on my thoughts on that). 
</p>
        <p>
Using a Memento pattern is critical because if you were to try to store all that complex
data in the Ajax history it would quickly fall to pieces.
</p>
        <p>
So, rule #1 - do not store complex data, store simple data that can be used to reconstruct
complex data
</p>
        <p>
While racking my brain for what to use as a non-map example, I came across a post
by Senthilkumar Moorthy on forums.asp.net in which he lays out an interaction using
Ajax that I thought would be a useful example since it uses multiple history points 
</p>
        <h3>The page layout
</h3>
        <p>
For simplicity sake I am keeping their names fairly generic and not adding a lot of
extra (fun) code...
</p>
        <ul>
          <li>
There are two UpdatePanels (upPanel1 and upPanel2). 
</li>
          <li>
upPanel1 contains a TextBox (textBox1), a Button (button1) and a DropDownList (ddl1) 
</li>
          <li>
when the user enters in phrase in textBox1 and clicks button1, ddl1 is populated with
subchoices 
</li>
          <li>
when the user clicks on ddl1 to select a choice, upPanel2 displays the details of
the selected item in a handful of labels</li>
        </ul>
        <p>
It should be noted that I am using the Adventure Works (light) database as my source
of data. 
</p>
        <ol>
          <li>
I will use textbox1 to search through ProductDescription and return a list of possible
matching items into ddl1. 
</li>
          <li>
Selecting an item from ddl1 will then display information about that particular item
in the details pane.</li>
        </ol>
        <p>
I have also included a class in the page called ProductInformation.
</p>
        <font size="2">
          <p>
          </p>
        </font>
        <font color="#0000ff" size="2">public</font>
        <font size="2">
        </font>
        <font color="#0000ff" size="2">class</font>
        <font size="2">
        </font>
        <font color="#2b91af" size="2">ProductInformation<br /></font>
        <font size="2">{<br />
      </font>
        <font color="#0000ff" size="2">public</font>
        <font size="2">
        </font>
        <font color="#0000ff" size="2">int</font>
        <font size="2"> ProductId
{ </font>
        <font color="#0000ff" size="2">get</font>
        <font size="2">; </font>
        <font color="#0000ff" size="2">set</font>
        <font size="2">;
}<br />
      </font>
        <font color="#0000ff" size="2">public</font>
        <font size="2">
        </font>
        <font color="#0000ff" size="2">string</font>
        <font size="2"> Name
{ </font>
        <font color="#0000ff" size="2">get</font>
        <font size="2">; </font>
        <font color="#0000ff" size="2">set</font>
        <font size="2">;
}<br />
      </font>
        <font color="#0000ff" size="2">public</font>
        <font size="2">
        </font>
        <font color="#0000ff" size="2">string</font>
        <font size="2"> Model
{ </font>
        <font color="#0000ff" size="2">get</font>
        <font size="2">; </font>
        <font color="#0000ff" size="2">set</font>
        <font size="2">;
}<br />
      </font>
        <font color="#0000ff" size="2">public</font>
        <font size="2">
        </font>
        <font color="#0000ff" size="2">string</font>
        <font size="2"> Description
{ </font>
        <font color="#0000ff" size="2">get</font>
        <font size="2">; </font>
        <font color="#0000ff" size="2">set</font>
        <font size="2">;
}<br />
      </font>
        <font color="#0000ff" size="2">public</font>
        <font size="2">
        </font>
        <font color="#2b91af" size="2">DateTime</font>
        <font size="2"> LastModified
{ </font>
        <font color="#0000ff" size="2">get</font>
        <font size="2">; </font>
        <font color="#0000ff" size="2">set</font>
        <font size="2">;
}<br />
}
</font>
        <h3>The history point events
</h3>
        <p>
The first thing to consider is where we want to put our history points. Ie, where
do we want, if the user clicks 'Back' to roll them back to. Also, what do we want,
if they post the URI, to display. It seems to me that there are clearly two logical
places and these all take place when events occur (which is a good way to start)
</p>
        <ol>
          <li>
when the user clicks button1 to populate ddl1 
</li>
          <li>
when the user selects an item from ddl1 and the detail is displayed</li>
        </ol>
        <p>
First off, note that we are storing three connected, but different points of data,
as opposed to the single point in the simple example of Part 2. In addition we are
having to store the Page Title (more on that later) because of an apparent issue with
the way that .net handles that. 
</p>
        <h3>The caveats
</h3>
        <p>
The biggest issue here is that data changes. Here are a few possibilities
</p>
        <ol>
          <li>
the entry of the textbox1 is no longer valid and returns no matching items 
</li>
          <li>
the selected item of ddl1 is no longer valid and returns no matching product 
</li>
          <li>
the details in upPanel2 have changed since the last update</li>
        </ol>
        <p>
Again, if this were simply mapping, #1 and #2 (changes in basic data) would not be
an issue. And since most people want the most up-to-date maps, #3 does not matter.
However, we are going, for the sake of study, assume that we care about all 3 of these
potential issues. This means we are going to have to handle that in a graceful way
when we unpack it to recreate the data.
</p>
        <p>
I have the sample code included below for you to download and I am using the AdventureWorksLT
for my data. You can snag it from CodePlex at <a href="http://www.codeplex.com/MSFTDBProdSamples/Release/ProjectReleases.aspx?ReleaseId=4004">http://www.codeplex.com/MSFTDBProdSamples/Release/ProjectReleases.aspx?ReleaseId=4004</a> .
The code itself is fairly rough in patches since I really wanted to hit the main points
about Ajax History but let me know if I need to clarify any section of it just so
you can understand what I am attempting to show.
</p>
        <h3>Creating the basic methods to create the page display
</h3>
        <p>
My methods for populating the DDL are as follows:
</p>
        <p>
    private void PopulateDDL(string text)<br />
    {<br />
        ddl1.Enabled = true;<br />
        StringDictionary _results = GetMatchingDescriptions(text);<br />
        if (_results != null)<br />
        {<br />
            ddl1.DataSource
= _results;<br />
            ddl1.DataTextField
= "Value";<br />
            ddl1.DataValueField
= "Key";<br />
            ddl1.DataBind();<br />
        }<br />
    }<br />
    private void PrefixDDL(string text, string value)<br />
    {<br />
        ddl1.Items.Insert(0, new ListItem(text,
value));<br />
        if (ddl1.SelectedIndex != -1)<br />
        {<br />
            ddl1.SelectedItem.Selected
= false;<br />
        }<br />
        ddl1.Items[0].Selected = true;<br />
    }
</p>
        <p>
My method for the Display Info (upPanel2) are as follows:
</p>
        <p>
    private void DisplayInfo(string selectedValue, DateTime requestedOn)<br />
    {<br />
        if (String.IsNullOrEmpty(selectedValue))<br />
        {<br />
            DisplayError("That
selection is no longer valid. Please retry");<br />
        }<br />
        else<br />
        {<br />
            int _productId;<br />
            if (Int32.TryParse(selectedValue,
out _productId))<br />
            {<br />
               
ProductInformation _product = GetProduct(_productId);<br />
               
if (_product == null)<br />
               
{<br />
                   
DisplayError("That selection could not be found. Please retry");<br />
               
}<br />
               
else<br />
               
{<br />
                   
lblLastModified.Text = _product.LastModified.ToString("F");<br />
                   
lblName.Text = Server.HtmlEncode(_product.Name);<br />
                   
lblModel.Text = Server.HtmlEncode(_product.Model);<br />
                   
lblDescription.Text = Server.HtmlEncode(_product.Description);<br />
               
// what if the data is old? notify the user<br />
                   
if (requestedOn &lt; _product.LastModified)<br />
                   
{<br />
                       
lblRequestedOn.Text = String.Format("This item has been modifed since request at {0}",
requestedOn.ToString("F"));<br />
                   
}<br />
                   
else<br />
                   
{<br />
                       
lblRequestedOn.Text = requestedOn.ToString("F");<br />
                   
}<br />
               
}<br />
            }<br />
            else<br />
            {<br />
               
DisplayError("That was an invalid selection");<br />
            }<br />
        }<br />
    }<br />
    private void ResetDisplayInfo()<br />
    {<br />
        lblRequestedOn.Text = "";<br />
        lblLastModified.Text = "";<br />
        lblName.Text = "";<br />
        lblModel.Text = "";<br />
        lblDescription.Text = "";<br />
    }<br />
    private void DisplayError(string errorText)<br />
    {<br />
        ResetDisplayInfo();<br />
        lblName.Text = errorText;<br />
    }
</p>
        <p>
I will call these methods not merely when the page is initially created but also when
it is REcreated during the ScriptManager's Navigate command.
</p>
        <h3>Creating the HistoryPoint methods/event handler
</h3>
        <p>
Apart from the modifications that are made similar to what was done on Part 2, the
main changes deal with the methods to store the History Points and to recreate the
page after the History Points have been reloaded. In other words what happens when
a History Point is set and what happens when a History Point is retrieved. Because
we do not want to store the ENTIRE page in the browser URI the fundamental question
is "what can I get away with?" This is a good time to practice your YAGNI (You ain't
gonna need it) to eliminate all but the most essential and simplest pieces of information.
In this case I have three pieces that can not be reduced any more
</p>
        <ol>
          <li>
the text in the textbox 
</li>
          <li>
the selected value of the dropdown list 
</li>
          <li>
the DateTime that the page was loaded (to see if the data has been changed) 
</li>
          <li>
(bonus) In addition, due to a 'feature' of Ajax History in .net 3.5, I am also including
the Page Title. I will discuss more about this later, but just know that it is included.</li>
        </ol>
        <p>
My method to store the History Point looks like this:
</p>
        <p>
    protected void StoreHistoryPoints(string textBoxText, string ddlValue, 
<br />
        DateTime requestedOn, string pageTitle)<br />
    {<br />
        ScriptManager _mySM = ScriptManager.GetCurrent(this.Page);<br />
        NameValueCollection _historyPointEntries
= new NameValueCollection();<br />
        _historyPointEntries.Add("whatTextBoxContains",
textBoxText);<br />
        _historyPointEntries.Add("whatWasSelectedInDDL",
ddlValue);<br />
        _historyPointEntries.Add("requestedOn",
requestedOn.Ticks.ToString()); // ticks are shorter in length<br />
        _historyPointEntries.Add("pageTitle", String.Format("AV
- {0}", pageTitle));<br />
        _mySM.AddHistoryPoint(_historyPointEntries,
String.Format("AV - {0}", pageTitle));<br />
    }
</p>
        <p>
It is very straightforward. I create a NameValueCollection to hold my minimal data
and then call the AddHistoryPoint.
</p>
        <p>
Before I continue I should mention that there are three overloaded methods for AddHistoryPoint
</p>
        <ul>
          <li>
ScriptManager.AddHistoryPoint(string, string) 
</li>
          <li>
ScriptManager.AddHistoryPoint(string, string, string) 
</li>
          <li>
ScriptManager.AddHistoryPoint(NameValueCollection, string)</li>
        </ul>
        <p>
The second two have an additional string parameter which is used to set the Page Title
when the History Point is stored. In this example I use it to set the Page Title to
whatever bike model that they are looking at. Thus if they save it in their favorites
it gives a user friendly name.
</p>
        <p>
HOWEVER!!! While this works going forward that information is lost when the Navigate
method is called and the HistoryPoint information is unpackaged. Ie - going forward
the ScriptManager changes the Page Title, but when the page is loaded using the "Back"
button or from a manually typed URI, it does not set the Page Title, nor is it accessible
through the HistoryEventArgs. As a workaround I have included the Page Title as one
of the KeyValue pairs in my history point so that I can recreate along with the rest
of the page. Of course, since this is an issue I could simply have set the Page Title
manually (for example in the portion of the code that determines the bike to display)
but I wanted to show you this overload.
</p>
        <p>
Also note that I could as easily have done this in my method:
</p>
        <p>
    protected void StoreHistoryPoints(string textBoxText, string ddlValue, 
<br />
        DateTime requestedOn, string pageTitle)<br />
    {<br />
        ScriptManager _mySM = ScriptManager.GetCurrent(this.Page);<br />
        _mySM.AddHistoryPoint("whatTextBoxContains",
textBoxText);<br />
        _mySM.AddHistoryPoint("whatWasSelectedInDDL",
ddlValue);<br />
        _mySM.AddHistoryPoint("requestedOn", requestedOn.Ticks.ToString());
// ticks are shorter in length<br />
        _mySM.AddHistoryPoint("pageTitle", String.Format("AV
- {0}", pageTitle));<br />
    }
</p>
        <p>
There is actually no discernable difference except for the Page Title being handled
by the Script Manager going forward. The NameValueCollection that the HistoryEventArgs
of the ScriptManager's Navigate method returns are the same in both methods. The code
that I display below for the Navigate event handles them exactly the same because
both return the same NameValueCollection.
</p>
        <p>
          <font color="#ff0000">Quick note</font> also that all these entries must be string
values (they are stored in the URI after all). For this reason I have changed the
DateTime to use ticks instead of writing it out, but you could have easily have chosen
a format which would return a simpler string. The key is to approach this with a minimalist
attitude. Not being too obsessive, but the shorting the string, the shorter the URI,
the better for the system.
</p>
        <h3>Recreating the page
</h3>
        <p>
Now I have the process in place for the storing of History Points. I can call this
method as my final command from both the button1_Click event handler and the ddl1_SelectedIndexChanged
event handler and it will store the information I pass it into the history. The Page
does not need to know what this data represents. It is the Caretaker (see Ajax and
Memento). All it knows is that it needs to store this information and return it when
requested.
</p>
        <p>
The second portion is the unpackaging when the History Points have been returned.
This is handled through the ScriptManager's Navigate event. One quick thing to note
- this event is called when the "Back" or "Refresh" commands are given to the browser,
but it also is called when the page is loaded with the specific History Point URI,
for example from a "Bookmark" or from a link.
</p>
        <p>
My event handler looks like this:
</p>
        <p>
   protected void sm1_Navigate(object sender, HistoryEventArgs e)<br />
    {<br />
        long _requestedOnAsTicks;<br />
        bool _hasHistory = long.TryParse(e.State["requestedOn"],
out _requestedOnAsTicks);<br />
        if (_hasHistory)<br />
        {<br />
            DateTime _requestedOn
= new DateTime(_requestedOnAsTicks);
</p>
        <p>
            string _textStored
= e.State["whatTextBoxContains"];<br />
            if (!String.IsNullOrEmpty(_textStored))<br />
            {<br />
               
// restore entries on TextBox and DDL<br />
               
textbox1.Text = _textStored;<br />
               
PopulateDDL(_textStored);<br />
            }<br />
            string _ddlValueStored
= e.State["whatWasSelectedInDDL"];<br />
            if (!String.IsNullOrEmpty(_ddlValueStored))<br />
            {<br />
               
ListItem _matchingItem = ddl1.Items.FindByValue(_ddlValueStored);<br />
               
if (_matchingItem != null)<br />
               
{<br />
                
  // we have victory, display the item...<br />
                   
_matchingItem.Selected = true;<br />
                   
DisplayInfo(_ddlValueStored, _requestedOn);<br />
               
}<br />
               
else<br />
               
{<br />
                   
// something is wrong, the item no longer shows. Display error...<br />
                   
ListItem _errorItem = new ListItem(_ddlValueStored, "");<br />
                   
DisplayInfo("", _requestedOn);<br />
               
}<br />
            }<br />
            else<br />
            {<br />
               
// since no DDL value was selected, add prompt at beginning of DDL<br />
               
PrefixDDL("Select One", "");<br />
            }
</p>
        <p>
            // this is a required
hack because even though page title is specified in the AjaxHistory, it 
<br />
            // does not work
when you navigate backwards..<br />
            string _pageTitle
= e.State["pageTitle"];<br />
            Page.Title = _pageTitle;<br />
        }<br />
        else<br />
        {<br />
            // if there is
no DateTime stored than this is the original (ie no history) -&gt; reset form<br />
            textbox1.Text =
"";<br />
            ddl1.Items.Clear();<br />
            ResetDisplayInfo();<br />
            Page.Title = "AV";<br />
        }<br />
    }
</p>
        <p>
The Navigate event uses the HistoryEventArgs. This really only has one thing in there
- the State, which is the NameValueCollection that you passed the ScriptManager during
the AddHistoryPoints calls.
</p>
        <p>
The first thing I do is see if there is anything in there. Since I am wanted to get
the date and the TryParse is a convenient way for me to verify that it is a valid
long, I check it there. If there is no history than this is a non-modified Ajax Page
(probably the very beginning) and I simply reset everything.
</p>
        <p>
Once I know there is a history I have to go through the process of recreating the
page. I extract the appropriate information and repopulate the Textbox, the DropDownList
(if appropriate) and the Display (if appropriate). By doing this I am creating a complex
page from simplistic data. 
</p>
        <p>
Because my data may have changed (say the Description has been updated) I have also
included a notification to the user if this takes place in the DisplayInfo method.
However, I no longer have access to the original data. That data is lost to me because
all I am passing are the minimal pieces to recreate the page. What is displayed is
the CURRENT information on that particular product.
</p>
        <p>
Also, note the setting of the Page.Title. Remember that even though I did pass that
as a parameter during my AddHistoryPoint method call, it is no longer available to
me during the Navigate event. If you want to use a unique Page Title when an Ajax
modification takes place, make sure to pass the Page Title as its own KeyValue pair
and then unpack and recreate it.
</p>
        <h3>Final Notes
</h3>
        <p>
If you have stuck in this long, congrats!!! I know this may still seem murky, probably
more due to my explanation than to anything else, but there are a few more things
I want to touch on. I will actually them in my (potentially) last blog on this - part
4 - wrap up.
</p>
        <h3>Zipped Example
</h3>
        <p>
          <a href="http://www.myfriedmind.com/techBlog/content/binary/AjaxExamples.zip">AjaxExamples.zip
(1.37 MB)</a>
        </p>
        <img width="0" height="0" src="http://www.myfriedmind.com/techBlog/aggbug.ashx?id=823a3232-19ab-4ee1-ac9b-fbdf605e557b" />
      </body>
      <title>Ajax History - a how to - Part 3 - complex example (c#)</title>
      <guid isPermaLink="false">http://www.myfriedmind.com/techBlog/PermaLink,guid,823a3232-19ab-4ee1-ac9b-fbdf605e557b.aspx</guid>
      <link>http://www.myfriedmind.com/techBlog/2009/07/09/AjaxHistoryAHowToPart3ComplexExampleC.aspx</link>
      <pubDate>Thu, 09 Jul 2009 16:05:14 GMT</pubDate>
      <description>&lt;p&gt;
Part 1 - &lt;a href="http://www.myfriedmind.com/techBlog/2009/06/30/AjaxHistoryAHowToPart1.aspx"&gt;&lt;font color=#5c80b1&gt;Introduction&lt;/font&gt;&lt;/a&gt;
&lt;br&gt;
Part 2 - &lt;a href="http://www.myfriedmind.com/techBlog/2009/07/01/AjaxHistoryAHowToPart2ABasicExample.aspx"&gt;&lt;font color=#5c80b1&gt;Basic
Example&lt;/font&gt;&lt;/a&gt;
&lt;br&gt;
Part 3 - &lt;a href="http://www.myfriedmind.com/techBlog/2009/07/09/AjaxHistoryAHowToPart3ComplexExampleC.aspx"&gt;&lt;font color=#5c80b1&gt;Complex
Example&lt;/font&gt;&lt;/a&gt;
&lt;br&gt;
Part 4 - &lt;a href="http://www.myfriedmind.com/techBlog/2009/07/09/AjaxHistoryAHowToPart4FinalNotes.aspx"&gt;&lt;font color=#5c80b1&gt;Final
Notes&lt;/font&gt;&lt;/a&gt;
&lt;br&gt;
Bonus - &lt;a href="http://www.myfriedmind.com/techBlog/2009/05/20/AjaxHistoryAndTheMementoPattern.aspx"&gt;&lt;font color=#5c80b1&gt;Ajax
History and the Memento Pattern&lt;/font&gt;&lt;/a&gt;
&lt;br&gt;
Extra Bonus - &lt;a href="http://www.myfriedmind.com/techBlog/2009/09/21/Opera9x10xFailingOnAjaxHistoryAndTheHackToFixIt.aspx"&gt;&lt;font color=#5c80b1&gt;Issues
with Opera&lt;/font&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
This is the third in a series looking at using Ajax History in .net 3.5. I would recommend
you look at &lt;a href="http://www.myfriedmind.com/techBlog/2009/06/30/AjaxHistoryAHowToPart1.aspx"&gt;Part
1&lt;/a&gt; and &lt;a href="http://www.myfriedmind.com/techBlog/2009/07/01/AjaxHistoryAHowToPart2ABasicExample.aspx"&gt;Part
2&lt;/a&gt; if you have not&amp;nbsp;already done so.
&lt;/p&gt;
&lt;p&gt;
Ajax out of the box is wonderful in that it reduces page reloads, but it is not wonderful
in that it does not treat each Ajax call as a unique URI. As a result all Ajax modified
changes are lost when the Back or refresh button are clicked. In addition there is
no way to store the URL of the page in such a way that it will display the results
of Ajax changes. I explain much of this in &lt;a href="http://www.myfriedmind.com/techBlog/2009/06/30/AjaxHistoryAHowToPart1.aspx"&gt;Part
1&lt;/a&gt;. In &lt;a href="http://www.myfriedmind.com/techBlog/2009/07/01/AjaxHistoryAHowToPart2ABasicExample.aspx"&gt;Part
2&lt;/a&gt; I provide (very) basic example of storing/retrieving Ajax changes. However in
the real world we do not live with simple pages. Most of what we want to reconstruct
are complex systems. This post will attempt to give a real-life example of such a
functionality.
&lt;/p&gt;
&lt;p&gt;
Many people use mapping pages as an example of how to do Ajax history functionality.
That is very nice because, especially for retrieving the pages, because the world
generally changes very little geographically. Longitude and Latitude have been fairly
constant since the early explorers. GPS does not change from year to year. So it is
the perfect example of how you can use a small portion of data (GPS coords for example)
to return a large complex data (a map). This is similar to the Memento pattern (take
a look at &lt;a href="http://www.myfriedmind.com/techBlog/2009/05/20/AjaxHistoryAndTheMementoPattern.aspx"&gt;http://www.myfriedmind.com/techBlog/2009/05/20/AjaxHistoryAndTheMementoPattern.aspx&lt;/a&gt;&amp;nbsp;for
more on my thoughts on that). 
&lt;/p&gt;
&lt;p&gt;
Using a Memento pattern is critical because if you were to try to store all that complex
data in the Ajax history it would quickly fall to pieces.
&lt;/p&gt;
&lt;p&gt;
So, rule #1 - do not store complex data, store simple data that can be used to reconstruct
complex data
&lt;/p&gt;
&lt;p&gt;
While racking my brain for what to use as a non-map example, I came across a post
by Senthilkumar Moorthy on forums.asp.net in which he lays out an interaction using
Ajax that I thought would be a useful example since it uses multiple history points 
&lt;/p&gt;
&lt;h3&gt;The page layout
&lt;/h3&gt;
&lt;p&gt;
For simplicity sake I am keeping their names fairly generic and not adding a lot of
extra (fun) code...
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
There are two UpdatePanels (upPanel1 and upPanel2). 
&lt;li&gt;
upPanel1 contains a TextBox (textBox1), a Button (button1) and a DropDownList (ddl1) 
&lt;li&gt;
when the user enters in phrase in textBox1 and clicks button1, ddl1 is populated with
subchoices 
&lt;li&gt;
when the user clicks on ddl1 to select a choice, upPanel2 displays the details of
the selected item in a handful of labels&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
It should be noted that I am using the Adventure Works (light) database as my source
of data. 
&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
I will use textbox1 to search through ProductDescription and return a list of possible
matching items into ddl1. 
&lt;li&gt;
Selecting an item from ddl1 will then display information about that particular item
in the details pane.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;
I have also included a class in the page called ProductInformation.
&lt;/p&gt;
&lt;font size=2&gt; 
&lt;p&gt;
&lt;/font&gt;&lt;font color=#0000ff size=2&gt;public&lt;/font&gt;&lt;font size=2&gt; &lt;/font&gt;&lt;font color=#0000ff size=2&gt;class&lt;/font&gt;&lt;font size=2&gt; &lt;/font&gt;&lt;font color=#2b91af size=2&gt;ProductInformation&lt;br&gt;
&lt;/font&gt;&lt;font size=2&gt;{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color=#0000ff size=2&gt;public&lt;/font&gt;&lt;font size=2&gt; &lt;/font&gt;&lt;font color=#0000ff size=2&gt;int&lt;/font&gt;&lt;font size=2&gt; ProductId
{ &lt;/font&gt;&lt;font color=#0000ff size=2&gt;get&lt;/font&gt;&lt;font size=2&gt;; &lt;/font&gt;&lt;font color=#0000ff size=2&gt;set&lt;/font&gt;&lt;font size=2&gt;;
}&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color=#0000ff size=2&gt;public&lt;/font&gt;&lt;font size=2&gt; &lt;/font&gt;&lt;font color=#0000ff size=2&gt;string&lt;/font&gt;&lt;font size=2&gt; Name
{ &lt;/font&gt;&lt;font color=#0000ff size=2&gt;get&lt;/font&gt;&lt;font size=2&gt;; &lt;/font&gt;&lt;font color=#0000ff size=2&gt;set&lt;/font&gt;&lt;font size=2&gt;;
}&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color=#0000ff size=2&gt;public&lt;/font&gt;&lt;font size=2&gt; &lt;/font&gt;&lt;font color=#0000ff size=2&gt;string&lt;/font&gt;&lt;font size=2&gt; Model
{ &lt;/font&gt;&lt;font color=#0000ff size=2&gt;get&lt;/font&gt;&lt;font size=2&gt;; &lt;/font&gt;&lt;font color=#0000ff size=2&gt;set&lt;/font&gt;&lt;font size=2&gt;;
}&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color=#0000ff size=2&gt;public&lt;/font&gt;&lt;font size=2&gt; &lt;/font&gt;&lt;font color=#0000ff size=2&gt;string&lt;/font&gt;&lt;font size=2&gt; Description
{ &lt;/font&gt;&lt;font color=#0000ff size=2&gt;get&lt;/font&gt;&lt;font size=2&gt;; &lt;/font&gt;&lt;font color=#0000ff size=2&gt;set&lt;/font&gt;&lt;font size=2&gt;;
}&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color=#0000ff size=2&gt;public&lt;/font&gt;&lt;font size=2&gt; &lt;/font&gt;&lt;font color=#2b91af size=2&gt;DateTime&lt;/font&gt;&lt;font size=2&gt; LastModified
{ &lt;/font&gt;&lt;font color=#0000ff size=2&gt;get&lt;/font&gt;&lt;font size=2&gt;; &lt;/font&gt;&lt;font color=#0000ff size=2&gt;set&lt;/font&gt;&lt;font size=2&gt;;
}&lt;br&gt;
}&gt;
&lt;/font&gt; 
&lt;h3&gt;The history point events
&lt;/h3&gt;
&lt;p&gt;
The first thing to consider is where we want to put our&amp;nbsp;history points. Ie, where
do we want, if the user clicks 'Back' to roll them back to. Also, what do we want,
if they post the URI, to display. It seems to me that there are clearly two logical
places and these all take place when events occur (which is a good way to start)
&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
when the user clicks button1 to populate ddl1 
&lt;li&gt;
when the user selects an item from ddl1 and the detail is displayed&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;
First off, note that we are storing three connected, but different points of data,
as opposed to the single point in the simple example of Part 2. In addition we are
having to store the Page Title (more on that later) because of an apparent issue with
the way that .net handles that. 
&lt;/p&gt;
&lt;h3&gt;The caveats
&lt;/h3&gt;
&lt;p&gt;
The biggest issue here is that data changes. Here are a few possibilities
&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
the entry of the textbox1 is no longer valid and returns no matching items 
&lt;li&gt;
the selected item of ddl1 is no longer valid and returns no matching product 
&lt;li&gt;
the details in upPanel2 have changed since the last update&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;
Again, if this were simply mapping, #1 and #2 (changes in basic data) would not be
an issue. And since most people want the most up-to-date maps, #3 does not matter.
However, we are going, for the sake of study, assume that we care about all 3 of these
potential issues. This means we are going to have to handle that in a graceful way
when we unpack it to recreate the data.
&lt;/p&gt;
&lt;p&gt;
I have the sample code included below for you to download and I am using the AdventureWorksLT
for my data. You can snag it&amp;nbsp;from CodePlex at &lt;a href="http://www.codeplex.com/MSFTDBProdSamples/Release/ProjectReleases.aspx?ReleaseId=4004"&gt;http://www.codeplex.com/MSFTDBProdSamples/Release/ProjectReleases.aspx?ReleaseId=4004&lt;/a&gt;&amp;nbsp;.
The code itself is fairly rough in patches since I really wanted to hit the main points
about Ajax History but let me know if I need to clarify any section of it just so
you can understand what I am attempting to show.
&lt;/p&gt;
&lt;h3&gt;Creating the basic methods to create the page display
&lt;/h3&gt;
&lt;p&gt;
My methods for populating the DDL are as follows:
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; private void PopulateDDL(string text)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ddl1.Enabled = true;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; StringDictionary _results = GetMatchingDescriptions(text);&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (_results != null)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ddl1.DataSource
= _results;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ddl1.DataTextField
= "Value";&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ddl1.DataValueField
= "Key";&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ddl1.DataBind();&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; private void PrefixDDL(string text, string value)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ddl1.Items.Insert(0, new ListItem(text,
value));&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (ddl1.SelectedIndex != -1)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ddl1.SelectedItem.Selected
= false;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ddl1.Items[0].Selected = true;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&lt;/p&gt;
&lt;p&gt;
My method for the Display Info (upPanel2) are as follows:
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; private void DisplayInfo(string selectedValue, DateTime requestedOn)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (String.IsNullOrEmpty(selectedValue))&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DisplayError("That
selection is no longer valid. Please retry");&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; else&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; int _productId;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (Int32.TryParse(selectedValue,
out _productId))&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
ProductInformation _product = GetProduct(_productId);&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
if (_product == null)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
DisplayError("That selection could not be found. Please retry");&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
}&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
else&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
lblLastModified.Text = _product.LastModified.ToString("F");&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
lblName.Text = Server.HtmlEncode(_product.Name);&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
lblModel.Text = Server.HtmlEncode(_product.Model);&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
lblDescription.Text = Server.HtmlEncode(_product.Description);&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
// what if the data is old? notify the user&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
if (requestedOn &amp;lt; _product.LastModified)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
lblRequestedOn.Text = String.Format("This item has been modifed since request at {0}",
requestedOn.ToString("F"));&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
}&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
else&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
lblRequestedOn.Text = requestedOn.ToString("F");&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
}&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
}&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; else&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
DisplayError("That was an invalid selection");&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; private void ResetDisplayInfo()&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; lblRequestedOn.Text = "";&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; lblLastModified.Text = "";&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; lblName.Text = "";&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; lblModel.Text = "";&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; lblDescription.Text = "";&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; private void DisplayError(string errorText)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ResetDisplayInfo();&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; lblName.Text = errorText;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&lt;/p&gt;
&lt;p&gt;
I will call these methods not merely when the page is initially created but also when
it is REcreated during the ScriptManager's Navigate command.
&lt;/p&gt;
&lt;h3&gt;Creating the HistoryPoint methods/event handler
&lt;/h3&gt;
&lt;p&gt;
Apart from the modifications that are made similar to what was done on Part 2, the
main changes deal with the methods to store the History Points and to recreate the
page after the History Points have been reloaded. In other words what happens when
a History Point is set and what happens when a History Point is retrieved. Because
we do not want to store the ENTIRE page in the browser URI the fundamental question
is "what can I get away with?" This is a good time to practice your YAGNI (You ain't
gonna need it) to eliminate all but the most essential and simplest pieces of information.
In this case I have three pieces that can not be reduced any more
&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
the text in the textbox 
&lt;li&gt;
the selected value of the dropdown list 
&lt;li&gt;
the DateTime that the page was loaded (to see if the data has been changed) 
&lt;li&gt;
(bonus) In addition, due to a 'feature' of Ajax History in .net 3.5, I am also including
the Page Title. I will discuss more about this later, but just know that it is included.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;
My method to store the History Point looks like this:
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; protected void StoreHistoryPoints(string textBoxText, string ddlValue, 
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DateTime requestedOn, string pageTitle)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ScriptManager _mySM = ScriptManager.GetCurrent(this.Page);&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; NameValueCollection _historyPointEntries
= new NameValueCollection();&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _historyPointEntries.Add("whatTextBoxContains",
textBoxText);&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _historyPointEntries.Add("whatWasSelectedInDDL",
ddlValue);&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _historyPointEntries.Add("requestedOn",
requestedOn.Ticks.ToString()); // ticks are shorter in length&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _historyPointEntries.Add("pageTitle", String.Format("AV
- {0}", pageTitle));&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _mySM.AddHistoryPoint(_historyPointEntries,
String.Format("AV - {0}", pageTitle));&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&lt;/p&gt;
&lt;p&gt;
It is very straightforward. I create a NameValueCollection to hold my minimal data
and then call the AddHistoryPoint.
&lt;/p&gt;
&lt;p&gt;
Before I continue I should mention that there are three overloaded methods for AddHistoryPoint
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
ScriptManager.AddHistoryPoint(string, string) 
&lt;li&gt;
ScriptManager.AddHistoryPoint(string, string, string) 
&lt;li&gt;
ScriptManager.AddHistoryPoint(NameValueCollection, string)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
The second two have an additional string parameter which is used to set the Page Title
when the History Point is stored. In this example I use it to set the Page Title to
whatever bike model that they are looking at. Thus if they save it in their favorites
it gives a user friendly name.
&lt;/p&gt;
&lt;p&gt;
HOWEVER!!! While this works going forward that information is lost when the Navigate
method is called and the HistoryPoint information is unpackaged. Ie - going forward
the ScriptManager changes the Page Title, but when the page is loaded using the "Back"
button or from a manually typed URI, it does not set the Page Title, nor is it accessible
through the HistoryEventArgs. As a workaround I have included the Page Title as one
of the KeyValue pairs in my history point so that I can recreate along with the rest
of the page. Of course, since this is an issue I could simply have set the Page Title
manually (for example in the portion of the code that determines the bike to display)
but I wanted to show you this overload.
&lt;/p&gt;
&lt;p&gt;
Also note that I could as easily have done this in my method:
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; protected void StoreHistoryPoints(string textBoxText, string ddlValue, 
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DateTime requestedOn, string pageTitle)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ScriptManager _mySM = ScriptManager.GetCurrent(this.Page);&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _mySM.AddHistoryPoint("whatTextBoxContains",
textBoxText);&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _mySM.AddHistoryPoint("whatWasSelectedInDDL",
ddlValue);&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _mySM.AddHistoryPoint("requestedOn", requestedOn.Ticks.ToString());
// ticks are shorter in length&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _mySM.AddHistoryPoint("pageTitle", String.Format("AV
- {0}", pageTitle));&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&lt;/p&gt;
&lt;p&gt;
There is actually no discernable difference except for the Page Title being handled
by the Script Manager going forward. The NameValueCollection that the HistoryEventArgs
of the ScriptManager's Navigate method returns are the same in both methods. The code
that I display below for the Navigate event handles them exactly the same because
both return the same NameValueCollection.
&lt;/p&gt;
&lt;p&gt;
&lt;font color=#ff0000&gt;Quick note&lt;/font&gt; also that all these entries must be string values
(they are stored in the URI after all). For this reason I have changed the DateTime
to use ticks instead of writing it out, but you could have easily have chosen a format
which would return a simpler string. The key is to approach this with a minimalist
attitude. Not being too obsessive, but the shorting the string, the shorter the URI,
the better for the system.
&lt;/p&gt;
&lt;h3&gt;Recreating the page
&lt;/h3&gt;
&lt;p&gt;
Now I have the process in place for the storing of History Points. I can call this
method as my final command from both the button1_Click event handler and the ddl1_SelectedIndexChanged
event handler and it will store the information I pass it into the history. The Page
does not need to know what this data represents. It is the Caretaker (see Ajax and
Memento). All it knows is that it needs to store this information and return it when
requested.
&lt;/p&gt;
&lt;p&gt;
The second portion is the unpackaging when the History Points have been returned.
This is handled through the ScriptManager's Navigate event. One quick thing to note
- this event is called when the "Back" or "Refresh" commands are given to the browser,
but it also is called when the page is loaded with the specific History Point URI,
for example from a "Bookmark" or from a link.
&lt;/p&gt;
&lt;p&gt;
My event handler looks like this:
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;&amp;nbsp; protected void sm1_Navigate(object sender, HistoryEventArgs e)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; long _requestedOnAsTicks;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; bool _hasHistory = long.TryParse(e.State["requestedOn"],
out _requestedOnAsTicks);&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (_hasHistory)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DateTime _requestedOn
= new DateTime(_requestedOnAsTicks);
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; string _textStored
= e.State["whatTextBoxContains"];&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (!String.IsNullOrEmpty(_textStored))&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
// restore entries on TextBox and DDL&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
textbox1.Text = _textStored;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
PopulateDDL(_textStored);&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; string _ddlValueStored
= e.State["whatWasSelectedInDDL"];&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (!String.IsNullOrEmpty(_ddlValueStored))&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
ListItem _matchingItem = ddl1.Items.FindByValue(_ddlValueStored);&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
if (_matchingItem != null)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp; // we have victory, display the item...&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
_matchingItem.Selected = true;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
DisplayInfo(_ddlValueStored, _requestedOn);&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
}&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
else&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
// something is wrong, the item no longer shows. Display error...&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
ListItem _errorItem = new ListItem(_ddlValueStored, "");&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
DisplayInfo("", _requestedOn);&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
}&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; else&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
// since no DDL value was selected, add prompt at beginning of DDL&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
PrefixDDL("Select One", "");&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // this is a required
hack because even though page title is specified in the AjaxHistory, it 
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // does not work
when you navigate backwards..&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; string _pageTitle
= e.State["pageTitle"];&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Page.Title = _pageTitle;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; else&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // if there is
no DateTime stored than this is the original (ie no history) -&amp;gt; reset form&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; textbox1.Text =
"";&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ddl1.Items.Clear();&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ResetDisplayInfo();&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Page.Title = "AV";&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&lt;/p&gt;
&lt;p&gt;
The Navigate event uses the HistoryEventArgs. This really only has one thing in there
- the State, which is the NameValueCollection that you passed the ScriptManager during
the AddHistoryPoints calls.
&lt;/p&gt;
&lt;p&gt;
The first thing I do is see if there is anything in there. Since I am wanted to get
the date and the TryParse is a convenient way for me to verify that it is a valid
long, I check it there. If there is no history than this is a non-modified Ajax Page
(probably the very beginning) and I simply reset everything.
&lt;/p&gt;
&lt;p&gt;
Once I know there is a history I have to go through the process of recreating the
page. I extract the appropriate information and repopulate the Textbox, the DropDownList
(if appropriate) and the Display (if appropriate). By doing this I am creating a complex
page from simplistic data. 
&lt;/p&gt;
&lt;p&gt;
Because my data may have changed (say the Description has been updated) I have also
included a notification to the user if this takes place in the DisplayInfo method.
However, I no longer have access to the original data. That data is lost to me because
all I am passing are the minimal pieces to recreate the page. What is displayed is
the CURRENT information on that particular product.
&lt;/p&gt;
&lt;p&gt;
Also, note the setting of the Page.Title. Remember that even though I did pass that
as a parameter during my AddHistoryPoint method call, it is no longer available to
me during the Navigate event. If you want to use a unique Page Title when an Ajax
modification takes place, make sure to pass the Page Title as its own KeyValue pair
and then unpack and recreate it.
&lt;/p&gt;
&lt;h3&gt;Final Notes
&lt;/h3&gt;
&lt;p&gt;
If you have stuck in this long, congrats!!! I know this may still seem murky, probably
more due to my explanation than to anything else, but there are a few more things
I want to touch on. I will actually them in my (potentially) last blog on this - part
4 - wrap up.
&lt;/p&gt;
&lt;h3&gt;Zipped Example
&lt;/h3&gt;
&lt;p&gt;
&lt;a href="http://www.myfriedmind.com/techBlog/content/binary/AjaxExamples.zip"&gt;AjaxExamples.zip
(1.37 MB)&lt;/a&gt;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.myfriedmind.com/techBlog/aggbug.ashx?id=823a3232-19ab-4ee1-ac9b-fbdf605e557b" /&gt;</description>
      <comments>http://www.myfriedmind.com/techBlog/CommentView,guid,823a3232-19ab-4ee1-ac9b-fbdf605e557b.aspx</comments>
      <category>Ajax</category>
      <category>Asp.Net</category>
      <category>c#</category>
      <category>Coding Tricks</category>
    </item>
    <item>
      <trackback:ping>http://www.myfriedmind.com/techBlog/Trackback.aspx?guid=b4b6d1b6-78ee-4163-afe9-29a9fb47a6d0</trackback:ping>
      <pingback:server>http://www.myfriedmind.com/techBlog/pingback.aspx</pingback:server>
      <pingback:target>http://www.myfriedmind.com/techBlog/PermaLink,guid,b4b6d1b6-78ee-4163-afe9-29a9fb47a6d0.aspx</pingback:target>
      <dc:creator>papabear</dc:creator>
      <wfw:comment>http://www.myfriedmind.com/techBlog/CommentView,guid,b4b6d1b6-78ee-4163-afe9-29a9fb47a6d0.aspx</wfw:comment>
      <wfw:commentRss>http://www.myfriedmind.com/techBlog/SyndicationService.asmx/GetEntryCommentsRss?guid=b4b6d1b6-78ee-4163-afe9-29a9fb47a6d0</wfw:commentRss>
      <slash:comments>3</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Part 1 - <a href="http://www.myfriedmind.com/techBlog/2009/06/30/AjaxHistoryAHowToPart1.aspx"><font color="#5c80b1">Introduction</font></a><br />
Part 2 - <a href="http://www.myfriedmind.com/techBlog/2009/07/01/AjaxHistoryAHowToPart2ABasicExample.aspx"><font color="#5c80b1">Basic
Example</font></a><br />
Part 3 - <a href="http://www.myfriedmind.com/techBlog/2009/07/09/AjaxHistoryAHowToPart3ComplexExampleC.aspx"><font color="#5c80b1">Complex
Example</font></a><br />
Part 4 - <a href="http://www.myfriedmind.com/techBlog/2009/07/09/AjaxHistoryAHowToPart4FinalNotes.aspx"><font color="#5c80b1">Final
Notes</font></a><br />
Bonus - <a href="http://www.myfriedmind.com/techBlog/2009/05/20/AjaxHistoryAndTheMementoPattern.aspx"><font color="#5c80b1">Ajax
History and the Memento Pattern</font></a><br />
Extra Bonus - <a href="http://www.myfriedmind.com/techBlog/2009/09/21/Opera9x10xFailingOnAjaxHistoryAndTheHackToFixIt.aspx"><font color="#5c80b1">Issues
with Opera</font></a></p>
        <p>
Handling Ajax history has been a critical issue since Ajax first started. With the
advent of .net 3.5 the ability to easily deal with that is rolled into the code. This
is part 2, here we will look at a simple example of handling Ajax history to give
a basic understanding of the process. If you have not read <a href="http://www.myfriedmind.com/techBlog/2009/06/30/AjaxHistoryAHowToPart1.aspx">Part
1</a>, I suggest you do that now. Part 3 will expand on handling Ajax history when
the data is more complex.<br />
For simplicity sake we are only going to look at an example of very, very basic history.
We are going to look at a page that displays changes made to the time.
</p>
        <p>
A basic assumption is that you are fairly familiar with Ajax (<a href="http://ajax.asp.net">http://ajax.asp.net</a>).
We are going to be using the ScriptManager (of course) and an UpdatePanel. 
<br />
Our basic page looks like this
</p>
        <p>
&lt;%@ Page Language="C#" AutoEventWireup="true" CodeFile="AjaxHistory.aspx.cs" Inherits="AjaxHistory"
%&gt;
</p>
        <p>
&lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "<a href="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd</a>"&gt;
</p>
        <p>
&lt;html xmlns="<a href="http://www.w3.org/1999/xhtml">http://www.w3.org/1999/xhtml</a>"&gt;<br />
&lt;head runat="server"&gt;<br />
    &lt;title&gt;&lt;/title&gt;<br />
&lt;/head&gt;<br />
&lt;body&gt;<br />
    &lt;form id="form1" runat="server"&gt;<br />
    &lt;asp:ScriptManager runat="server" ID="sm1" EnablePartialRendering="true"
/&gt;<br />
    &lt;div&gt;<br />
        &lt;asp:UpdatePanel runat="server" ID="upME"&gt;<br />
            &lt;ContentTemplate&gt;<br />
               
&lt;asp:Button runat="server" ID="uxChangeTime" 
<br />
                   
OnClick="uxChangeTime_Click" Text="-- change:" /&gt;<br />
               
&lt;asp:Label runat="server" ID="lblTime" /&gt;<br />
            &lt;/ContentTemplate&gt;<br />
            &lt;Triggers&gt;<br />
               
&lt;asp:AsyncPostBackTrigger ControlID="uxChangeTime"<br />
                    
EventName="Click" /&gt;<br />
            &lt;/Triggers&gt;<br />
        &lt;/asp:UpdatePanel&gt;<br />
    &lt;/div&gt;<br />
    &lt;/form&gt;<br />
&lt;/body&gt;<br />
&lt;/html&gt;
</p>
        <p>
The codebehind sets the label text to be the current date/time on every click:
</p>
        <p>
(c# code)<br />
protected void uxChangeTime_Click(object sender, EventArgs e)<br />
{<br />
    string _currentDateTime = DateTime.Now.ToString("F");<br />
    lblTime.Text = _currentDateTime;<br />
}
</p>
        <p>
(vb code)<br />
Protected Sub uxChangeTime_Click(ByVal sender As Object, &amp;_<br />
  ByVal e As System.EventArgs) Handles uxChangeTime.Click<br />
    Dim _currentDateTime As String = DateTime.Now.ToString("F")<br />
    lblTime.Text = _currentDateTime<br />
End Sub
</p>
        <p>
As you can see this is fairly straightforward. Clicking on the button displays the
current DateTime in the label. However, there is no history. Clicking back will not
display the last DateTime displayed but either be grayed out (if this was the first
page loaded) or take you back to the page before this one.
</p>
        <p>
To enable history is very, very simple in 3.5
</p>
        <ol>
          <li>
modify the ScriptManager, setting a property or two and registering an event (Navigate)
for the ScriptManager 
</li>
          <li>
modify the Click handler to notify the ScriptManager to record a History Point 
</li>
          <li>
handle the event called by the ScriptManager to rollback, when required, the page</li>
        </ol>
        <h3>Step 1: Modify the ScriptManager
</h3>
        <p>
The modifications are very simple - set EnableHistory equal to true and specify what
should handle the Navigate event. You can also specify if you want the HistoryState
to be 'secure' by setting EnableSecurityHistoryState equal to true, but this is optional.
</p>
        <p>
Your ScriptManager should now look like this:
</p>
        <p>
&lt;asp:ScriptManager runat="server" ID="sm1"<br />
     <strong><font color="#ff0000">EnableHistory="true" OnNavigate="sm1_Navigate"<br />
     EnableSecureHistoryState="true"</font></strong> /&gt;
</p>
        <h3>Step 2: Add an AsyncPostBackTrigger for the Navigate event of the ScriptManager
</h3>
        <p>
&lt;asp:UpdatePanel ...&gt;<br />
    ...<br />
    &lt;Triggers&gt;<br />
         &lt;asp:AsyncPostBackTrigger ControlID="uxChangeTime"<br />
                    
EventName="Click" /&gt;<br />
         <font color="#ff0000">&lt;asp:AsyncPostBackTrigger
ControlID="sm1" EventName="Navigate" /&gt;<br /></font>    &lt;/Triggers&gt;<br />
&lt;/asp:UpdatePanel&gt;
</p>
        <h4>Step 3: Modify the Click handler (or whatever event it is that would trigger a
HistoryPoint to be recorded
</h4>
        <p>
What you are doing here is notifying the ScriptManager what information to store as
a HistoryPoint by calling its AddHistoryPoint method. There are three possible overloads
and we will look at the other two next blog, but for now we will use one of the simplest,
a single key/value string pair to store the current DateTime with the key "myTime":
</p>
        <p>
(c# code)<br />
protected void uxChangeTime_Click(object sender, EventArgs e)<br />
{<br />
    string _currentDateTime = DateTime.Now.ToString("F");<br />
    lblTime.Text = _currentDateTime;<br />
    <strong><font color="#ff0000">ScriptManager.GetCurrent(this).AddHistoryPoint("myTime",
_currentDateTime);<br /></font></strong>}
</p>
        <p>
(vb code)<br />
Protected Sub uxChangeTime_Click(ByVal sender As Object, &amp;_<br />
  ByVal e As System.EventArgs) Handles uxChangeTime.Click<br />
    Dim _currentDateTime As String = DateTime.Now.ToString("F")<br />
    lblTime.Text = _currentDateTime<br />
    <strong><font color="#ff0000">ScriptManager.GetCurrent(Me).AddHistoryPoint("myTime",
_currentDateTime)<br /></font></strong>End Sub
</p>
        <h4>Step 4: handle the ScriptManager Navigate event
</h4>
        <p>
In this event we retrive the State property of the HistoryEventArgs and use that to
set the page to be what we want it to be. In this very simple example we will use
it to set the value of the label to be the DateTime that that particular page displayed:
</p>
        <p>
(c# code)<br />
protected void sm1_Navigate(object sender, HistoryEventArgs e)<br />
{<br />
    string _historyValue = e.State["myTime"];<br />
    if (_historyValue != null)<br />
    {<br />
        lblTime.Text = _historyValue;<br />
    }<br />
}
</p>
        <p>
(vb code)<br />
Protected Sub sm1_Navigate(ByVal sender As Object, &amp;_<br />
  ByVal e As System.HistoryEventArgs) Handles sm1.Navigate<br />
    Dim _historyValue As String = e.State["myTime"]<br />
    if(_historyValue &lt;&gt; Nothing)<br />
    {<br />
       lblTime.Text = _historyValue<br />
    }<br />
End Sub
</p>
        <p>
Voila! We now have a functional Ajax page with history. Try it!
</p>
        <p>
What has happened is that we are using History Points. When we click the button it
determines the current DateTime, displays it, and stores it as a history point. When
we click the "Back" button it retrieves the previous history point (which was the
current DateTime in string format) and displays that (see chart below).
</p>
        <p>
          <img src="http://www.myfriedmind.com/techBlog/content/binary/clickbackdisplay.gif" border="0" />
        </p>
        <p>
Next blog: a look at more intensive use of History Points...<br />
btw, for prep, take a looksee at my blog on the Memento pattern and Ajax history to
understand my basic approach: <a href="http://www.myfriedmind.com/techBlog/2009/05/20/AjaxHistoryAndTheMementoPattern.aspx">http://www.myfriedmind.com/techBlog/2009/05/20/AjaxHistoryAndTheMementoPattern.aspx</a></p>
        <img width="0" height="0" src="http://www.myfriedmind.com/techBlog/aggbug.ashx?id=b4b6d1b6-78ee-4163-afe9-29a9fb47a6d0" />
      </body>
      <title>Ajax History - a how to - Part 2 - a basic example</title>
      <guid isPermaLink="false">http://www.myfriedmind.com/techBlog/PermaLink,guid,b4b6d1b6-78ee-4163-afe9-29a9fb47a6d0.aspx</guid>
      <link>http://www.myfriedmind.com/techBlog/2009/07/01/AjaxHistoryAHowToPart2ABasicExample.aspx</link>
      <pubDate>Wed, 01 Jul 2009 14:45:56 GMT</pubDate>
      <description>&lt;p&gt;
Part 1 - &lt;a href="http://www.myfriedmind.com/techBlog/2009/06/30/AjaxHistoryAHowToPart1.aspx"&gt;&lt;font color=#5c80b1&gt;Introduction&lt;/font&gt;&lt;/a&gt;
&lt;br&gt;
Part 2 - &lt;a href="http://www.myfriedmind.com/techBlog/2009/07/01/AjaxHistoryAHowToPart2ABasicExample.aspx"&gt;&lt;font color=#5c80b1&gt;Basic
Example&lt;/font&gt;&lt;/a&gt;
&lt;br&gt;
Part 3 - &lt;a href="http://www.myfriedmind.com/techBlog/2009/07/09/AjaxHistoryAHowToPart3ComplexExampleC.aspx"&gt;&lt;font color=#5c80b1&gt;Complex
Example&lt;/font&gt;&lt;/a&gt;
&lt;br&gt;
Part 4 - &lt;a href="http://www.myfriedmind.com/techBlog/2009/07/09/AjaxHistoryAHowToPart4FinalNotes.aspx"&gt;&lt;font color=#5c80b1&gt;Final
Notes&lt;/font&gt;&lt;/a&gt;
&lt;br&gt;
Bonus - &lt;a href="http://www.myfriedmind.com/techBlog/2009/05/20/AjaxHistoryAndTheMementoPattern.aspx"&gt;&lt;font color=#5c80b1&gt;Ajax
History and the Memento Pattern&lt;/font&gt;&lt;/a&gt;
&lt;br&gt;
Extra Bonus - &lt;a href="http://www.myfriedmind.com/techBlog/2009/09/21/Opera9x10xFailingOnAjaxHistoryAndTheHackToFixIt.aspx"&gt;&lt;font color=#5c80b1&gt;Issues
with Opera&lt;/font&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
Handling Ajax history has been a critical issue since Ajax first started. With the
advent of .net 3.5 the ability to easily deal with that is rolled into the code. This
is part 2, here we will look at a simple example of handling Ajax history to give
a basic understanding of the process. If you have not read &lt;a href="http://www.myfriedmind.com/techBlog/2009/06/30/AjaxHistoryAHowToPart1.aspx"&gt;Part
1&lt;/a&gt;, I suggest you do that now. Part 3 will expand on handling Ajax history when
the data is more complex.&lt;br&gt;
For simplicity sake we are only going to look at an example of very, very basic history.
We are going to look at a page that displays changes made to the time.
&lt;/p&gt;
&lt;p&gt;
A basic assumption is that you are fairly familiar with Ajax (&lt;a href="http://ajax.asp.net"&gt;http://ajax.asp.net&lt;/a&gt;).
We are going to be using the ScriptManager (of course) and an UpdatePanel. 
&lt;br&gt;
Our basic page looks like this
&lt;/p&gt;
&lt;p&gt;
&amp;lt;%@ Page Language="C#" AutoEventWireup="true" CodeFile="AjaxHistory.aspx.cs" Inherits="AjaxHistory"
%&amp;gt;
&lt;/p&gt;
&lt;p&gt;
&amp;lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "&lt;a href="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&gt;http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd&lt;/a&gt;"&amp;gt;
&lt;/p&gt;
&lt;p&gt;
&amp;lt;html xmlns="&lt;a href="http://www.w3.org/1999/xhtml"&gt;http://www.w3.org/1999/xhtml&lt;/a&gt;"&amp;gt;&lt;br&gt;
&amp;lt;head runat="server"&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;title&amp;gt;&amp;lt;/title&amp;gt;&lt;br&gt;
&amp;lt;/head&amp;gt;&lt;br&gt;
&amp;lt;body&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;form id="form1" runat="server"&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;asp:ScriptManager runat="server" ID="sm1" EnablePartialRendering="true"
/&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;div&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;asp:UpdatePanel runat="server" ID="upME"&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;ContentTemplate&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;lt;asp:Button runat="server" ID="uxChangeTime" 
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
OnClick="uxChangeTime_Click" Text="-- change:" /&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;lt;asp:Label runat="server" ID="lblTime" /&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/ContentTemplate&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;Triggers&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;lt;asp:AsyncPostBackTrigger ControlID="uxChangeTime"&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
EventName="Click" /&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/Triggers&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/asp:UpdatePanel&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/div&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/form&amp;gt;&lt;br&gt;
&amp;lt;/body&amp;gt;&lt;br&gt;
&amp;lt;/html&amp;gt;
&lt;/p&gt;
&lt;p&gt;
The codebehind sets the label text to be the current date/time on every click:
&lt;/p&gt;
&lt;p&gt;
(c# code)&lt;br&gt;
protected void uxChangeTime_Click(object sender, EventArgs e)&lt;br&gt;
{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; string _currentDateTime = DateTime.Now.ToString("F");&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; lblTime.Text = _currentDateTime;&lt;br&gt;
}
&lt;/p&gt;
&lt;p&gt;
(vb code)&lt;br&gt;
Protected Sub uxChangeTime_Click(ByVal sender As Object, &amp;amp;_&lt;br&gt;
&amp;nbsp; ByVal e As System.EventArgs) Handles uxChangeTime.Click&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; Dim _currentDateTime As String = DateTime.Now.ToString("F")&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; lblTime.Text = _currentDateTime&lt;br&gt;
End Sub
&lt;/p&gt;
&lt;p&gt;
As you can see this is fairly straightforward. Clicking on the button displays the
current DateTime in the label. However, there is no history. Clicking back will not
display the last DateTime displayed but either be grayed out (if this was the first
page loaded) or take you back to the page before this one.
&lt;/p&gt;
&lt;p&gt;
To enable history is very, very simple in 3.5
&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
modify the ScriptManager, setting a property or two and registering an event (Navigate)
for the ScriptManager 
&lt;li&gt;
modify the Click handler to notify the ScriptManager to record a History Point 
&lt;li&gt;
handle the event called by the ScriptManager to rollback, when required, the page&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Step 1: Modify the ScriptManager
&lt;/h3&gt;
&lt;p&gt;
The modifications are very simple - set EnableHistory equal to true and specify what
should handle the Navigate event. You can also specify if you want the HistoryState
to be 'secure' by setting EnableSecurityHistoryState equal to true, but this is optional.
&lt;/p&gt;
&lt;p&gt;
Your ScriptManager should now look like this:
&lt;/p&gt;
&lt;p&gt;
&amp;lt;asp:ScriptManager runat="server" ID="sm1"&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;strong&gt;&lt;font color=#ff0000&gt;EnableHistory="true" OnNavigate="sm1_Navigate"&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; EnableSecureHistoryState="true"&lt;/font&gt;&lt;/strong&gt; /&amp;gt;
&lt;/p&gt;
&lt;h3&gt;Step 2: Add an AsyncPostBackTrigger for the Navigate event of the ScriptManager
&lt;/h3&gt;
&lt;p&gt;
&amp;lt;asp:UpdatePanel ...&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; ...&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;Triggers&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;asp:AsyncPostBackTrigger ControlID="uxChangeTime"&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
EventName="Click" /&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color=#ff0000&gt;&amp;lt;asp:AsyncPostBackTrigger
ControlID="sm1" EventName="Navigate" /&amp;gt;&lt;br&gt;
&lt;/font&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/Triggers&amp;gt;&lt;br&gt;
&amp;lt;/asp:UpdatePanel&amp;gt;
&lt;/p&gt;
&lt;h4&gt;Step 3: Modify the Click handler (or whatever event it is that would trigger a
HistoryPoint to be recorded
&lt;/h4&gt;
&lt;p&gt;
What you are doing here is notifying the ScriptManager what information to store as
a HistoryPoint by calling its AddHistoryPoint method. There are three possible overloads
and we will look at the other two next blog, but for now we will use one of the simplest,
a single key/value string pair to store the current DateTime with the key "myTime":
&lt;/p&gt;
&lt;p&gt;
(c# code)&lt;br&gt;
protected void uxChangeTime_Click(object sender, EventArgs e)&lt;br&gt;
{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; string _currentDateTime = DateTime.Now.ToString("F");&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; lblTime.Text = _currentDateTime;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;strong&gt;&lt;font color=#ff0000&gt;ScriptManager.GetCurrent(this).AddHistoryPoint("myTime",
_currentDateTime);&lt;br&gt;
&lt;/font&gt;&lt;/strong&gt;}
&lt;/p&gt;
&lt;p&gt;
(vb code)&lt;br&gt;
Protected Sub uxChangeTime_Click(ByVal sender As Object, &amp;amp;_&lt;br&gt;
&amp;nbsp; ByVal e As System.EventArgs) Handles uxChangeTime.Click&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; Dim _currentDateTime As String = DateTime.Now.ToString("F")&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; lblTime.Text = _currentDateTime&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;strong&gt;&lt;font color=#ff0000&gt;ScriptManager.GetCurrent(Me).AddHistoryPoint("myTime",
_currentDateTime)&lt;br&gt;
&lt;/font&gt;&lt;/strong&gt;End Sub
&lt;/p&gt;
&lt;h4&gt;Step 4: handle the ScriptManager Navigate event
&lt;/h4&gt;
&lt;p&gt;
In this event we retrive the State property of the HistoryEventArgs and use that to
set the page to be what we want it to be. In this very simple example we will use
it to set the value of the label to be the DateTime that that particular page displayed:
&lt;/p&gt;
&lt;p&gt;
(c# code)&lt;br&gt;
protected void sm1_Navigate(object sender, HistoryEventArgs e)&lt;br&gt;
{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; string _historyValue = e.State["myTime"];&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; if (_historyValue != null)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; lblTime.Text = _historyValue;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;
}
&lt;/p&gt;
&lt;p&gt;
(vb code)&lt;br&gt;
Protected Sub sm1_Navigate(ByVal sender As Object, &amp;amp;_&lt;br&gt;
&amp;nbsp; ByVal e As System.HistoryEventArgs) Handles sm1.Navigate&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; Dim _historyValue As String = e.State["myTime"]&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; if(_historyValue &amp;lt;&amp;gt; Nothing)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; lblTime.Text = _historyValue&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;
End Sub
&lt;/p&gt;
&lt;p&gt;
Voila! We now have a functional Ajax page with history. Try it!
&lt;/p&gt;
&lt;p&gt;
What has happened is that we are using History Points. When we click the button it
determines the current DateTime, displays it, and stores it as a history point. When
we click the "Back" button it retrieves the previous history point (which was the
current DateTime in string format) and displays that (see chart below).
&lt;/p&gt;
&lt;p&gt;
&lt;img src="http://www.myfriedmind.com/techBlog/content/binary/clickbackdisplay.gif" border=0&gt;
&lt;/p&gt;
&lt;p&gt;
Next blog: a look at more intensive use of History Points...&lt;br&gt;
btw, for prep, take a looksee at my blog on the Memento pattern and Ajax history to
understand my basic approach:&amp;nbsp;&lt;a href="http://www.myfriedmind.com/techBlog/2009/05/20/AjaxHistoryAndTheMementoPattern.aspx"&gt;http://www.myfriedmind.com/techBlog/2009/05/20/AjaxHistoryAndTheMementoPattern.aspx&lt;/a&gt;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.myfriedmind.com/techBlog/aggbug.ashx?id=b4b6d1b6-78ee-4163-afe9-29a9fb47a6d0" /&gt;</description>
      <comments>http://www.myfriedmind.com/techBlog/CommentView,guid,b4b6d1b6-78ee-4163-afe9-29a9fb47a6d0.aspx</comments>
      <category>Ajax</category>
      <category>Asp.Net</category>
      <category>c#</category>
      <category>Coding Tricks</category>
      <category>VB.Net</category>
    </item>
    <item>
      <trackback:ping>http://www.myfriedmind.com/techBlog/Trackback.aspx?guid=d2c8095a-c083-4c09-ac19-6df6edf8a627</trackback:ping>
      <pingback:server>http://www.myfriedmind.com/techBlog/pingback.aspx</pingback:server>
      <pingback:target>http://www.myfriedmind.com/techBlog/PermaLink,guid,d2c8095a-c083-4c09-ac19-6df6edf8a627.aspx</pingback:target>
      <dc:creator>papabear</dc:creator>
      <wfw:comment>http://www.myfriedmind.com/techBlog/CommentView,guid,d2c8095a-c083-4c09-ac19-6df6edf8a627.aspx</wfw:comment>
      <wfw:commentRss>http://www.myfriedmind.com/techBlog/SyndicationService.asmx/GetEntryCommentsRss?guid=d2c8095a-c083-4c09-ac19-6df6edf8a627</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Part 1 - <a href="http://www.myfriedmind.com/techBlog/2009/06/30/AjaxHistoryAHowToPart1.aspx"><font color="#5c80b1">Introduction</font></a><br />
Part 2 - <a href="http://www.myfriedmind.com/techBlog/2009/07/01/AjaxHistoryAHowToPart2ABasicExample.aspx"><font color="#5c80b1">Basic
Example</font></a><br />
Part 3 - <a href="http://www.myfriedmind.com/techBlog/2009/07/09/AjaxHistoryAHowToPart3ComplexExampleC.aspx"><font color="#5c80b1">Complex
Example</font></a><br />
Part 4 - <a href="http://www.myfriedmind.com/techBlog/2009/07/09/AjaxHistoryAHowToPart4FinalNotes.aspx"><font color="#5c80b1">Final
Notes</font></a><br />
Bonus - <a href="http://www.myfriedmind.com/techBlog/2009/05/20/AjaxHistoryAndTheMementoPattern.aspx"><font color="#5c80b1">Ajax
History and the Memento Pattern</font></a><br />
Extra Bonus - <a href="http://www.myfriedmind.com/techBlog/2009/09/21/Opera9x10xFailingOnAjaxHistoryAndTheHackToFixIt.aspx"><font color="#5c80b1">Issues
with Opera</font></a></p>
        <p>
One of the most exciting prospects with .net 3.5 is the ability to handle Ajax History. 
</p>
        <p>
Ajax, for those of you who may be only vaguely familiar, is a way to do partial postbacks
of web pages. This allows you to modify only a portion of the screen rather than updating
the entire transaction. This increases the potential speed exponentially. One form
are CallBacks, another used by the UpdatePanel is a full PostBack but only a redrawing
of the appropriate sections of the page.
</p>
        <p>
However, there are three main problems with Ajax when using controls like the UpdatePanel:
</p>
        <ol>
          <li>
Hitting the “Back” button loads the page that was loaded BEFORE the ajax page 
</li>
          <li>
Refreshing the page has the effect of losing whatever Ajax calls have been made (ie
the page itself is reloaded from the start). 
</li>
          <li>
There is no effective method to ‘link’ to the page resulting from ajax calls. All
links lose any Ajax calls because the URL does not display the necessary information
to recreate the page at the appropriate place.</li>
        </ol>
        <p>
All of these can be resolved (as we shall see) by using Ajax History. 
</p>
        <p>
This first blog entry will lay out the problems in greater detail and the general
means by which Ajax History resolves them. Later entries will go more into detail
on how to do Ajax History (yes, there is some additional work, but not very much).
</p>
        <h3>Hitting the “Back” button loads the page that was loaded BEFORE the ajax page
</h3>
        <p>
The issue here is caused by two factors:
</p>
        <ol>
          <li>
The "Back" button loads the last entry in url history 
</li>
          <li>
Ajax does not automatically change the url history</li>
        </ol>
        <p>
An example of what I am talking about can be seen in my (non-artistic) image below. 
</p>
        <p>
          <img src="http://www.myfriedmind.com/techBlog/content/binary/PostbackVsCallBack.jpg" border="0" />
        </p>
        <p>
Hitting the "Back" button after doing regular Postbacks will take you to the most
recent page of information. However, hitting the "Back" button after doing CallBacks
takes you all the way back to the page that was loaded BEFORE you even got to the
Ajax page.
</p>
        <p>
The reason for this lies in the way that the href property of the Html Document Object
Model is handled. By default whenever a full PostBack occurs or a modification to
the hash in the URI (such as an internal link), the URI of the new entry is stored
in the location history. This is handled by the browser behind the scenes and has
been since the early days. However, since Ajax calls are not full PostBacks the browser
mechanism does not, by default, record their entry.
</p>
        <p>
To get around this, a rather ingenious method is used. Because modifications to the
URI’s hash portion is included in the history but DOES NOT require full PostBack (think
internal anchor links) .net 3.5 writes to the hash portion of the page to trigger
the entry being recorded, by the browser, in the href history. Pretty slick, hunh?
</p>
        <p>
For those of you unfamiliar with the hash concept of the URI, consider the following
quick example:
</p>
        <p>
&lt;html&gt;<br />
&lt;head&gt;&lt;/head&gt;<br />
&lt;body&gt;<br />
&lt;a name=’Up’&gt;&lt;/a&gt;<br />
&lt;a href=’upsidedown.html#Down’&gt;Go Down&lt;/a&gt;<br />
&lt;p&gt;&amp;nbsp;&lt;/p&gt;<br />
&lt;a name=’Down’&gt;&lt;/a&gt;<br />
&lt;a href=’upsidedown.html#Up’&gt;Go Up&lt;/a&gt;<br />
&lt;/body&gt;<br />
&lt;/html&gt;
</p>
        <p>
I have posted this basic page to my site. Note that there are anchor tags (&lt;a…)
that have names and others that have a hash sign (#) in them that refer to that name.
These are commonly used to enable users to just to a particular portion of the page
without having to scroll and are known as Internal Links (because they link to an
internal portion of the page and not to an external page).<br /><br />
When the page first loads you can see that the URI is simply <a href="http://www.myfriedmind.com/updown.html">http://www.myfriedmind.com/updown.html</a>.
There is one link visible (the other would be visible if you scrolled but I shrunk
the browser window to give an idea of what internal links are generally used for. 
</p>
        <p>
          <img src="http://www.myfriedmind.com/techBlog/content/binary/updownStart.JPG" border="0" />
        </p>
        <p>
Once the link is clicked it moves the page down to where the “named” anchor is. In
other words, clicking on the anchor tag that references #Down (&lt;a href=’upsidedown.html#Down’&gt;Go
Down&lt;/a&gt;) moves the page to the anchor that contains the name that matches the
one after the hash sign – so you are moved WITHIN the page (to &lt;a name=’Down’&gt;&lt;/a&gt;).
This is very important – note that the URI has changed, it is now showing the hash.
Also critical to note is that THE PAGE DID NOT POSTBACK!
</p>
        <p>
          <img src="http://www.myfriedmind.com/techBlog/content/binary/updownDown.JPG" border="0" />
        </p>
        <p>
Clicking on the link that has the hash entry for Up (&lt;a href=’upsidedown.html#Up’&gt;Go
Up&lt;/a&gt;) results in moving to the anchor tag that has the name (Up) that matches
what was after the hash mark. Again, the URI is updated to a new hash display and
THE PAGE DID NOT POSTBACK!!!
</p>
        <p>
          <img src="http://www.myfriedmind.com/techBlog/content/binary/updownUp.JPG" border="0" />
        </p>
        <p>
It is critical that you understand that when this takes place the browser records
the change in its href history. In other words, modifications to the hash are RECORDED
in the browser’s href history. Thus hitting the “Back” button means that we move back
to the previous entry, which is NOT <a href="http://www.myfriedmind.com/updown.html">http://www.myfriedmind.com/updown.html</a>,
but <a href="http://www.myfriedmind.com/updown.html#Down">http://www.myfriedmind.com/updown.html#Down</a> (see
below)
</p>
        <p>
          <img src="http://www.myfriedmind.com/techBlog/content/binary/updownDown.JPG" />
        </p>
        <p>
Thus the elegant solution – to store Ajax postbacks, record the entries in the hash
of the URI (like you are doing an internal link) and the updated URI will be recorded
in the browser history for you. Any clicks on the “Back” button will load the previous
entry. See the basic example below. Note that the change after CallBack to the URL
(adding a hash entry).
</p>
        <p>
          <img src="http://www.myfriedmind.com/techBlog/content/binary/AjaxHistoryCallbacks.jpg" border="0" />
        </p>
        <p>
I must note here that the adding to the hash is not automatic. You do need to do code
but very, very little. Your code mostly deals with how to effectively package the
info and unpackage when required. If you are curious take a looksee at my (fascinating)
blog on how this is similar to the Memento pattern -&gt;  <a href="http://www.myfriedmind.com/techBlog/2009/05/20/AjaxHistoryAndTheMementoPattern.aspx">http://www.myfriedmind.com/techBlog/2009/05/20/AjaxHistoryAndTheMementoPattern.aspx</a>.
</p>
        <p>
Once you grasp this concept – that the Ajax History is stored in the URI’s hash, the
solutions to both of problems #2 and #3 (page refresh and linking) are resolved. 
</p>
        <ul>
          <li>
Refreshing  the page refreshes the URI, INCLUDING the hash. Thus the page that
gets returned is the page that has had the Ajax modifications done 
</li>
          <li>
Sending a link to this page, INCLUDES the URI’s hash, and thus the page will be able
to return the point in its Ajax modifications that a person wants</li>
        </ul>
        <p>
There are a number of very useful examples of how this is used today (Ajax History
is not new with 3.5 but it DOES make it a whole lot simpler). The most commonly used
are mapping websites. One can hunt around (using Ajax) until one gets to the exact
display one desires and then save/send/whatever that display. Without the hash entry
one would always end up at the very beginning and the desired display would be lost.
I can use bing to zoom into the street view of Dunn Bros (the BEST coffee) by my old
alma mater in Saint Paul and shoot that url to a friend.( shortened for display - <a href="http://www.bing.com/maps/#JnE9eX...zMTI1">http://www.bing.com/maps/#JnE9eX...zMTI1</a>)
</p>
        <p>
But this is not limited to mapping sites. Imagine that you have a Ajax based site
that enables users to filter/sort/etc on a GridView display customer accounts. “Ah
ha,” says the manager (they say things like that when no one is listening) “this is
precisely the display I am looking for. I will just save it into my favorites. And
I will also email it to the big boss.” Without the hash they would be exceedingly
frustrated as would the big boss. With proper Ajax history coding the sun shines,
the wind blows, and gas prices drop. Everyone is happy.
</p>
        <p>
;)
</p>
        <p>
Next blog: What exactly is involved in doing Ajax History, the concepts….<br /></p>
        <img width="0" height="0" src="http://www.myfriedmind.com/techBlog/aggbug.ashx?id=d2c8095a-c083-4c09-ac19-6df6edf8a627" />
      </body>
      <title>Ajax History - a how to - Part 1</title>
      <guid isPermaLink="false">http://www.myfriedmind.com/techBlog/PermaLink,guid,d2c8095a-c083-4c09-ac19-6df6edf8a627.aspx</guid>
      <link>http://www.myfriedmind.com/techBlog/2009/06/30/AjaxHistoryAHowToPart1.aspx</link>
      <pubDate>Tue, 30 Jun 2009 16:03:29 GMT</pubDate>
      <description>&lt;p&gt;
Part 1 - &lt;a href="http://www.myfriedmind.com/techBlog/2009/06/30/AjaxHistoryAHowToPart1.aspx"&gt;&lt;font color=#5c80b1&gt;Introduction&lt;/font&gt;&lt;/a&gt;
&lt;br&gt;
Part 2 - &lt;a href="http://www.myfriedmind.com/techBlog/2009/07/01/AjaxHistoryAHowToPart2ABasicExample.aspx"&gt;&lt;font color=#5c80b1&gt;Basic
Example&lt;/font&gt;&lt;/a&gt;
&lt;br&gt;
Part 3 - &lt;a href="http://www.myfriedmind.com/techBlog/2009/07/09/AjaxHistoryAHowToPart3ComplexExampleC.aspx"&gt;&lt;font color=#5c80b1&gt;Complex
Example&lt;/font&gt;&lt;/a&gt;
&lt;br&gt;
Part 4 - &lt;a href="http://www.myfriedmind.com/techBlog/2009/07/09/AjaxHistoryAHowToPart4FinalNotes.aspx"&gt;&lt;font color=#5c80b1&gt;Final
Notes&lt;/font&gt;&lt;/a&gt;
&lt;br&gt;
Bonus - &lt;a href="http://www.myfriedmind.com/techBlog/2009/05/20/AjaxHistoryAndTheMementoPattern.aspx"&gt;&lt;font color=#5c80b1&gt;Ajax
History and the Memento Pattern&lt;/font&gt;&lt;/a&gt;
&lt;br&gt;
Extra Bonus - &lt;a href="http://www.myfriedmind.com/techBlog/2009/09/21/Opera9x10xFailingOnAjaxHistoryAndTheHackToFixIt.aspx"&gt;&lt;font color=#5c80b1&gt;Issues
with Opera&lt;/font&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
One of the most exciting prospects with .net 3.5 is the ability to handle Ajax History. 
&lt;/p&gt;
&lt;p&gt;
Ajax, for those of you who may be only vaguely familiar, is a way to do partial postbacks
of web pages. This allows you to modify only a portion of the screen rather than updating
the entire transaction. This increases the potential speed exponentially. One form
are CallBacks, another used by the UpdatePanel is a full PostBack but only a redrawing
of the appropriate sections of the page.
&lt;/p&gt;
&lt;p&gt;
However, there are three main problems with Ajax when using controls like the UpdatePanel:
&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
Hitting the “Back” button loads the page that was loaded BEFORE the ajax page 
&lt;li&gt;
Refreshing the page has the effect of losing whatever Ajax calls have been made (ie
the page itself is reloaded from the start). 
&lt;li&gt;
There is no effective method to ‘link’ to the page resulting from ajax calls. All
links lose any Ajax calls because the URL does not display the necessary information
to recreate the page at the appropriate place.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;
All of these can be resolved (as we shall see) by using Ajax History. 
&lt;/p&gt;
&lt;p&gt;
This first blog entry will lay out the problems in greater detail and the general
means by which Ajax History resolves them. Later entries will go more into detail
on how to do Ajax History (yes, there is some additional work, but not very much).
&lt;/p&gt;
&lt;h3&gt;Hitting the “Back” button loads the page that was loaded BEFORE the ajax page
&lt;/h3&gt;
&lt;p&gt;
The issue here is caused by two factors:
&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
The "Back" button loads the last entry in url history 
&lt;li&gt;
Ajax does not automatically&amp;nbsp;change the url history&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;
An example of what I am talking about can be seen in my (non-artistic) image below. 
&lt;/p&gt;
&lt;p&gt;
&lt;img src="http://www.myfriedmind.com/techBlog/content/binary/PostbackVsCallBack.jpg" border=0&gt;
&lt;/p&gt;
&lt;p&gt;
Hitting the "Back" button after doing regular Postbacks will take you to the most
recent page of information. However, hitting the "Back" button after doing CallBacks
takes you all the way back to the page that was loaded BEFORE you even got to the
Ajax page.
&lt;/p&gt;
&lt;p&gt;
The reason for this lies in the way that the href property of the Html Document Object
Model is handled. By default whenever a full PostBack occurs or a modification to
the hash in the URI (such as an internal link), the URI of the new entry is stored
in the location history. This is handled by the browser behind the scenes and has
been since the early days. However, since Ajax calls are not full PostBacks the browser
mechanism does not, by default, record their entry.
&lt;/p&gt;
&lt;p&gt;
To get around this, a rather ingenious method is used. Because modifications to the
URI’s hash portion is included in the history but DOES NOT require full PostBack (think
internal anchor links) .net 3.5 writes to the hash portion of the page to trigger
the entry being recorded, by the browser, in the href history. Pretty slick, hunh?
&lt;/p&gt;
&lt;p&gt;
For those of you unfamiliar with the hash concept of the URI, consider the following
quick example:
&lt;/p&gt;
&lt;p&gt;
&amp;lt;html&amp;gt;&lt;br&gt;
&amp;lt;head&amp;gt;&amp;lt;/head&amp;gt;&lt;br&gt;
&amp;lt;body&amp;gt;&lt;br&gt;
&amp;lt;a name=’Up’&amp;gt;&amp;lt;/a&amp;gt;&lt;br&gt;
&amp;lt;a href=’upsidedown.html#Down’&amp;gt;Go Down&amp;lt;/a&amp;gt;&lt;br&gt;
&amp;lt;p&amp;gt;&amp;amp;nbsp;&amp;lt;/p&amp;gt;&lt;br&gt;
&amp;lt;a name=’Down’&amp;gt;&amp;lt;/a&amp;gt;&lt;br&gt;
&amp;lt;a href=’upsidedown.html#Up’&amp;gt;Go Up&amp;lt;/a&amp;gt;&lt;br&gt;
&amp;lt;/body&amp;gt;&lt;br&gt;
&amp;lt;/html&amp;gt;
&lt;/p&gt;
&lt;p&gt;
I have posted this basic page to my site. Note that there are anchor tags (&amp;lt;a…)
that have names and others that have a hash sign (#) in them that refer to that name.
These are commonly used to enable users to just to a particular portion of the page
without having to scroll and are known as Internal Links (because they link to an
internal portion of the page and not to an external page).&lt;br&gt;
&lt;br&gt;
When the page first loads you can see that the URI is simply &lt;a href="http://www.myfriedmind.com/updown.html"&gt;http://www.myfriedmind.com/updown.html&lt;/a&gt;.
There is one link visible (the other would be visible if you scrolled but I shrunk
the browser window to give an idea of what internal links are generally used for. 
&lt;/p&gt;
&lt;p&gt;
&lt;img src="http://www.myfriedmind.com/techBlog/content/binary/updownStart.JPG" border=0&gt;
&lt;/p&gt;
&lt;p&gt;
Once the link is clicked it moves the page down to where the “named” anchor is. In
other words, clicking on the anchor tag that references #Down (&amp;lt;a href=’upsidedown.html#Down’&amp;gt;Go
Down&amp;lt;/a&amp;gt;) moves the page to the anchor that contains the name that matches the
one after the hash sign – so you are moved WITHIN the page (to &amp;lt;a name=’Down’&amp;gt;&amp;lt;/a&amp;gt;).
This is very important – note that the URI has changed, it is now showing the hash.
Also critical to note is that THE PAGE DID NOT POSTBACK!
&lt;/p&gt;
&lt;p&gt;
&lt;img src="http://www.myfriedmind.com/techBlog/content/binary/updownDown.JPG" border=0&gt;
&lt;/p&gt;
&lt;p&gt;
Clicking on the link that has the hash entry for Up (&amp;lt;a href=’upsidedown.html#Up’&amp;gt;Go
Up&amp;lt;/a&amp;gt;) results in moving to the anchor tag that has the name (Up) that matches
what was after the hash mark. Again, the URI is updated to a new hash display and
THE PAGE DID NOT POSTBACK!!!
&lt;/p&gt;
&lt;p&gt;
&lt;img src="http://www.myfriedmind.com/techBlog/content/binary/updownUp.JPG" border=0&gt;
&lt;/p&gt;
&lt;p&gt;
It is critical that you understand that when this takes place the browser records
the change in its href history. In other words, modifications to the hash are RECORDED
in the browser’s href history. Thus hitting the “Back” button means that we move back
to the previous entry, which is NOT &lt;a href="http://www.myfriedmind.com/updown.html"&gt;http://www.myfriedmind.com/updown.html&lt;/a&gt;,
but &lt;a href="http://www.myfriedmind.com/updown.html#Down"&gt;http://www.myfriedmind.com/updown.html#Down&lt;/a&gt; (see
below)
&lt;/p&gt;
&lt;p&gt;
&lt;img src="http://www.myfriedmind.com/techBlog/content/binary/updownDown.JPG"&gt;
&lt;/p&gt;
&lt;p&gt;
Thus the elegant solution – to store Ajax postbacks, record the entries in the hash
of the URI (like you are doing an internal link) and the updated URI will be recorded
in the browser history for you. Any clicks on the “Back” button will load the previous
entry. See the basic example below. Note that the change after CallBack to the URL
(adding a hash entry).
&lt;/p&gt;
&lt;p&gt;
&lt;img src="http://www.myfriedmind.com/techBlog/content/binary/AjaxHistoryCallbacks.jpg" border=0&gt;
&lt;/p&gt;
&lt;p&gt;
I must note here that the adding to the hash is not automatic. You do need to do code
but very, very little. Your code mostly deals with how to effectively package the
info and unpackage when required. If you are curious take a looksee at my (fascinating)
blog on how this is similar to the Memento pattern -&amp;gt; &amp;nbsp;&lt;a href="http://www.myfriedmind.com/techBlog/2009/05/20/AjaxHistoryAndTheMementoPattern.aspx"&gt;http://www.myfriedmind.com/techBlog/2009/05/20/AjaxHistoryAndTheMementoPattern.aspx&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;
Once you grasp this concept – that the Ajax History is stored in the URI’s hash, the
solutions to both of problems #2 and #3 (page refresh and linking) are resolved. 
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
Refreshing&amp;nbsp; the page refreshes the URI, INCLUDING the hash. Thus the page that
gets returned is the page that has had the Ajax modifications done 
&lt;li&gt;
Sending a link to this page, INCLUDES the URI’s hash, and thus the page will be able
to return the point in its Ajax modifications that a person wants&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
There are a number of very useful examples of how&amp;nbsp;this is used today (Ajax History
is not new with 3.5 but it DOES make it a whole lot simpler). The most commonly used
are mapping websites. One can hunt around (using Ajax) until one gets to the exact
display one desires and then save/send/whatever that display. Without the hash entry
one would always end up at the very beginning and the desired display would be lost.
I can use bing to zoom into the street view of Dunn Bros (the BEST coffee) by my old
alma mater in Saint Paul and shoot that url to a friend.( shortened for display - &lt;a href="http://www.bing.com/maps/#JnE9eX...zMTI1"&gt;http://www.bing.com/maps/#JnE9eX...zMTI1&lt;/a&gt;)
&lt;/p&gt;
&lt;p&gt;
But this is not limited to mapping sites. Imagine that you have a Ajax based site
that enables users to filter/sort/etc on a GridView display customer accounts. “Ah
ha,” says the manager (they say things like that when no one is listening) “this is
precisely the display I am looking for. I will just save it into my favorites. And
I will also email it to the big boss.” Without the hash they would be exceedingly
frustrated as would the big boss. With proper Ajax history coding the sun shines,
the wind blows, and gas prices drop. Everyone is happy.
&lt;/p&gt;
&lt;p&gt;
;)
&lt;/p&gt;
&lt;p&gt;
Next blog: What exactly is involved in doing Ajax History, the concepts….&lt;br&gt;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.myfriedmind.com/techBlog/aggbug.ashx?id=d2c8095a-c083-4c09-ac19-6df6edf8a627" /&gt;</description>
      <comments>http://www.myfriedmind.com/techBlog/CommentView,guid,d2c8095a-c083-4c09-ac19-6df6edf8a627.aspx</comments>
      <category>Ajax</category>
      <category>Asp.Net</category>
      <category>c#</category>
      <category>Coding Tricks</category>
      <category>VB.Net</category>
    </item>
    <item>
      <trackback:ping>http://www.myfriedmind.com/techBlog/Trackback.aspx?guid=52f2adba-43f8-44ce-83ce-3312677761d6</trackback:ping>
      <pingback:server>http://www.myfriedmind.com/techBlog/pingback.aspx</pingback:server>
      <pingback:target>http://www.myfriedmind.com/techBlog/PermaLink,guid,52f2adba-43f8-44ce-83ce-3312677761d6.aspx</pingback:target>
      <dc:creator>papabear</dc:creator>
      <wfw:comment>http://www.myfriedmind.com/techBlog/CommentView,guid,52f2adba-43f8-44ce-83ce-3312677761d6.aspx</wfw:comment>
      <wfw:commentRss>http://www.myfriedmind.com/techBlog/SyndicationService.asmx/GetEntryCommentsRss?guid=52f2adba-43f8-44ce-83ce-3312677761d6</wfw:commentRss>
      <slash:comments>2</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
okay, I apologize. I promised to do this weeks ago and am only finally getting it
up. Hopefully it will be worth the wait...
</p>
        <p>
If you are planning on simply using a DDL (and not Cascading), look here -&gt; <a href="http://www.myfriedmind.com/techBlog/2009/06/04/DropDownListGridViewAndDynamicallySelectingTheAppropriateListItemDuringEdit.aspx">http://www.myfriedmind.com/techBlog/2009/06/04/DropDownListGridViewAndDynamicallySelectingTheAppropriateListItemDuringEdit.aspx</a></p>
        <p>
Note that this example uses a remote webservice (rather than a PageMethod) for the
CascadingDropDownList calls and I have not included them to simplify the amount of
code on this page, but they are fairly straightforward -&gt; <a href="http://www.asp.net/AJAX/AjaxControlToolkit/Samples/CascadingDropDown/CascadingDropDown.aspx">http://www.asp.net/AJAX/AjaxControlToolkit/Samples/CascadingDropDown/CascadingDropDown.aspx</a></p>
        <p>
Sample DataObject (in c#)
</p>
        <p>
class MyObject<br />
{<br />
   public int ObjId { get; set; }<br />
   public string StateAbbreviation { get; set; }<br />
   public string ZipCode { get; set; }<br />
}
</p>
        <p>
Sample DataObject (in vb.net)
</p>
        <p>
Class MyObject<br />
   Public ObjId As Integer<br />
   Public StateAbbreviation As String<br />
   Public ZipCode As String<br />
End Class
</p>
        <p>
Entry on SampleGridView.aspx page (as simple as you can get it)
</p>
        <p>
&lt;asp:GridView runat="server" ID="lstMyData" DataKeyNames="ObjId"<br />
    AutoGenerateColumns="false" EnableViewState="true"<br />
    AutoGenerateEditButton="true"<br />
    OnRowDataBound="lstMyData_RowDataBound" &gt;<br />
    &lt;Columns&gt;<br />
        &lt;asp:TemplateField&gt;<br />
            &lt;ItemTemplate&gt;<br />
               
&lt;asp:Label runat="server" ID="lblState"     
<br />
                   
Text='&lt;%# Eval("StateAbbreviation") %&gt;' /&gt;<br />
            &lt;/ItemTemplate&gt;<br />
            &lt;EditItemTemplate&gt;<br />
               
&lt;asp:DropDownList runat="server" ID="uxState" /&gt;<br />
               
&lt;aKit:CascadingDropDown ID="ajxState" runat="server" 
<br />
                   
TargetControlID="uxState" Category="State" <br />
                   
ServiceMethod="GetStates" /&gt;<br />
            &lt;/EditItemTemplate&gt;<br />
        &lt;/asp:TemplateField&gt;<br />
        &lt;asp:TemplateField&gt;<br />
            &lt;ItemTemplate&gt;<br />
               
&lt;asp:Label runat="server" ID="lblZipCode"   
<br />
                  
Text='&lt;%# Eval("ZipCode") %&gt;' /&gt;<br />
            &lt;/ItemTemplate&gt;<br />
            &lt;EditItemTemplate&gt;<br />
               
&lt;asp:DropDownList runat="server" ID="uxZipCode" /&gt;<br />
               
&lt;aKit:CascadingDropDown ID="ajxZipCode" runat="server" 
<br />
                   
TargetControlID="uxZipCode" Category="ZipCode" 
<br />
                   
LoadingText="[Loading Zipcode...]"<br />
                   
ServicePath="WebServiceToReturnData.asmx" <br />
                   
ServiceMethod="GetZipCode" 
<br />
                 
ParentControlID="uxState" /&gt;<br />
            &lt;/EditItemTemplate&gt;<br />
        &lt;/asp:TemplateField&gt;<br />
    &lt;/Columns&gt;<br />
&lt;/asp:GridView&gt;
</p>
        <p>
Codebehind (in c#) SampleGridView.apx.cs (note this does NOT include the code to return
the values)
</p>
        <p>
protected void lstMyData_RowDataBound(object sender, 
<br />
        GridViewRowEventArgs e)<br />
{<br />
    // verify this is a DataRow, not a Header, Footer, etc...<br />
    if (e.Row.RowType == DataControlRowType.DataRow)<br />
    {<br />
        // in case you want to do something else
here....<br />
        
<br />
        // see if this is the Row used for Editing<br />
        if ((e.Row.RowState &amp; DataControlRowState.Edit)
!= 0)<br />
        {<br />
            // get the DataItem
that is bound 
<br />
            // and cast it
accordingly<br />
            MyObject _myObject
= (MyObject)e.Row.DataItem;<br /><br />
            // get the CascadingDropDowns<br />
            CascadingDropDown
_ajxState = 
<br />
               
(CascadingDropDown) e.Row.FindControl("ajxState");<br />
            CascadingDropDown
_ajxZipCode = 
<br />
               
(CascadingDropDown) e.Row.FindControl("ajxZipCode");<br /><br />
            // the data
is automatically updated via the Ajax,<br />
            // so we merely
need to select the item<br /><br />
            _ajxState.SelectedValue
= _myObject.StateAbbreviation<br />
            // _ajxState.ContextKey
= this can be set here if you are using it;<br /><br />
            _ajxZipCode.SelectedValue
= myObject.ZipCode;<br />
        }<br />
    }<br />
}
</p>
        <p>
Codebehind (in vb.net) SampleGridView.apx.cs (note this does NOT include the code
to return the values)
</p>
        <p>
Protected Sub lstMyData_RowDataBound(ByVal sender As Object, _<br />
    ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs) _<br />
    Handles lstMyData.RowDataBound<br />
    If e.Row.RowType = DataControlRowType.DataRow Then
</p>
        <p>
            ' in case you want
to do something else here....
</p>
        <p>
            ' see if this is
the Row used for Editing<br />
            If (e.Row.RowState
And DataControlRowState.Edit) &lt;&gt; 0 Then
</p>
        <p>
          <br />
               
' get the DataItem that is bound<br />
               
' and cast it accordingly<br />
               
Dim _myObject As MyObject = _<br />
                   
DirectCast(e.Row.DataItem, MyObject)
</p>
        <p>
               
' get the CascadingDropDowns<br />
               
Dim _ajxState As CascadingDropDown = _<br />
                   
DirectCast(e.Row.FindControl("ajxState"), CascadingDropDown)<br />
               
Dim _ajxZipcode As CascadingDropDown = _<br />
                   
DirectCast(e.Row.FindControl("ajxZipCode"), CascadingDropDown)
</p>
        <p>
               
' ddl population should be handled by the Ajax<br />
               
' ServiceMethod of the CascadingDropDown
</p>
        <p>
               
' select the appropriate item<br />
               
_ajxState.SelectedValue = _myObject.StateAbbreviation<br />
               
_ajxZipCode.SelectedValue = _myObject.ZipCode
</p>
        <p>
            End If<br />
     End If<br />
End Sub
</p>
        <img width="0" height="0" src="http://www.myfriedmind.com/techBlog/aggbug.ashx?id=52f2adba-43f8-44ce-83ce-3312677761d6" />
      </body>
      <title>CascadingDropDownLists, GridViews, and Dynamically selecting the appropriate ListItem during Edit...</title>
      <guid isPermaLink="false">http://www.myfriedmind.com/techBlog/PermaLink,guid,52f2adba-43f8-44ce-83ce-3312677761d6.aspx</guid>
      <link>http://www.myfriedmind.com/techBlog/2009/06/22/CascadingDropDownListsGridViewsAndDynamicallySelectingTheAppropriateListItemDuringEdit.aspx</link>
      <pubDate>Mon, 22 Jun 2009 15:16:46 GMT</pubDate>
      <description>&lt;p&gt;
okay, I apologize. I promised to do this weeks ago and am only finally getting it
up. Hopefully it will be worth the wait...
&lt;/p&gt;
&lt;p&gt;
If you are planning on simply using a DDL (and not Cascading), look here -&amp;gt; &lt;a href="http://www.myfriedmind.com/techBlog/2009/06/04/DropDownListGridViewAndDynamicallySelectingTheAppropriateListItemDuringEdit.aspx"&gt;http://www.myfriedmind.com/techBlog/2009/06/04/DropDownListGridViewAndDynamicallySelectingTheAppropriateListItemDuringEdit.aspx&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
Note that this example uses a remote webservice (rather than a PageMethod) for the
CascadingDropDownList calls and I have not included them to simplify the amount of
code on this page, but they are fairly straightforward -&amp;gt; &lt;a href="http://www.asp.net/AJAX/AjaxControlToolkit/Samples/CascadingDropDown/CascadingDropDown.aspx"&gt;http://www.asp.net/AJAX/AjaxControlToolkit/Samples/CascadingDropDown/CascadingDropDown.aspx&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
Sample DataObject (in c#)
&lt;/p&gt;
&lt;p&gt;
class MyObject&lt;br&gt;
{&lt;br&gt;
&amp;nbsp;&amp;nbsp; public int ObjId { get; set; }&lt;br&gt;
&amp;nbsp;&amp;nbsp; public string StateAbbreviation { get; set; }&lt;br&gt;
&amp;nbsp;&amp;nbsp; public string ZipCode { get; set; }&lt;br&gt;
}
&lt;/p&gt;
&lt;p&gt;
Sample DataObject (in vb.net)
&lt;/p&gt;
&lt;p&gt;
Class MyObject&lt;br&gt;
&amp;nbsp;&amp;nbsp; Public ObjId As Integer&lt;br&gt;
&amp;nbsp;&amp;nbsp; Public StateAbbreviation As String&lt;br&gt;
&amp;nbsp;&amp;nbsp; Public ZipCode As String&lt;br&gt;
End Class
&lt;/p&gt;
&lt;p&gt;
Entry on SampleGridView.aspx page (as simple as you can get it)
&lt;/p&gt;
&lt;p&gt;
&amp;lt;asp:GridView runat="server" ID="lstMyData" DataKeyNames="ObjId"&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; AutoGenerateColumns="false" EnableViewState="true"&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; AutoGenerateEditButton="true"&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; OnRowDataBound="lstMyData_RowDataBound" &amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;Columns&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;asp:TemplateField&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;ItemTemplate&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;lt;asp:Label runat="server" ID="lblState"&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
Text='&amp;lt;%# Eval("StateAbbreviation") %&amp;gt;' /&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/ItemTemplate&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;EditItemTemplate&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;lt;asp:DropDownList runat="server" ID="uxState" /&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;lt;aKit:CascadingDropDown ID="ajxState" runat="server" 
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
TargetControlID="uxState" Category="State"&amp;nbsp;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
ServiceMethod="GetStates" /&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/EditItemTemplate&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/asp:TemplateField&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;asp:TemplateField&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;ItemTemplate&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;lt;asp:Label runat="server" ID="lblZipCode"&amp;nbsp;&amp;nbsp; 
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
Text='&amp;lt;%# Eval("ZipCode") %&amp;gt;' /&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/ItemTemplate&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;EditItemTemplate&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;lt;asp:DropDownList runat="server" ID="uxZipCode" /&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;lt;aKit:CascadingDropDown ID="ajxZipCode" runat="server" 
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
TargetControlID="uxZipCode" Category="ZipCode" 
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
LoadingText="[Loading Zipcode...]"&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
ServicePath="WebServiceToReturnData.asmx"&amp;nbsp;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
ServiceMethod="GetZipCode" 
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
ParentControlID="uxState" /&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/EditItemTemplate&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/asp:TemplateField&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/Columns&amp;gt;&lt;br&gt;
&amp;lt;/asp:GridView&amp;gt;
&lt;/p&gt;
&lt;p&gt;
Codebehind (in c#) SampleGridView.apx.cs (note this does NOT include the code to return
the values)
&lt;/p&gt;
&lt;p&gt;
protected void lstMyData_RowDataBound(object sender, 
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; GridViewRowEventArgs e)&lt;br&gt;
{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; // verify this is a DataRow, not a Header, Footer, etc...&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; if (e.Row.RowType == DataControlRowType.DataRow)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // in case you want to do something else
here....&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // see if this is the Row used for Editing&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if ((e.Row.RowState &amp;amp; DataControlRowState.Edit)
!= 0)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // get the DataItem
that is bound 
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // and cast it
accordingly&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; MyObject _myObject
= (MyObject)e.Row.DataItem;&lt;br&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // get the CascadingDropDowns&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; CascadingDropDown
_ajxState = 
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
(CascadingDropDown) e.Row.FindControl("ajxState");&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; CascadingDropDown
_ajxZipCode = 
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
(CascadingDropDown) e.Row.FindControl("ajxZipCode");&lt;br&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //&amp;nbsp;the data
is&amp;nbsp;automatically updated via the Ajax,&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //&amp;nbsp;so we merely
need to select the item&lt;br&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _ajxState.SelectedValue
= _myObject.StateAbbreviation&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // _ajxState.ContextKey
= this can be set here if you are using it;&lt;br&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _ajxZipCode.SelectedValue
= myObject.ZipCode;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;
}
&lt;/p&gt;
&lt;p&gt;
Codebehind (in vb.net) SampleGridView.apx.cs (note this does NOT include the code
to return the values)
&lt;/p&gt;
&lt;p&gt;
Protected Sub lstMyData_RowDataBound(ByVal sender As Object, _&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs) _&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; Handles lstMyData.RowDataBound&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; If e.Row.RowType = DataControlRowType.DataRow Then
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ' in case you want
to do something else here....
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ' see if this is
the Row used for Editing&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; If (e.Row.RowState
And DataControlRowState.Edit)&amp;nbsp;&amp;lt;&amp;gt; 0 Then
&lt;/p&gt;
&lt;p&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
' get the DataItem that is bound&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
' and cast it accordingly&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
Dim _myObject As MyObject = _&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
DirectCast(e.Row.DataItem, MyObject)
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
' get the CascadingDropDowns&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
Dim _ajxState As CascadingDropDown = _&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
DirectCast(e.Row.FindControl("ajxState"), CascadingDropDown)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
Dim _ajxZipcode As CascadingDropDown = _&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
DirectCast(e.Row.FindControl("ajxZipCode"), CascadingDropDown)
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
' ddl population should be handled by the Ajax&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
' ServiceMethod of the CascadingDropDown
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
' select the appropriate item&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
_ajxState.SelectedValue = _myObject.StateAbbreviation&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
_ajxZipCode.SelectedValue = _myObject.ZipCode
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; End If&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; End If&lt;br&gt;
End Sub
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.myfriedmind.com/techBlog/aggbug.ashx?id=52f2adba-43f8-44ce-83ce-3312677761d6" /&gt;</description>
      <comments>http://www.myfriedmind.com/techBlog/CommentView,guid,52f2adba-43f8-44ce-83ce-3312677761d6.aspx</comments>
      <category>Ajax</category>
      <category>c#</category>
      <category>Coding Tricks</category>
      <category>VB.Net</category>
    </item>
    <item>
      <trackback:ping>http://www.myfriedmind.com/techBlog/Trackback.aspx?guid=80712240-5305-49d4-aefa-771ef499f69f</trackback:ping>
      <pingback:server>http://www.myfriedmind.com/techBlog/pingback.aspx</pingback:server>
      <pingback:target>http://www.myfriedmind.com/techBlog/PermaLink,guid,80712240-5305-49d4-aefa-771ef499f69f.aspx</pingback:target>
      <dc:creator>papabear</dc:creator>
      <wfw:comment>http://www.myfriedmind.com/techBlog/CommentView,guid,80712240-5305-49d4-aefa-771ef499f69f.aspx</wfw:comment>
      <wfw:commentRss>http://www.myfriedmind.com/techBlog/SyndicationService.asmx/GetEntryCommentsRss?guid=80712240-5305-49d4-aefa-771ef499f69f</wfw:commentRss>
      <slash:comments>2</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
          <em>
            <font color="#ff0000">Note: special thanks to Thomas who catches my error in using
QueryString vs url hash - I have made the appropriate changes in this entry...</font>
          </em>
        </p>
        <p>
Part 1 - <a href="http://www.myfriedmind.com/techBlog/2009/06/30/AjaxHistoryAHowToPart1.aspx"><font color="#5c80b1">Introduction</font></a><br />
Part 2 - <a href="http://www.myfriedmind.com/techBlog/2009/07/01/AjaxHistoryAHowToPart2ABasicExample.aspx"><font color="#5c80b1">Basic
Example</font></a><br />
Part 3 - <a href="http://www.myfriedmind.com/techBlog/2009/07/09/AjaxHistoryAHowToPart3ComplexExampleC.aspx"><font color="#5c80b1">Complex
Example</font></a><br />
Part 4 - <a href="http://www.myfriedmind.com/techBlog/2009/07/09/AjaxHistoryAHowToPart4FinalNotes.aspx"><font color="#5c80b1">Final
Notes</font></a><br />
Bonus - <a href="http://www.myfriedmind.com/techBlog/2009/05/20/AjaxHistoryAndTheMementoPattern.aspx"><font color="#5c80b1">Ajax
History and the Memento Pattern</font></a><br />
Extra Bonus - <a href="http://www.myfriedmind.com/techBlog/2009/09/21/Opera9x10xFailingOnAjaxHistoryAndTheHackToFixIt.aspx"><font color="#5c80b1">Issues
with Opera</font></a></p>
        <p>
Recently while watching a <a href="http://msevents.microsoft.com/CUI/WebCastEventDetails.aspx?culture=en-US&amp;EventID=1032414968">geekspeak
on Ajax history</a> it struck me that it reminded me strongly of a Memento pattern.
I mentioned this to Glen Gordon and he recommended I write a blog on it, so without
further ado...
</p>
        <p>
First off, a little background. Maintaining history has been one of the holy grails
of Ajax since it began. It is a wonderful feeling to produce a zippy, intiutive site
that has fantastic UI, but once someone hits the "back" button everything goes down
the tube. The reason is simple, browsers were created in the time before, even before
Javascript, much less XML. Back then the "back" button, or any sort of history action,
brought you back not to your last action but to the last page that fully loaded.
</p>
        <p>
To give a parallel, for anyone who has used the "undo" command in whatever program,
what it does is "undo" the last action that you did. Imagine typing for hours in Word,
clicking "undo", and having it wipe out EVERYTHING that you had just done, not just
the last little action. No one would want that, but this is what the "back" key effectively
did by default. Hence, the quest to maintain Ajax history. Wouldn't it be nice if
the "back" key, or other "back" command acted as an "undo" vs a true "back to the
previous page"?
</p>
        <p>
In addition, what if after working on a page (say a maps page) that uses Ajax, you
want to send someone the link. The option is to use a URL, but since Ajax by default
modified the page but not the URL, all that work would be useless. You would think
you were sending them a map to your cabin by the lake, they would simply get the default
map of the world. Not good.
</p>
        <p>
There have been ways to resolve this even before .net 3.5 came out. One merely has
to look at some of the larger Ajax enabled sites (such as google maps) to see this,
but this is such a constant and complex requirement in almost any Ajax development
that it is only logical that someone develop a abstractive pattern to simplify and
standardize it. The 3.5 framework does this, one of many reason it makes me squeal
like schoolgirl. But what is especially fun to look at is how it does it, specifically
what pattern was chosen. The pattern, which is extremely logical to choose, is akin
to the Memento pattern.
</p>
        <p>
I won't go into <a href="http://en.wikipedia.org/wiki/Design_pattern_%28computer_science%29">Design
Patterns </a>here. If you are not sure, follow this <a href="http://en.wikipedia.org/wiki/Design_pattern_%28computer_science%29">link</a>, <a href="http://en.wikipedia.org/wiki/Design_Patterns_%28book%29">buy
the book</a>, <a href="http://art.cafepress.com/item/black-gof-design-patterns-poster/238970064">get
the poster</a>. I want to focus on one pattern, the Memento pattern and how it relates
to Ajax history in the hopes that it will illumine your coding.
</p>
        <p>
The Memento pattern requires two players, commonly refered to as the Originator and
the Caretaker. To clarify the interaction:
</p>
        <ol>
          <li>
The Caretaker is going to change the Originator in some way but the Originator needs
to be able to undo the change. 
</li>
          <li>
The Caretaker receives a small "memento" object and stores it (hence the Caretaker
name). 
</li>
          <li>
The Caretaker then changes the Originator.</li>
        </ol>
        <p>
If the change needs to be undone:
</p>
        <ol>
          <li>
The Caretaker returns the "memento" object to the Originator. 
</li>
          <li>
The Originator uses the "memento" object to undo the change.</li>
        </ol>
        <p>
But it is also critical to understand about the "memento".
</p>
        <ul>
          <li>
The "memento" is an opaque object, meaning the Caretaker can not change it 
</li>
          <li>
The "memento" is small, it is not the entire Originator, merely the minimal information
needed to rollback state 
</li>
          <li>
The Originator is the one who packages and unpackages the "memento" 
</li>
          <li>
The Originator is the one who rolls back state (ie, the Caretaker does not modify
the Originator to roll it back)</li>
        </ul>
        <p>
So how does this apply to how .Net does Ajax history? In short, .Net uses the URL
of the page as the "memento", the History as the Caretaker, with the code you write
in the framework acting as the Originator.
</p>
        <ol>
          <li>
The Ajax action is going to change the webpage someway. 
</li>
          <li>
The current hash is already stored 
</li>
          <li>
The Ajax action makes the change and alters the hash</li>
        </ol>
        <p>
If the change needs to be undone:
</p>
        <ol>
          <li>
The hash (in the URL) that was from the previous page (the rollback
state) is returned. 
</li>
          <li>
The code that YOU wrote rollsback the state.</li>
        </ol>
        <p>
In this case the memento has these characteristics
</p>
        <ul>
          <li>
The "memento" is a url which is unchanged by the Caretaker (browser) 
</li>
          <li>
The "memento" is small (you should make sure of this) 
</li>
          <li>
The framework writes the URL that you need and allows you to access it 
</li>
          <li>
Your code is what rolls back state 
</li>
        </ul>
        <p>
So, what does this mean? Basically the key point is that you can apply the practices
that you have in place for working with the Memento pattern to working with Ajax history.
Chief among these is that the "memento" should be small! Do not try to squeeze too
much into your URL. It is not pretty and there are limits! Instead pare down to the
minimum of what you need to be able to restore state.
</p>
        <p>
One major bonus is that this not merely allows rollback, but enables your users to
use URLs to return an Ajax-enabled page on which certain steps have already been taken.
This is AMAZING!!!!!!! And compared to how we used to have to do it, it is like a
walk in the park! 
</p>
        <p>
 
</p>
        <img width="0" height="0" src="http://www.myfriedmind.com/techBlog/aggbug.ashx?id=80712240-5305-49d4-aefa-771ef499f69f" />
      </body>
      <title>Ajax history and the Memento pattern</title>
      <guid isPermaLink="false">http://www.myfriedmind.com/techBlog/PermaLink,guid,80712240-5305-49d4-aefa-771ef499f69f.aspx</guid>
      <link>http://www.myfriedmind.com/techBlog/2009/05/20/AjaxHistoryAndTheMementoPattern.aspx</link>
      <pubDate>Wed, 20 May 2009 17:17:13 GMT</pubDate>
      <description>&lt;p&gt;
&lt;em&gt;&lt;font color=#ff0000&gt;Note: special thanks to Thomas who catches my error in using
QueryString vs url hash - I have made the appropriate changes in this entry...&lt;/font&gt;&lt;/em&gt;
&lt;/p&gt;
&lt;p&gt;
Part 1 - &lt;a href="http://www.myfriedmind.com/techBlog/2009/06/30/AjaxHistoryAHowToPart1.aspx"&gt;&lt;font color=#5c80b1&gt;Introduction&lt;/font&gt;&lt;/a&gt;
&lt;br&gt;
Part 2 - &lt;a href="http://www.myfriedmind.com/techBlog/2009/07/01/AjaxHistoryAHowToPart2ABasicExample.aspx"&gt;&lt;font color=#5c80b1&gt;Basic
Example&lt;/font&gt;&lt;/a&gt;
&lt;br&gt;
Part 3 - &lt;a href="http://www.myfriedmind.com/techBlog/2009/07/09/AjaxHistoryAHowToPart3ComplexExampleC.aspx"&gt;&lt;font color=#5c80b1&gt;Complex
Example&lt;/font&gt;&lt;/a&gt;
&lt;br&gt;
Part 4 - &lt;a href="http://www.myfriedmind.com/techBlog/2009/07/09/AjaxHistoryAHowToPart4FinalNotes.aspx"&gt;&lt;font color=#5c80b1&gt;Final
Notes&lt;/font&gt;&lt;/a&gt;
&lt;br&gt;
Bonus - &lt;a href="http://www.myfriedmind.com/techBlog/2009/05/20/AjaxHistoryAndTheMementoPattern.aspx"&gt;&lt;font color=#5c80b1&gt;Ajax
History and the Memento Pattern&lt;/font&gt;&lt;/a&gt;
&lt;br&gt;
Extra Bonus - &lt;a href="http://www.myfriedmind.com/techBlog/2009/09/21/Opera9x10xFailingOnAjaxHistoryAndTheHackToFixIt.aspx"&gt;&lt;font color=#5c80b1&gt;Issues
with Opera&lt;/font&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
Recently while watching a &lt;a href="http://msevents.microsoft.com/CUI/WebCastEventDetails.aspx?culture=en-US&amp;amp;EventID=1032414968"&gt;geekspeak
on Ajax history&lt;/a&gt; it struck me that it reminded me strongly of a Memento pattern.
I mentioned this to Glen Gordon and he recommended I write a blog on it, so without
further ado...
&lt;/p&gt;
&lt;p&gt;
First off, a little background. Maintaining history has been one of the holy grails
of Ajax since it began. It is a wonderful feeling to produce a zippy, intiutive site
that has fantastic UI, but once someone hits the "back" button everything goes down
the tube. The reason is simple, browsers were created in the time before, even before
Javascript, much less XML. Back then the "back" button, or any sort of history action,
brought you back not to your last action but to the last page that fully loaded.
&lt;/p&gt;
&lt;p&gt;
To give a parallel, for anyone who has used the "undo" command in whatever program,
what it does is "undo" the last action that you did. Imagine typing for hours in Word,
clicking "undo", and having it wipe out EVERYTHING that you had just done, not just
the last little action. No one would want that, but this is what the "back" key effectively
did by default. Hence, the quest to maintain Ajax history. Wouldn't it be nice if
the "back" key, or other "back" command acted as an "undo" vs a true "back to the
previous page"?
&lt;/p&gt;
&lt;p&gt;
In addition, what if after working on a page (say a maps page) that uses Ajax, you
want to send someone the link. The option is to use a URL, but since Ajax by default
modified the page but not the URL, all that work would be useless. You would think
you were sending them a map to your cabin by the lake, they would simply get the default
map of the world. Not good.
&lt;/p&gt;
&lt;p&gt;
There have been ways to resolve this even before .net 3.5 came out. One merely has
to look at some of the larger Ajax enabled sites (such as google maps) to see this,
but this is such a constant and complex requirement in almost any Ajax development
that it is only logical that someone develop a abstractive pattern to simplify and
standardize it. The 3.5 framework does this, one of many reason it makes me squeal
like schoolgirl. But what is especially fun to look at is how it does it, specifically
what pattern was chosen. The pattern, which is extremely logical to choose, is akin
to the Memento pattern.
&lt;/p&gt;
&lt;p&gt;
I won't go into &lt;a href="http://en.wikipedia.org/wiki/Design_pattern_%28computer_science%29"&gt;Design
Patterns &lt;/a&gt;here. If you are not sure, follow this &lt;a href="http://en.wikipedia.org/wiki/Design_pattern_%28computer_science%29"&gt;link&lt;/a&gt;, &lt;a href="http://en.wikipedia.org/wiki/Design_Patterns_%28book%29"&gt;buy
the book&lt;/a&gt;, &lt;a href="http://art.cafepress.com/item/black-gof-design-patterns-poster/238970064"&gt;get
the poster&lt;/a&gt;. I want to focus on one pattern, the Memento pattern and how it relates
to Ajax history in the hopes that it will illumine your coding.
&lt;/p&gt;
&lt;p&gt;
The Memento pattern requires two players, commonly refered to as the Originator and
the Caretaker. To clarify the interaction:
&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
The Caretaker is going to change the Originator in some way but the Originator needs
to be able to undo the change. 
&lt;li&gt;
The Caretaker receives a small&amp;nbsp;"memento" object and stores it (hence the Caretaker
name). 
&lt;li&gt;
The Caretaker then changes the Originator.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;
If the change needs to be undone:
&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
The Caretaker returns the "memento" object to the Originator. 
&lt;li&gt;
The Originator uses the "memento" object to undo the change.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;
But it is also critical to understand about the "memento".
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
The "memento" is an opaque object, meaning the Caretaker can not change it 
&lt;li&gt;
The "memento" is small, it is not the entire Originator, merely the minimal information
needed to rollback state 
&lt;li&gt;
The Originator is the one who packages and unpackages the "memento" 
&lt;li&gt;
The Originator is the one who rolls back state (ie, the Caretaker does not modify
the Originator to roll it back)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
So how does this apply to how .Net does Ajax history? In short, .Net uses the URL
of the page as the "memento", the History as the Caretaker, with the code you write
in the framework acting as the Originator.
&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
The Ajax action is going to change the webpage someway. 
&lt;li&gt;
The current hash is already stored 
&lt;li&gt;
The Ajax action makes the change and alters the hash&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;
If the change needs to be undone:
&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
The&amp;nbsp;hash&amp;nbsp;(in the URL)&amp;nbsp;that was from the previous page (the rollback
state) is returned. 
&lt;li&gt;
The code that YOU wrote rollsback the state.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;
In this case the memento has these characteristics
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
The "memento" is a url which is unchanged by the Caretaker (browser) 
&lt;li&gt;
The "memento" is small (you should make sure of this) 
&lt;li&gt;
The&amp;nbsp;framework writes the URL that you need and allows you to access it 
&lt;li&gt;
Your code&amp;nbsp;is what&amp;nbsp;rolls back state 
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
So, what does this mean? Basically the key point is that you can apply the practices
that you have in place for working with the Memento pattern to working with Ajax history.
Chief among these is that the "memento" should be small! Do not try to squeeze too
much into your URL. It is not pretty and there are limits! Instead pare down to the
minimum of what you need to be able to restore state.
&lt;/p&gt;
&lt;p&gt;
One major bonus is that this not merely allows rollback, but enables your users to
use URLs to return an Ajax-enabled page on which certain steps have already been taken.
This is AMAZING!!!!!!! And compared to how we used to have to do it, it is like a
walk in the park! 
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.myfriedmind.com/techBlog/aggbug.ashx?id=80712240-5305-49d4-aefa-771ef499f69f" /&gt;</description>
      <comments>http://www.myfriedmind.com/techBlog/CommentView,guid,80712240-5305-49d4-aefa-771ef499f69f.aspx</comments>
      <category>Ajax</category>
      <category>Asp.Net</category>
      <category>c#</category>
      <category>Coding Tricks</category>
      <category>Design Patterns</category>
      <category>VB.Net</category>
    </item>
    <item>
      <trackback:ping>http://www.myfriedmind.com/techBlog/Trackback.aspx?guid=e6eef807-abf5-44cb-a9ce-f789d97514ee</trackback:ping>
      <pingback:server>http://www.myfriedmind.com/techBlog/pingback.aspx</pingback:server>
      <pingback:target>http://www.myfriedmind.com/techBlog/PermaLink,guid,e6eef807-abf5-44cb-a9ce-f789d97514ee.aspx</pingback:target>
      <dc:creator>papabear</dc:creator>
      <wfw:comment>http://www.myfriedmind.com/techBlog/CommentView,guid,e6eef807-abf5-44cb-a9ce-f789d97514ee.aspx</wfw:comment>
      <wfw:commentRss>http://www.myfriedmind.com/techBlog/SyndicationService.asmx/GetEntryCommentsRss?guid=e6eef807-abf5-44cb-a9ce-f789d97514ee</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Recently someone asked about using Ajax on Sharepoint. I should note that a number
of resources are out there on this which I used, so - as brilliant as I am &lt;g&gt;
- the credit for this has to go to those who have gone before...
</p>
        <p>
Like a lot of people I have been working on both since their betas, so whether or
not I should install Ajax on Sharepoint was a no-brainer. Unfortunately, when Sharepoint
2007 first came out it was the very end of 2006 and Ajax was not officially released
until January 23, 2007. As a result, in order to utilize Ajax on Sharepoint (pre-SP1)
you needed to jump through a whole host of hoops. This is not to say it could not
be done, merely that it was a cumbersome and painful process.
</p>
        <p class="step">
Step 1: Install SP1 on Sharepoint
</p>
        <p>
Luckily the folks on the Sharepoint team made that a priority, and even though we
had to wait a bit for it, they did include 'Ajax support' in SP1. So the first step
to using Ajax on Sharepoint 2007 is, quite simply, install Sharepoint 2007 SP1. You
can do it without SP1, but really, why would you?
</p>
        <p>
Note that simply installing SP1 does not automatically turn on Ajax (there are more
steps) but it removes some of the bugs that popped up.
</p>
        <p class="step">
Step 2: (Recommended): Install Asp.Net framework 3.5 SP1
</p>
        <p>
The next thing that I strongly suggest is that you upgrade to .Net 3.5 (sp1). Why?
Simply because if you are going to be doing any Ajax you will want to. 
</p>
        <ul>
          <li>
It includes it directly in the framework, no need to install it separately 
</li>
          <li>
It has awesome debugging - you will still use Fiddler, but less often 
</li>
          <li>
Intellisense 
</li>
          <li>
Much, much easier means of creating a 'tracking history' of Ajax calls</li>
        </ul>
        <p>
If you decide to install .Net 3.5, note that you will not see a Web Service Extension
for it in the IIS Manager. This is not a flaw, this is because 3.5 is an extension
of 2.0. Let me state that again - if you install 3.5 you will actually use 2.0 as
the .Net version.
</p>
        <p>
Doing these two steps does not mean that Ajax is automatically up and running, just
that the necessary dlls have been put into the GAC.
</p>
        <p>
One final note - if you install 3.5 you will be using version 3.5.0.0 of System.Web.UI.*
in a number of your web.config entries. If you are using an earlier version, make
sure to check the GAC and find out what the specific version is. Most of the rest
of the steps involve modifying your web.config, so make sure you know your System.Web.UI.Extensions
version before you being
</p>
        <p class="step">
Step 2a: Make a back up of your web.config
</p>
        <p>
We are all good techies here, right? Which means we are all paranoid, right? Never,
ever modify your web.config unless you have a rollback copy at hand. Remember, paranoia
is a job-requirement.
</p>
        <p class="step">
Step 3: Add the system.web.extensions sectionGroups to the configSections
of your web.config
</p>
        <p>
If you are not familiar with Sharepoint, this will be located in your c:\inetpub\wwwroot\VirtualDirectories\wss\{your
site's port here}. So if you have your Sharepoint on port 8080 your web.config will
be located at c:\inetpub\wwwroot\VirtualDirectories\wss\8080. Remember to make a copy
of it like a good, paranoid nerd. Also, I tend to remark what I am adding and why
to my web.config, but you don't have to.
</p>
        <p>
Add this in the &lt;configSections&gt; portion, which should be at the top. You will
already see other &lt;sectionGroup... &gt; entries there, just add this one at the
end (above the &lt;/configSections&gt; entry), wrapped for readability...
</p>
        <font color="#0000ff" size="2">
          <p>
&lt;!--
</p>
        </font>
        <font color="#008000" size="2"> ======= Added for Ajax start ====== </font>
        <font color="#0000ff" size="2">--&gt;<br />
&lt;</font>
        <font color="#a31515" size="2">sectionGroup</font>
        <font color="#0000ff" size="2">
        </font>
        <font color="#ff0000" size="2">name</font>
        <font color="#0000ff" size="2">=</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2">system.web.extensions</font>
        <font color="#000000" size="2">" 
<br /></font>
        <font color="#ff0000" size="2">         
type</font>
        <font color="#0000ff" size="2">=</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2">System.Web.Configuration.SystemWebExtensionsSectionGroup, 
<br />
          System.Web.Extensions, Version=3.5.0.0,
Culture=neutral,  
<br />
          </font>
        <font color="#0000ff" size="2">PublicKeyToken=31bf3856ad364e35</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2">&gt;<br />
     &lt;</font>
        <font color="#a31515" size="2">sectionGroup</font>
        <font color="#0000ff" size="2">
        </font>
        <font color="#ff0000" size="2">name</font>
        <font color="#0000ff" size="2">=</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2">scripting</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2">  
<br />
              </font>
        <font color="#ff0000" size="2">type</font>
        <font color="#0000ff" size="2">=</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2">System.Web.Configuration.ScriptingSectionGroup, 
<br />
              </font>
        <font color="#0000ff" size="2">System.Web.Extensions,
Version=3.5.0.0,  <br />
              Culture=neutral,
PublicKeyToken=31bf3856ad364e35</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2">&gt;<br />
         &lt;</font>
        <font color="#a31515" size="2">section</font>
        <font color="#0000ff" size="2">
        </font>
        <font color="#ff0000" size="2">name</font>
        <font color="#0000ff" size="2">=</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2">scriptResourceHandler</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2">
          <br />
                </font>
        <font color="#ff0000" size="2">type</font>
        <font color="#0000ff" size="2">=</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2">System.Web.Configuration.ScriptingScriptResourceHandlerSection,<br />
                 System.Web.Extensions, Version=3.5.0.0,
Culture=neutral, 
<br />
                
PublicKeyToken=31bf3856ad364e35</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2">
        </font>
        <font color="#ff0000" size="2">requirePermission</font>
        <font color="#0000ff" size="2">=</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2">false</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2"> <br />
                 </font>
        <font color="#ff0000" size="2">allowDefinition</font>
        <font color="#0000ff" size="2">=</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2">MachineToApplication</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2"> /&gt;<br /></font>
        <font color="#0000ff" size="2">         &lt;</font>
        <font color="#a31515" size="2">sectionGroup</font>
        <font color="#0000ff" size="2">
        </font>
        <font color="#ff0000" size="2">name</font>
        <font color="#0000ff" size="2">=</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2">webServices</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2">
          <br />
                 </font>
        <font color="#ff0000" size="2">type</font>
        <font color="#0000ff" size="2">=</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2">System.Web.Configuration.ScriptingWebServicesSectionGroup, 
<br />
                
System.Web.Extensions, Version=3.5.0.0, Culture=neutral, 
<br />
                
PublicKeyToken=31bf3856ad364e35</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2">&gt;<br />
             &lt;</font>
        <font color="#a31515" size="2">section</font>
        <font color="#0000ff" size="2">
        </font>
        <font color="#ff0000" size="2">name</font>
        <font color="#0000ff" size="2">=</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2">jsonSerialization</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2">
          <br />
                     </font>
        <font color="#ff0000" size="2">type</font>
        <font color="#0000ff" size="2">=</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2">System.Web.Configuration.ScriptingJsonSerializationSection, 
<br />
                    
System.Web.Extensions, Version=3.5.0.0, Culture=neutral, 
<br />
                    
PublicKeyToken=31bf3856ad364e35</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2">
        </font>
        <font color="#ff0000" size="2">requirePermission</font>
        <font color="#0000ff" size="2">=</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2">false</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2">
          <br />
                     </font>
        <font color="#ff0000" size="2">allowDefinition</font>
        <font color="#0000ff" size="2">=</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2">Everywhere</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2"> /&gt;<br />
             </font>
        <font color="#0000ff" size="2">&lt;</font>
        <font color="#a31515" size="2">section</font>
        <font color="#0000ff" size="2">
        </font>
        <font color="#ff0000" size="2">name</font>
        <font color="#0000ff" size="2">=</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2">profileService</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2">
          <br />
                    </font>
        <font color="#ff0000" size="2">type</font>
        <font color="#0000ff" size="2">=</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2">System.Web.Configuration.ScriptingProfileServiceSection, <br />
                    System.Web.Extensions,
Version=3.5.0.0, Culture=neutral, 
<br />
                   
PublicKeyToken=31bf3856ad364e35</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2">
        </font>
        <font color="#ff0000" size="2">requirePermission</font>
        <font color="#0000ff" size="2">=</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2">false</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2">
          <br />
                    </font>
        <font color="#ff0000" size="2">allowDefinition</font>
        <font color="#0000ff" size="2">=</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2">MachineToApplication</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2"> /&gt;<br />
             </font>
        <font color="#0000ff" size="2">&lt;</font>
        <font color="#a31515" size="2">section</font>
        <font color="#0000ff" size="2">
        </font>
        <font color="#ff0000" size="2">name</font>
        <font color="#0000ff" size="2">=</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2">authenticationService</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2">
          <br />
                    </font>
        <font color="#ff0000" size="2">type</font>
        <font color="#0000ff" size="2">=</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2">System.Web.Configuration.ScriptingAuthenticationServiceSection, 
<br />
                   
System.Web.Extensions, Version=3.5.0.0, Culture=neutral, 
<br />
                   
PublicKeyToken=31bf3856ad364e35</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2">
        </font>
        <font color="#ff0000" size="2">requirePermission</font>
        <font color="#0000ff" size="2">=</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2">false</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2">
          <br />
                    </font>
        <font color="#ff0000" size="2">allowDefinition</font>
        <font color="#0000ff" size="2">=</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2">MachineToApplication</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2"> /&gt;<br />
          &lt;/</font>
        <font color="#a31515" size="2">sectionGroup</font>
        <font color="#0000ff" size="2">&gt;<br />
     &lt;/</font>
        <font color="#a31515" size="2">sectionGroup</font>
        <font color="#0000ff" size="2">&gt;<br />
&lt;/</font>
        <font color="#a31515" size="2">sectionGroup</font>
        <font color="#0000ff" size="2">&gt;<br />
&lt;!--</font>
        <font color="#008000" size="2"> ======= Added for Ajax end ====== </font>
        <font color="#0000ff" size="2">--&gt;</font>
        <p class="step">
Step 4: Add System.Web.Extensions as a "SafeControl" to your web.config
</p>
        <p>
SafeControls are those assemblies that should be considered "Safe" by Sharepoint.
Do a quick find for &lt;SafeControls&gt; and you will see a whole lotta them. Simply
add this line to the bottom, above the &lt;/SafeControls&gt;. 
</p>
        <p>
NOTE!!! If you are using a different version than .net 3.5, make sure that you verify
what version it is in the GAC. This needs to be specified in the "Version" section
or Sharepoint will throw an error. Because I am using 3.5, my version is 3.5.0.0
</p>
        <font color="#0000ff" size="2">
          <p>
&lt;!--
</p>
        </font>
        <font color="#008000" size="2"> ====== Added for Ajax  ====== </font>
        <font color="#0000ff" size="2">--&gt;<br />
&lt;</font>
        <font color="#a31515" size="2">SafeControl</font>
        <font color="#0000ff" size="2">
        </font>
        <font color="#ff0000" size="2">Assembly</font>
        <font color="#0000ff" size="2">=</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2">System.Web.Extensions,
Version=3.5.0.0, 
<br />
        </font>
        <font color="#0000ff" size="2">Culture=neutral,
PublicKeyToken=31bf3856ad364e35</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2">  
<br />
        </font>
        <font color="#ff0000" size="2">Namespace</font>
        <font color="#0000ff" size="2">=</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2">System.Web.UI</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2">
        </font>
        <font color="#ff0000" size="2">TypeName</font>
        <font color="#0000ff" size="2">=</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2">*</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2">
        </font>
        <font color="#ff0000" size="2">Safe</font>
        <font color="#0000ff" size="2">=</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2">True</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2"> /&gt;
</font>
        <p class="step">
Step 5: Add the needed "verbs" to your &lt;httpHandlers&gt;
</p>
        <p>
Note that this is NOT the &lt;httpModules&gt; section. There should already be some
entries there, so just stick this at the end, above the &lt;/httpHandlers&gt; line....
</p>
        <font color="#0000ff" size="2">
          <p>
&lt;!--
</p>
        </font>
        <font color="#008000" size="2"> ====== Added for Ajax start ====== </font>
        <font color="#0000ff" size="2">--&gt;<br />
&lt;</font>
        <font color="#a31515" size="2">add</font>
        <font color="#0000ff" size="2">
        </font>
        <font color="#ff0000" size="2">verb</font>
        <font color="#0000ff" size="2">=</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2">*</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2">
        </font>
        <font color="#ff0000" size="2">path</font>
        <font color="#0000ff" size="2">=</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2">*.asmx</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2">
        </font>
        <font color="#ff0000" size="2">validate</font>
        <font color="#0000ff" size="2">=</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2">false</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2">
          <br />
        </font>
        <font color="#ff0000" size="2">type</font>
        <font color="#0000ff" size="2">=</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2">System.Web.Script.Services.ScriptHandlerFactory, 
<br />
        System.Web.Extensions, Version=3.5.0.0,
Culture=neutral, 
<br />
        PublicKeyToken=31bf3856ad364e35</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2"> /&gt;<br />
&lt;</font>
        <font color="#a31515" size="2">add</font>
        <font color="#0000ff" size="2">
        </font>
        <font color="#ff0000" size="2">verb</font>
        <font color="#0000ff" size="2">=</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2">*</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2">
        </font>
        <font color="#ff0000" size="2">path</font>
        <font color="#0000ff" size="2">=</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2">*_AppService.axd</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2">
        </font>
        <font color="#ff0000" size="2">validate</font>
        <font color="#0000ff" size="2">=</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2">false</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2">
          <br />
        </font>
        <font color="#ff0000" size="2">type</font>
        <font color="#0000ff" size="2">=</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2">System.Web.Script.Services.ScriptHandlerFactory, <br />
        System.Web.Extensions, Version=3.5.0.0, 
<br />
        Culture=neutral, PublicKeyToken=31bf3856ad364e35</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2"> /&gt;<br />
&lt;</font>
        <font color="#a31515" size="2">add</font>
        <font color="#0000ff" size="2">
        </font>
        <font color="#ff0000" size="2">verb</font>
        <font color="#0000ff" size="2">=</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2">GET,HEAD</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2">
        </font>
        <font color="#ff0000" size="2">path</font>
        <font color="#0000ff" size="2">=</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2">ScriptResource.axd</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2">
          <br />
        </font>
        <font color="#ff0000" size="2">type</font>
        <font color="#0000ff" size="2">=</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2">System.Web.Handlers.ScriptResourceHandler, <br />
        System.Web.Extensions, Version=3.5.0.0,
Culture=neutral, 
<br />
        PublicKeyToken=31bf3856ad364e35</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2">
        </font>
        <font color="#ff0000" size="2">validate</font>
        <font color="#0000ff" size="2">=</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2">false</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2"> /&gt;<br />
&lt;!--</font>
        <font color="#008000" size="2"> ====== Added for Ajax end ====== </font>
        <font color="#0000ff" size="2">--&gt;</font>
        <p class="step">
Step 6: Add the &lt;controls&gt; reference to the &lt;pages...&gt; section of the
web.config
</p>
        <p>
This will enable your pages to recognize the controls that come with Ajax (such as
the ScriptManager, etc). Locate the &lt;pages ...&gt; section and add this at the
end above the &lt;/pages&gt; entry. Again, keep an eye on the Version.
</p>
        <font color="#0000ff" size="2">
          <p>
&lt;!--
</p>
        </font>
        <font color="#008000" size="2"> ====== Added for Ajax  ====== </font>
        <font color="#0000ff" size="2">--&gt;<br />
&lt;</font>
        <font color="#a31515" size="2">controls</font>
        <font color="#0000ff" size="2">&gt;<br />
    &lt;</font>
        <font color="#a31515" size="2">add</font>
        <font color="#0000ff" size="2">
        </font>
        <font color="#ff0000" size="2">tagPrefix</font>
        <font color="#0000ff" size="2">=</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2">asp</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2">
        </font>
        <font color="#ff0000" size="2">namespace</font>
        <font color="#0000ff" size="2">=</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2">System.Web.UI</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2">
          <br />
          </font>
        <font color="#ff0000" size="2">assembly</font>
        <font color="#0000ff" size="2">=</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2">System.Web.Extensions,
Version=3.5.0.0, 
<br />
          Culture=neutral, PublicKeyToken=31bf3856ad364e35</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2"> /&gt;<br /></font>
        <font color="#0000ff" size="2">&lt;/</font>
        <font color="#a31515" size="2">controls</font>
        <font color="#0000ff" size="2">&gt;<br /></font>
        <font color="#0000ff" size="2">&lt;!--<font color="#008000" size="2"> ======
Added for Ajax  end ====== </font><font color="#0000ff" size="2">--&gt;</font></font>
        <p class="step">
Step 7: Add this at the very end of your web.config, just above the &lt;/configuration&gt;
line
</p>
        <p>
Of course you could stick it somewhere else, but let's be neat here... This is the
section that first thing that you put into your web.config (the &lt;sectionGroup...&gt;
referenced. There is documentation out there on sectionGroups, and they are very handy,
if you get interested. I have left a lot of commented lines in there for if you need
them. And, once more repeat after me, if you are not using 3.5, check the Version!
</p>
        <font color="#0000ff" size="2">
          <p>
&lt;!--
</p>
        </font>
        <font color="#008000" size="2"> ====== Added for Ajax start ====== </font>
        <font color="#0000ff" size="2">--&gt;<br />
&lt;</font>
        <font color="#a31515" size="2">system.web.extensions</font>
        <font color="#0000ff" size="2">&gt;<br />
    &lt;</font>
        <font color="#a31515" size="2">scripting</font>
        <font color="#0000ff" size="2">&gt;<br />
        &lt;</font>
        <font color="#a31515" size="2">webServices</font>
        <font color="#0000ff" size="2">&gt;<br />
            &lt;!--</font>
        <font color="#008000" size="2"> Uncomment
this line to enable the authentication 
<br />
               
service. Include requireSSL="true" if appropriate. </font>
        <font color="#0000ff" size="2">--&gt;<br />
              
 &lt;!-- </font>
        <font color="#008000" size="2">&lt;authenticationService enabled="true"
requireSSL = "true|false"/&gt; </font>
        <font color="#0000ff" size="2">--&gt;<br />
             &lt;!--</font>
        <font color="#008000" size="2"> Uncomment
these lines to enable the profile service. 
<br />
                  
To allow profile properties to be retrieved and modified <br />
                   in
ASP.NET AJAX applications, you need to add each property 
<br />
                  
name to the readAccessProperties and <br />
                   writeAccessProperties
attributes. </font>
        <font color="#0000ff" size="2">--&gt;<br />
               
&lt;!-- </font>
        <font color="#008000" size="2">&lt;profileService enabled="true" 
<br />
                          
readAccessProperties="propertyname1,propertyname2" 
<br />
                          
writeAccessProperties="propertyname1,propertyname2" /&gt; </font>
        <font color="#0000ff" size="2">--&gt;<br />
 </font>
        <font color="#0000ff" size="2">       &lt;/</font>
        <font color="#a31515" size="2">webServices</font>
        <font color="#0000ff" size="2">&gt;<br />
        &lt;!-- </font>
        <font color="#008000" size="2">&lt;scriptResourceHandler
enableCompression="true" enableCaching="true" /&gt; </font>
        <font color="#0000ff" size="2">--&gt;<br />
    </font>
        <font color="#0000ff" size="2">&lt;/</font>
        <font color="#a31515" size="2">scripting</font>
        <font color="#0000ff" size="2">&gt;<br />
&lt;/</font>
        <font color="#a31515" size="2">system.web.extensions</font>
        <font color="#0000ff" size="2">&gt;<br />
&lt;</font>
        <font color="#a31515" size="2">system.webServer</font>
        <font color="#0000ff" size="2">&gt;<br />
    &lt;</font>
        <font color="#a31515" size="2">validation</font>
        <font color="#0000ff" size="2">
        </font>
        <font color="#ff0000" size="2">validateIntegratedModeConfiguration</font>
        <font color="#0000ff" size="2">=</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2">false</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2"> /&gt;<br />
        &lt;</font>
        <font color="#a31515" size="2">modules</font>
        <font color="#0000ff" size="2">&gt;<br />
            &lt;</font>
        <font color="#a31515" size="2">add</font>
        <font color="#0000ff" size="2">
        </font>
        <font color="#ff0000" size="2">name</font>
        <font color="#0000ff" size="2">=</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2">ScriptModule</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2">
        </font>
        <font color="#ff0000" size="2">preCondition</font>
        <font color="#0000ff" size="2">=</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2">integratedMode</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2">
          <br />
                </font>
        <font color="#ff0000" size="2">type</font>
        <font color="#0000ff" size="2">=</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2">System.Web.Handlers.ScriptModule, <br />
                System.Web.Extensions,
Version=3.5.0.0, Culture=neutral, <br />
                PublicKeyToken=31bf3856ad364e35</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2"> /&gt;<br />
        &lt;/</font>
        <font color="#a31515" size="2">modules</font>
        <font color="#0000ff" size="2">&gt;<br />
        &lt;</font>
        <font color="#a31515" size="2">handlers</font>
        <font color="#0000ff" size="2">&gt;<br />
            &lt;</font>
        <font color="#a31515" size="2">remove</font>
        <font color="#0000ff" size="2">
        </font>
        <font color="#ff0000" size="2">name</font>
        <font color="#0000ff" size="2">=</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2">WebServiceHandlerFactory-Integrated</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2"> /&gt;<br />
            &lt;</font>
        <font color="#a31515" size="2">add</font>
        <font color="#0000ff" size="2">
        </font>
        <font color="#ff0000" size="2">name</font>
        <font color="#0000ff" size="2">=</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2">ScriptHandlerFactory</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2">
        </font>
        <font color="#ff0000" size="2">verb</font>
        <font color="#0000ff" size="2">=</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2">*</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2">
        </font>
        <font color="#ff0000" size="2">path</font>
        <font color="#0000ff" size="2">=</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2">*.asmx</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2">
          <br />
                  </font>
        <font color="#ff0000" size="2">preCondition</font>
        <font color="#0000ff" size="2">=</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2">integratedMode</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2">
          <br />
                  </font>
        <font color="#ff0000" size="2">type</font>
        <font color="#0000ff" size="2">=</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2">System.Web.Script.Services.ScriptHandlerFactory, 
<br />
                 
System.Web.Extensions, Version=3.5.0.0, Culture=neutral, <br />
                  PublicKeyToken=31bf3856ad364e35</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2"> /&gt;<br />
            &lt;</font>
        <font color="#a31515" size="2">add</font>
        <font color="#0000ff" size="2">
        </font>
        <font color="#ff0000" size="2">name</font>
        <font color="#0000ff" size="2">=</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2">ScriptHandlerFactoryAppServices</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2">
        </font>
        <font color="#ff0000" size="2">verb</font>
        <font color="#0000ff" size="2">=</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2">*</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2">
          <br />
                  </font>
        <font color="#ff0000" size="2">path</font>
        <font color="#0000ff" size="2">=</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2">*_AppService.axd</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2">
        </font>
        <font color="#ff0000" size="2">preCondition</font>
        <font color="#0000ff" size="2">=</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2">integratedMode</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2">
          <br />
                  </font>
        <font color="#ff0000" size="2">type</font>
        <font color="#0000ff" size="2">=</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2">System.Web.Script.Services.ScriptHandlerFactory, 
<br />
                 
System.Web.Extensions, Version=3.5.0.0, Culture=neutral, 
<br />
                 
PublicKeyToken=31bf3856ad364e35</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2"> /&gt;<br />
            &lt;</font>
        <font color="#a31515" size="2">add</font>
        <font color="#0000ff" size="2">
        </font>
        <font color="#ff0000" size="2">name</font>
        <font color="#0000ff" size="2">=</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2">ScriptResource</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2">
        </font>
        <font color="#ff0000" size="2">preCondition</font>
        <font color="#0000ff" size="2">=</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2">integratedMode</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2">
          <br />
                  </font>
        <font color="#ff0000" size="2">verb</font>
        <font color="#0000ff" size="2">=</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2">GET,HEAD</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2">
        </font>
        <font color="#ff0000" size="2">path</font>
        <font color="#0000ff" size="2">=</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2">ScriptResource.axd</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2">
          <br />
                  </font>
        <font color="#ff0000" size="2">type</font>
        <font color="#0000ff" size="2">=</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2">System.Web.Handlers.ScriptResourceHandler, 
<br />
                 
System.Web.Extensions, Version=3.5.0.0, Culture=neutral, 
<br />
                 
PublicKeyToken=31bf3856ad364e35</font>
        <font color="#000000" size="2">"</font>
        <font color="#0000ff" size="2"> /&gt;<br />
        &lt;/</font>
        <font color="#a31515" size="2">handlers</font>
        <font color="#0000ff" size="2">&gt;<br />
&lt;/</font>
        <font color="#a31515" size="2">system.webServer</font>
        <font color="#0000ff" size="2">&gt;<br />
&lt;!--</font>
        <font color="#008000" size="2"> ====== Added for Ajax  end
====== </font>
        <font color="#0000ff" size="2">--&gt;</font>
        <p class="step">
Step 8: Add a ScriptManager to your Master Page
</p>
        <p>
You can always do it dynamically, and I always check in my code to see if it
exists before whatever webpart I am writing loads, but it is much simpler just to
add it on your Master Page. Just stick it below the &lt;form id="Form1"... &gt; entry
:<br /><font color="#0000ff" size="2"><br /></font><font color="#0000ff" size="2">&lt;</font><font color="#a31515" size="2">asp</font><font color="#0000ff" size="2">:</font><font color="#a31515" size="2">ScriptManager</font><font size="2"></font><font color="#ff0000" size="2">runat</font><font color="#0000ff" size="2">="server"</font><font size="2"></font><font color="#ff0000" size="2">ID</font><font color="#0000ff" size="2">="ScriptManager1
/</font><font color="#0000ff" size="2">&gt;</font></p>
        <p>
Please note that there are a LOT of other goodies you can add to your ScriptManager,
especially in .net 3.5, so feel free to expand it. Just make sure it is in there.
</p>
        <p class="step">
Step 9: Write Ajax pages (or webparts).
</p>
        <p>
If you have followed these directions you should be ready to roll. I have not included
how to add the AjaxControlToolkit, but if you are this far it is fairly a no-brainer.
Add the .dll to the GAC; add the assembly reference to the web.config 'assemblies',
add the namespace entry to the web.config 'controls' section and you are ready to
rock! 
</p>
        <p class="step">
Final NOTE!!! UpdatePanels on Pre-SP1 ...
</p>
        <p>
You may need to add the following code to get UpdatePanels to work properly, just
put it in your Master Page
</p>
        <font size="2">
          <p>
          </p>
        </font>
        <font color="#0000ff" size="2">&lt;</font>
        <font color="#a31515" size="2">script</font>
        <font size="2">
        </font>
        <font color="#ff0000" size="2">type</font>
        <font color="#0000ff" size="2">="text/javascript"&gt;<br />
    </font>
        <font size="2">_spOriginalFormAction = document.forms[0].action; 
<br />
    </font>
        <font size="2">_spSuppressFormOnSubmitWrapper=true;<br /></font>
        <font color="#0000ff" size="2">&lt;/</font>
        <font color="#a31515" size="2">script</font>
        <font color="#0000ff" size="2">&gt;
</font>
        <img width="0" height="0" src="http://www.myfriedmind.com/techBlog/aggbug.ashx?id=e6eef807-abf5-44cb-a9ce-f789d97514ee" />
      </body>
      <title>Sharepoint 2007 and Ajax</title>
      <guid isPermaLink="false">http://www.myfriedmind.com/techBlog/PermaLink,guid,e6eef807-abf5-44cb-a9ce-f789d97514ee.aspx</guid>
      <link>http://www.myfriedmind.com/techBlog/2009/05/14/Sharepoint2007AndAjax.aspx</link>
      <pubDate>Thu, 14 May 2009 18:50:48 GMT</pubDate>
      <description>&lt;p&gt;
Recently someone asked about using Ajax on Sharepoint.&amp;nbsp;I should note that a number
of resources are out there on this which I used, so - as brilliant as&amp;nbsp;I am &amp;lt;g&amp;gt;
- the credit for this has to go to those who have gone before...
&lt;/p&gt;
&lt;p&gt;
Like a lot of people I have been working on both since their betas, so whether or
not I should install Ajax on Sharepoint was a no-brainer. Unfortunately, when Sharepoint
2007 first came out it was the very end of 2006 and Ajax was not officially released
until January 23, 2007. As a result, in order to utilize Ajax on Sharepoint (pre-SP1)
you needed to jump through a whole host of hoops. This is not to say it could not
be done, merely that it was a cumbersome and painful process.
&lt;/p&gt;
&lt;p class=step&gt;
Step 1: Install SP1 on Sharepoint
&lt;/p&gt;
&lt;p&gt;
Luckily the folks on the Sharepoint team made that&amp;nbsp;a priority, and even though&amp;nbsp;we
had to wait a bit for it, they did include 'Ajax support' in SP1. So the first step
to using Ajax on Sharepoint 2007 is, quite simply, install Sharepoint 2007 SP1. You
can do it without SP1, but really, why would you?
&lt;/p&gt;
&lt;p&gt;
Note that simply installing SP1 does not automatically turn on Ajax (there are more
steps) but it removes some of the bugs that popped up.
&lt;/p&gt;
&lt;p class=step&gt;
Step 2: (Recommended): Install Asp.Net framework 3.5 SP1
&lt;/p&gt;
&lt;p&gt;
The next thing that I strongly suggest is that you upgrade to .Net 3.5 (sp1). Why?
Simply because if you are going to be doing any Ajax you will want to. 
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
It includes it directly in the framework, no need to install it separately 
&lt;li&gt;
It has awesome debugging - you will still use Fiddler, but less often 
&lt;li&gt;
Intellisense 
&lt;li&gt;
Much, much easier means of creating a 'tracking history' of Ajax calls&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
If you decide to install .Net 3.5, note that you will not see a Web Service Extension
for it in the IIS Manager. This is not a flaw, this is because 3.5 is an extension
of 2.0. Let me state that again - if you install 3.5 you will actually use 2.0 as
the .Net version.
&lt;/p&gt;
&lt;p&gt;
Doing these two steps does not mean that Ajax is automatically up and running, just
that the necessary dlls have been put into the GAC.
&lt;/p&gt;
&lt;p&gt;
One final note - if you install 3.5 you will be using version 3.5.0.0 of System.Web.UI.*
in a number of your web.config entries. If you are using an earlier version, make
sure to check the GAC and find out what the specific version is. Most of the rest
of the steps involve modifying your web.config, so make sure you know your System.Web.UI.Extensions
version before you being
&lt;/p&gt;
&lt;p class=step&gt;
Step 2a: Make a back up of your web.config
&lt;/p&gt;
&lt;p&gt;
We are all good techies here, right? Which means we are all paranoid, right? Never,
ever modify your web.config unless you have a rollback copy at hand. Remember, paranoia
is a job-requirement.
&lt;/p&gt;
&lt;p class=step&gt;
Step 3: Add the&amp;nbsp;system.web.extensions&amp;nbsp;sectionGroups to the configSections
of your web.config
&lt;/p&gt;
&lt;p&gt;
If you are not familiar with Sharepoint, this will be located in your c:\inetpub\wwwroot\VirtualDirectories\wss\{your
site's port here}. So if you have your Sharepoint on port 8080 your web.config will
be located at c:\inetpub\wwwroot\VirtualDirectories\wss\8080. Remember to make a copy
of it like a good, paranoid nerd. Also, I tend to remark what I am adding and why
to my web.config, but you don't have to.
&lt;/p&gt;
&lt;p&gt;
Add this in the &amp;lt;configSections&amp;gt; portion, which should be at the top. You will
already see other &amp;lt;sectionGroup... &amp;gt; entries there, just add this one at the
end (above the &amp;lt;/configSections&amp;gt; entry), wrapped for readability...
&lt;/p&gt;
&lt;font color=#0000ff size=2&gt; 
&lt;p&gt;
&amp;lt;!--
&lt;/font&gt;&lt;font color=#008000 size=2&gt; ======= Added for Ajax start ====== &lt;/font&gt;&lt;font color=#0000ff size=2&gt;--&amp;gt;&lt;br&gt;
&amp;lt;&lt;/font&gt;&lt;font color=#a31515 size=2&gt;sectionGroup&lt;/font&gt;&lt;font color=#0000ff size=2&gt; &lt;/font&gt;&lt;font color=#ff0000 size=2&gt;name&lt;/font&gt;&lt;font color=#0000ff size=2&gt;=&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt;system.web.extensions&lt;/font&gt;&lt;font color=#000000 size=2&gt;" 
&lt;br&gt;
&lt;/font&gt;&lt;font color=#ff0000 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
type&lt;/font&gt;&lt;font color=#0000ff size=2&gt;=&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt;System.Web.Configuration.SystemWebExtensionsSectionGroup, 
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; System.Web.Extensions,&amp;nbsp;Version=3.5.0.0,
Culture=neutral,&amp;nbsp; 
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color=#0000ff size=2&gt;PublicKeyToken=31bf3856ad364e35&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt;&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;&lt;/font&gt;&lt;font color=#a31515 size=2&gt;sectionGroup&lt;/font&gt;&lt;font color=#0000ff size=2&gt; &lt;/font&gt;&lt;font color=#ff0000 size=2&gt;name&lt;/font&gt;&lt;font color=#0000ff size=2&gt;=&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt;scripting&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt;&amp;nbsp; 
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color=#ff0000 size=2&gt;type&lt;/font&gt;&lt;font color=#0000ff size=2&gt;=&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt;System.Web.Configuration.ScriptingSectionGroup, 
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color=#0000ff size=2&gt;System.Web.Extensions,
Version=3.5.0.0,&amp;nbsp;&amp;nbsp;&lt;br&gt;
&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Culture=neutral,
PublicKeyToken=31bf3856ad364e35&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt;&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;&lt;/font&gt;&lt;font color=#a31515 size=2&gt;section&lt;/font&gt;&lt;font color=#0000ff size=2&gt; &lt;/font&gt;&lt;font color=#ff0000 size=2&gt;name&lt;/font&gt;&lt;font color=#0000ff size=2&gt;=&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt;scriptResourceHandler&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt; 
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color=#ff0000 size=2&gt;type&lt;/font&gt;&lt;font color=#0000ff size=2&gt;=&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt;System.Web.Configuration.ScriptingScriptResourceHandlerSection,&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;System.Web.Extensions,&amp;nbsp;Version=3.5.0.0,
Culture=neutral, 
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
PublicKeyToken=31bf3856ad364e35&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt; &lt;/font&gt;&lt;font color=#ff0000 size=2&gt;requirePermission&lt;/font&gt;&lt;font color=#0000ff size=2&gt;=&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt;false&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt;&amp;nbsp;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color=#ff0000 size=2&gt;allowDefinition&lt;/font&gt;&lt;font color=#0000ff size=2&gt;=&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt;MachineToApplication&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt; /&amp;gt;&lt;br&gt;
&lt;/font&gt;&lt;font color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;&lt;/font&gt;&lt;font color=#a31515 size=2&gt;sectionGroup&lt;/font&gt;&lt;font color=#0000ff size=2&gt; &lt;/font&gt;&lt;font color=#ff0000 size=2&gt;name&lt;/font&gt;&lt;font color=#0000ff size=2&gt;=&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt;webServices&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt; 
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color=#ff0000 size=2&gt;type&lt;/font&gt;&lt;font color=#0000ff size=2&gt;=&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt;System.Web.Configuration.ScriptingWebServicesSectionGroup, 
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
System.Web.Extensions,&amp;nbsp;Version=3.5.0.0, Culture=neutral, 
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
PublicKeyToken=31bf3856ad364e35&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt;&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;&lt;/font&gt;&lt;font color=#a31515 size=2&gt;section&lt;/font&gt;&lt;font color=#0000ff size=2&gt; &lt;/font&gt;&lt;font color=#ff0000 size=2&gt;name&lt;/font&gt;&lt;font color=#0000ff size=2&gt;=&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt;jsonSerialization&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt; 
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color=#ff0000 size=2&gt;type&lt;/font&gt;&lt;font color=#0000ff size=2&gt;=&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt;System.Web.Configuration.ScriptingJsonSerializationSection, 
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
System.Web.Extensions, Version=3.5.0.0, Culture=neutral, 
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
PublicKeyToken=31bf3856ad364e35&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt; &lt;/font&gt;&lt;font color=#ff0000 size=2&gt;requirePermission&lt;/font&gt;&lt;font color=#0000ff size=2&gt;=&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt;false&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt; 
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color=#ff0000 size=2&gt;allowDefinition&lt;/font&gt;&lt;font color=#0000ff size=2&gt;=&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt;Everywhere&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt; /&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color=#0000ff size=2&gt;&amp;lt;&lt;/font&gt;&lt;font color=#a31515 size=2&gt;section&lt;/font&gt;&lt;font color=#0000ff size=2&gt; &lt;/font&gt;&lt;font color=#ff0000 size=2&gt;name&lt;/font&gt;&lt;font color=#0000ff size=2&gt;=&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt;profileService&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt; 
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color=#ff0000 size=2&gt;type&lt;/font&gt;&lt;font color=#0000ff size=2&gt;=&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt;System.Web.Configuration.ScriptingProfileServiceSection,&amp;nbsp;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;System.Web.Extensions,
Version=3.5.0.0, Culture=neutral, 
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
PublicKeyToken=31bf3856ad364e35&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt; &lt;/font&gt;&lt;font color=#ff0000 size=2&gt;requirePermission&lt;/font&gt;&lt;font color=#0000ff size=2&gt;=&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt;false&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt; 
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color=#ff0000 size=2&gt;allowDefinition&lt;/font&gt;&lt;font color=#0000ff size=2&gt;=&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt;MachineToApplication&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt; /&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color=#0000ff size=2&gt;&amp;lt;&lt;/font&gt;&lt;font color=#a31515 size=2&gt;section&lt;/font&gt;&lt;font color=#0000ff size=2&gt; &lt;/font&gt;&lt;font color=#ff0000 size=2&gt;name&lt;/font&gt;&lt;font color=#0000ff size=2&gt;=&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt;authenticationService&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt; 
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color=#ff0000 size=2&gt;type&lt;/font&gt;&lt;font color=#0000ff size=2&gt;=&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt;System.Web.Configuration.ScriptingAuthenticationServiceSection, 
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
System.Web.Extensions, Version=3.5.0.0, Culture=neutral, 
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
PublicKeyToken=31bf3856ad364e35&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt; &lt;/font&gt;&lt;font color=#ff0000 size=2&gt;requirePermission&lt;/font&gt;&lt;font color=#0000ff size=2&gt;=&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt;false&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt; 
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color=#ff0000 size=2&gt;allowDefinition&lt;/font&gt;&lt;font color=#0000ff size=2&gt;=&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt;MachineToApplication&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt; /&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/&lt;/font&gt;&lt;font color=#a31515 size=2&gt;sectionGroup&lt;/font&gt;&lt;font color=#0000ff size=2&gt;&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/&lt;/font&gt;&lt;font color=#a31515 size=2&gt;sectionGroup&lt;/font&gt;&lt;font color=#0000ff size=2&gt;&amp;gt;&lt;br&gt;
&amp;lt;/&lt;/font&gt;&lt;font color=#a31515 size=2&gt;sectionGroup&lt;/font&gt;&lt;font color=#0000ff size=2&gt;&amp;gt;&lt;br&gt;
&amp;lt;!--&lt;/font&gt;&lt;font color=#008000 size=2&gt; ======= Added for Ajax end ====== &lt;/font&gt;&lt;font color=#0000ff size=2&gt;--&amp;gt;&lt;/font&gt;&gt;
&lt;p class=step&gt;
Step 4: Add System.Web.Extensions as a "SafeControl" to your web.config
&lt;/p&gt;
&lt;p&gt;
SafeControls are those assemblies that should be considered "Safe" by Sharepoint.
Do a quick find for &amp;lt;SafeControls&amp;gt; and you will see a whole lotta them. Simply
add this line to the bottom, above the &amp;lt;/SafeControls&amp;gt;. 
&lt;/p&gt;
&lt;p&gt;
NOTE!!! If you are using a different version than .net 3.5, make sure that you verify
what version it is in the GAC. This needs to be specified in the "Version" section
or Sharepoint will throw an error. Because I am using 3.5, my version is 3.5.0.0
&lt;/p&gt;
&lt;font color=#0000ff size=2&gt; 
&lt;p&gt;
&amp;lt;!--
&lt;/font&gt;&lt;font color=#008000 size=2&gt; ====== Added for Ajax&amp;nbsp; ====== &lt;/font&gt;&lt;font color=#0000ff size=2&gt;--&amp;gt;&lt;br&gt;
&amp;lt;&lt;/font&gt;&lt;font color=#a31515 size=2&gt;SafeControl&lt;/font&gt;&lt;font color=#0000ff size=2&gt; &lt;/font&gt;&lt;font color=#ff0000 size=2&gt;Assembly&lt;/font&gt;&lt;font color=#0000ff size=2&gt;=&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt;System.Web.Extensions,
Version=3.5.0.0, 
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color=#0000ff size=2&gt;Culture=neutral,
PublicKeyToken=31bf3856ad364e35&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt;&amp;nbsp; 
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color=#ff0000 size=2&gt;Namespace&lt;/font&gt;&lt;font color=#0000ff size=2&gt;=&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt;System.Web.UI&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt; &lt;/font&gt;&lt;font color=#ff0000 size=2&gt;TypeName&lt;/font&gt;&lt;font color=#0000ff size=2&gt;=&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt;*&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt; &lt;/font&gt;&lt;font color=#ff0000 size=2&gt;Safe&lt;/font&gt;&lt;font color=#0000ff size=2&gt;=&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt;True&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt; /&amp;gt;&gt;
&lt;/font&gt; 
&lt;p class=step&gt;
Step 5: Add the needed "verbs" to your &amp;lt;httpHandlers&amp;gt;
&lt;/p&gt;
&lt;p&gt;
Note that this is NOT the &amp;lt;httpModules&amp;gt; section. There should already be some
entries there, so just stick this at the end, above the &amp;lt;/httpHandlers&amp;gt; line....
&lt;/p&gt;
&lt;font color=#0000ff size=2&gt; 
&lt;p&gt;
&amp;lt;!--
&lt;/font&gt;&lt;font color=#008000 size=2&gt; ====== Added for Ajax start ====== &lt;/font&gt;&lt;font color=#0000ff size=2&gt;--&amp;gt;&lt;br&gt;
&amp;lt;&lt;/font&gt;&lt;font color=#a31515 size=2&gt;add&lt;/font&gt;&lt;font color=#0000ff size=2&gt; &lt;/font&gt;&lt;font color=#ff0000 size=2&gt;verb&lt;/font&gt;&lt;font color=#0000ff size=2&gt;=&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt;*&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt; &lt;/font&gt;&lt;font color=#ff0000 size=2&gt;path&lt;/font&gt;&lt;font color=#0000ff size=2&gt;=&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt;*.asmx&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt; &lt;/font&gt;&lt;font color=#ff0000 size=2&gt;validate&lt;/font&gt;&lt;font color=#0000ff size=2&gt;=&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt;false&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt; 
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color=#ff0000 size=2&gt;type&lt;/font&gt;&lt;font color=#0000ff size=2&gt;=&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt;System.Web.Script.Services.ScriptHandlerFactory, 
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; System.Web.Extensions, Version=3.5.0.0,
Culture=neutral, 
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; PublicKeyToken=31bf3856ad364e35&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt; /&amp;gt;&lt;br&gt;
&amp;lt;&lt;/font&gt;&lt;font color=#a31515 size=2&gt;add&lt;/font&gt;&lt;font color=#0000ff size=2&gt; &lt;/font&gt;&lt;font color=#ff0000 size=2&gt;verb&lt;/font&gt;&lt;font color=#0000ff size=2&gt;=&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt;*&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt; &lt;/font&gt;&lt;font color=#ff0000 size=2&gt;path&lt;/font&gt;&lt;font color=#0000ff size=2&gt;=&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt;*_AppService.axd&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt; &lt;/font&gt;&lt;font color=#ff0000 size=2&gt;validate&lt;/font&gt;&lt;font color=#0000ff size=2&gt;=&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt;false&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt; 
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color=#ff0000 size=2&gt;type&lt;/font&gt;&lt;font color=#0000ff size=2&gt;=&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt;System.Web.Script.Services.ScriptHandlerFactory,&amp;nbsp;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;System.Web.Extensions, Version=3.5.0.0, 
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Culture=neutral, PublicKeyToken=31bf3856ad364e35&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt; /&amp;gt;&lt;br&gt;
&amp;lt;&lt;/font&gt;&lt;font color=#a31515 size=2&gt;add&lt;/font&gt;&lt;font color=#0000ff size=2&gt; &lt;/font&gt;&lt;font color=#ff0000 size=2&gt;verb&lt;/font&gt;&lt;font color=#0000ff size=2&gt;=&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt;GET,HEAD&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt; &lt;/font&gt;&lt;font color=#ff0000 size=2&gt;path&lt;/font&gt;&lt;font color=#0000ff size=2&gt;=&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt;ScriptResource.axd&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt; 
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color=#ff0000 size=2&gt;type&lt;/font&gt;&lt;font color=#0000ff size=2&gt;=&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt;System.Web.Handlers.ScriptResourceHandler,&amp;nbsp;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;System.Web.Extensions, Version=3.5.0.0,
Culture=neutral, 
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; PublicKeyToken=31bf3856ad364e35&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt; &lt;/font&gt;&lt;font color=#ff0000 size=2&gt;validate&lt;/font&gt;&lt;font color=#0000ff size=2&gt;=&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt;false&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt; /&amp;gt;&lt;br&gt;
&amp;lt;!--&lt;/font&gt;&lt;font color=#008000 size=2&gt; ====== Added for Ajax end ====== &lt;/font&gt;&lt;font color=#0000ff size=2&gt;--&amp;gt;&lt;/font&gt;&gt;
&lt;p class=step&gt;
Step 6: Add the &amp;lt;controls&amp;gt; reference to the &amp;lt;pages...&amp;gt; section of the
web.config
&lt;/p&gt;
&lt;p&gt;
This will enable your pages to recognize the controls that come with Ajax (such as
the ScriptManager, etc). Locate the &amp;lt;pages ...&amp;gt; section and add this at the
end above the &amp;lt;/pages&amp;gt; entry. Again, keep an eye on the Version.
&lt;/p&gt;
&lt;font color=#0000ff size=2&gt; 
&lt;p&gt;
&amp;lt;!--
&lt;/font&gt;&lt;font color=#008000 size=2&gt; ====== Added for Ajax&amp;nbsp; ====== &lt;/font&gt;&lt;font color=#0000ff size=2&gt;--&amp;gt;&lt;br&gt;
&amp;lt;&lt;/font&gt;&lt;font color=#a31515 size=2&gt;controls&lt;/font&gt;&lt;font color=#0000ff size=2&gt;&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;&lt;/font&gt;&lt;font color=#a31515 size=2&gt;add&lt;/font&gt;&lt;font color=#0000ff size=2&gt; &lt;/font&gt;&lt;font color=#ff0000 size=2&gt;tagPrefix&lt;/font&gt;&lt;font color=#0000ff size=2&gt;=&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt;asp&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt; &lt;/font&gt;&lt;font color=#ff0000 size=2&gt;namespace&lt;/font&gt;&lt;font color=#0000ff size=2&gt;=&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt;System.Web.UI&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt; 
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color=#ff0000 size=2&gt;assembly&lt;/font&gt;&lt;font color=#0000ff size=2&gt;=&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt;System.Web.Extensions,
Version=3.5.0.0, 
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Culture=neutral, PublicKeyToken=31bf3856ad364e35&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt; /&amp;gt;&lt;br&gt;
&lt;/font&gt;&lt;font color=#0000ff size=2&gt;&amp;lt;/&lt;/font&gt;&lt;font color=#a31515 size=2&gt;controls&lt;/font&gt;&lt;font color=#0000ff size=2&gt;&amp;gt;&lt;br&gt;
&lt;/font&gt;&lt;font color=#0000ff size=2&gt;&amp;lt;!--&lt;font color=#008000 size=2&gt; ====== Added
for Ajax&amp;nbsp;&amp;nbsp;end ====== &lt;/font&gt;&lt;font color=#0000ff size=2&gt;--&amp;gt;&lt;/font&gt;&gt;
&lt;/font&gt; 
&lt;p class=step&gt;
Step 7: Add this at the very end of your web.config, just above the &amp;lt;/configuration&amp;gt;
line
&lt;/p&gt;
&lt;p&gt;
Of course you could stick it somewhere else, but let's be neat here... This is the
section that first thing that you put into your web.config (the &amp;lt;sectionGroup...&amp;gt;
referenced. There is documentation out there on sectionGroups, and they are very handy,
if you get interested. I have left a lot of commented lines in there for if you need
them. And, once more repeat after me, if you are not using 3.5, check the Version!
&lt;/p&gt;
&lt;font color=#0000ff size=2&gt; 
&lt;p&gt;
&amp;lt;!--
&lt;/font&gt;&lt;font color=#008000 size=2&gt; ====== Added for Ajax start ====== &lt;/font&gt;&lt;font color=#0000ff size=2&gt;--&amp;gt;&lt;br&gt;
&amp;lt;&lt;/font&gt;&lt;font color=#a31515 size=2&gt;system.web.extensions&lt;/font&gt;&lt;font color=#0000ff size=2&gt;&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;&lt;/font&gt;&lt;font color=#a31515 size=2&gt;scripting&lt;/font&gt;&lt;font color=#0000ff size=2&gt;&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;&lt;/font&gt;&lt;font color=#a31515 size=2&gt;webServices&lt;/font&gt;&lt;font color=#0000ff size=2&gt;&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;!--&lt;/font&gt;&lt;font color=#008000 size=2&gt; Uncomment
this line to enable the authentication 
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
service. Include requireSSL="true" if appropriate. &lt;/font&gt;&lt;font color=#0000ff size=2&gt;--&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;lt;!-- &lt;/font&gt;&lt;font color=#008000 size=2&gt;&amp;lt;authenticationService enabled="true"
requireSSL = "true|false"/&amp;gt; &lt;/font&gt;&lt;font color=#0000ff size=2&gt;--&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;!--&lt;/font&gt;&lt;font color=#008000 size=2&gt; Uncomment
these lines to enable the profile service. 
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
To allow profile properties to be retrieved and modified&amp;nbsp;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;in
ASP.NET AJAX applications, you need to add each property 
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
name to the readAccessProperties and&amp;nbsp;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;writeAccessProperties
attributes. &lt;/font&gt;&lt;font color=#0000ff size=2&gt;--&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;lt;!-- &lt;/font&gt;&lt;font color=#008000 size=2&gt;&amp;lt;profileService enabled="true" 
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
readAccessProperties="propertyname1,propertyname2" 
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
writeAccessProperties="propertyname1,propertyname2" /&amp;gt; &lt;/font&gt;&lt;font color=#0000ff size=2&gt;--&amp;gt;&lt;br&gt;
&amp;nbsp;&lt;/font&gt;&lt;font color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/&lt;/font&gt;&lt;font color=#a31515 size=2&gt;webServices&lt;/font&gt;&lt;font color=#0000ff size=2&gt;&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;!-- &lt;/font&gt;&lt;font color=#008000 size=2&gt;&amp;lt;scriptResourceHandler
enableCompression="true" enableCaching="true" /&amp;gt; &lt;/font&gt;&lt;font color=#0000ff size=2&gt;--&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color=#0000ff size=2&gt;&amp;lt;/&lt;/font&gt;&lt;font color=#a31515 size=2&gt;scripting&lt;/font&gt;&lt;font color=#0000ff size=2&gt;&amp;gt;&lt;br&gt;
&amp;lt;/&lt;/font&gt;&lt;font color=#a31515 size=2&gt;system.web.extensions&lt;/font&gt;&lt;font color=#0000ff size=2&gt;&amp;gt;&lt;br&gt;
&amp;lt;&lt;/font&gt;&lt;font color=#a31515 size=2&gt;system.webServer&lt;/font&gt;&lt;font color=#0000ff size=2&gt;&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;&lt;/font&gt;&lt;font color=#a31515 size=2&gt;validation&lt;/font&gt;&lt;font color=#0000ff size=2&gt; &lt;/font&gt;&lt;font color=#ff0000 size=2&gt;validateIntegratedModeConfiguration&lt;/font&gt;&lt;font color=#0000ff size=2&gt;=&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt;false&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt; /&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;&lt;/font&gt;&lt;font color=#a31515 size=2&gt;modules&lt;/font&gt;&lt;font color=#0000ff size=2&gt;&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;&lt;/font&gt;&lt;font color=#a31515 size=2&gt;add&lt;/font&gt;&lt;font color=#0000ff size=2&gt; &lt;/font&gt;&lt;font color=#ff0000 size=2&gt;name&lt;/font&gt;&lt;font color=#0000ff size=2&gt;=&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt;ScriptModule&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt; &lt;/font&gt;&lt;font color=#ff0000 size=2&gt;preCondition&lt;/font&gt;&lt;font color=#0000ff size=2&gt;=&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt;integratedMode&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt; 
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color=#ff0000 size=2&gt;type&lt;/font&gt;&lt;font color=#0000ff size=2&gt;=&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt;System.Web.Handlers.ScriptModule,&amp;nbsp;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;System.Web.Extensions,
Version=3.5.0.0, Culture=neutral,&amp;nbsp;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;PublicKeyToken=31bf3856ad364e35&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt; /&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/&lt;/font&gt;&lt;font color=#a31515 size=2&gt;modules&lt;/font&gt;&lt;font color=#0000ff size=2&gt;&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;&lt;/font&gt;&lt;font color=#a31515 size=2&gt;handlers&lt;/font&gt;&lt;font color=#0000ff size=2&gt;&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;&lt;/font&gt;&lt;font color=#a31515 size=2&gt;remove&lt;/font&gt;&lt;font color=#0000ff size=2&gt; &lt;/font&gt;&lt;font color=#ff0000 size=2&gt;name&lt;/font&gt;&lt;font color=#0000ff size=2&gt;=&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt;WebServiceHandlerFactory-Integrated&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt; /&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;&lt;/font&gt;&lt;font color=#a31515 size=2&gt;add&lt;/font&gt;&lt;font color=#0000ff size=2&gt; &lt;/font&gt;&lt;font color=#ff0000 size=2&gt;name&lt;/font&gt;&lt;font color=#0000ff size=2&gt;=&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt;ScriptHandlerFactory&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt; &lt;/font&gt;&lt;font color=#ff0000 size=2&gt;verb&lt;/font&gt;&lt;font color=#0000ff size=2&gt;=&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt;*&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt; &lt;/font&gt;&lt;font color=#ff0000 size=2&gt;path&lt;/font&gt;&lt;font color=#0000ff size=2&gt;=&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt;*.asmx&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt; 
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color=#ff0000 size=2&gt;preCondition&lt;/font&gt;&lt;font color=#0000ff size=2&gt;=&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt;integratedMode&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt; 
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color=#ff0000 size=2&gt;type&lt;/font&gt;&lt;font color=#0000ff size=2&gt;=&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt;System.Web.Script.Services.ScriptHandlerFactory, 
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
System.Web.Extensions, Version=3.5.0.0, Culture=neutral,&amp;nbsp;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;PublicKeyToken=31bf3856ad364e35&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt; /&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;&lt;/font&gt;&lt;font color=#a31515 size=2&gt;add&lt;/font&gt;&lt;font color=#0000ff size=2&gt; &lt;/font&gt;&lt;font color=#ff0000 size=2&gt;name&lt;/font&gt;&lt;font color=#0000ff size=2&gt;=&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt;ScriptHandlerFactoryAppServices&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt; &lt;/font&gt;&lt;font color=#ff0000 size=2&gt;verb&lt;/font&gt;&lt;font color=#0000ff size=2&gt;=&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt;*&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt; 
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color=#ff0000 size=2&gt;path&lt;/font&gt;&lt;font color=#0000ff size=2&gt;=&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt;*_AppService.axd&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt; &lt;/font&gt;&lt;font color=#ff0000 size=2&gt;preCondition&lt;/font&gt;&lt;font color=#0000ff size=2&gt;=&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt;integratedMode&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt; 
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color=#ff0000 size=2&gt;type&lt;/font&gt;&lt;font color=#0000ff size=2&gt;=&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt;System.Web.Script.Services.ScriptHandlerFactory, 
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
System.Web.Extensions, Version=3.5.0.0, Culture=neutral, 
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
PublicKeyToken=31bf3856ad364e35&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt; /&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;&lt;/font&gt;&lt;font color=#a31515 size=2&gt;add&lt;/font&gt;&lt;font color=#0000ff size=2&gt; &lt;/font&gt;&lt;font color=#ff0000 size=2&gt;name&lt;/font&gt;&lt;font color=#0000ff size=2&gt;=&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt;ScriptResource&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt; &lt;/font&gt;&lt;font color=#ff0000 size=2&gt;preCondition&lt;/font&gt;&lt;font color=#0000ff size=2&gt;=&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt;integratedMode&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt; 
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color=#ff0000 size=2&gt;verb&lt;/font&gt;&lt;font color=#0000ff size=2&gt;=&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt;GET,HEAD&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt; &lt;/font&gt;&lt;font color=#ff0000 size=2&gt;path&lt;/font&gt;&lt;font color=#0000ff size=2&gt;=&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt;ScriptResource.axd&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt; 
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color=#ff0000 size=2&gt;type&lt;/font&gt;&lt;font color=#0000ff size=2&gt;=&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt;System.Web.Handlers.ScriptResourceHandler, 
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
System.Web.Extensions, Version=3.5.0.0, Culture=neutral, 
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
PublicKeyToken=31bf3856ad364e35&lt;/font&gt;&lt;font color=#000000 size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt; /&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/&lt;/font&gt;&lt;font color=#a31515 size=2&gt;handlers&lt;/font&gt;&lt;font color=#0000ff size=2&gt;&amp;gt;&lt;br&gt;
&amp;lt;/&lt;/font&gt;&lt;font color=#a31515 size=2&gt;system.webServer&lt;/font&gt;&lt;font color=#0000ff size=2&gt;&amp;gt;&lt;br&gt;
&amp;lt;!--&lt;/font&gt;&lt;font color=#008000 size=2&gt; ====== Added for Ajax&amp;nbsp;&amp;nbsp;end ====== &lt;/font&gt;&lt;font color=#0000ff size=2&gt;--&amp;gt;&lt;/font&gt;&gt;
&lt;p class=step&gt;
Step 8: Add a ScriptManager to your Master Page
&lt;/p&gt;
&lt;p&gt;
You can always do it dynamically, and I always check in my code&amp;nbsp;to see if it
exists before whatever webpart I am writing loads, but it is much simpler just to
add it on your Master Page. Just stick it below the&amp;nbsp;&amp;lt;form id="Form1"... &amp;gt;&amp;nbsp;entry
:&lt;br&gt;
&lt;font color=#0000ff size=2&gt;
&lt;br&gt;
&lt;/font&gt;&lt;font color=#0000ff size=2&gt;&amp;lt;&lt;/font&gt;&lt;font color=#a31515 size=2&gt;asp&lt;/font&gt;&lt;font color=#0000ff size=2&gt;:&lt;/font&gt;&lt;font color=#a31515 size=2&gt;ScriptManager&lt;/font&gt;&lt;font size=2&gt; &lt;/font&gt;&lt;font color=#ff0000 size=2&gt;runat&lt;/font&gt;&lt;font color=#0000ff size=2&gt;="server"&lt;/font&gt;&lt;font size=2&gt; &lt;/font&gt;&lt;font color=#ff0000 size=2&gt;ID&lt;/font&gt;&lt;font color=#0000ff size=2&gt;="ScriptManager1
/&lt;/font&gt;&lt;font color=#0000ff size=2&gt;&amp;gt;&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
Please note that there are a LOT of other goodies you can add to your ScriptManager,
especially in .net 3.5, so feel free to expand it. Just make sure it is in there.
&lt;/p&gt;
&lt;p class=step&gt;
Step 9: Write Ajax pages (or webparts).
&lt;/p&gt;
&lt;p&gt;
If you have followed these directions you should be ready to roll. I have not included
how to add the AjaxControlToolkit, but if you are this far it is fairly a no-brainer.
Add the .dll to the GAC; add the assembly reference to the web.config 'assemblies',
add the namespace entry to the web.config 'controls' section and you are ready to
rock!&amp;nbsp;
&lt;/p&gt;
&lt;p class=step&gt;
Final NOTE!!! UpdatePanels on Pre-SP1 ...
&lt;/p&gt;
&lt;p&gt;
You may need to add the following code to get UpdatePanels to work properly, just
put it in your Master Page
&lt;/p&gt;
&lt;font size=2&gt; 
&lt;p&gt;
&lt;/font&gt;&lt;font color=#0000ff size=2&gt;&amp;lt;&lt;/font&gt;&lt;font color=#a31515 size=2&gt;script&lt;/font&gt;&lt;font size=2&gt; &lt;/font&gt;&lt;font color=#ff0000 size=2&gt;type&lt;/font&gt;&lt;font color=#0000ff size=2&gt;="text/javascript"&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font size=2&gt;_spOriginalFormAction = document.forms[0].action; 
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font size=2&gt;_spSuppressFormOnSubmitWrapper=true;&lt;br&gt;
&lt;/font&gt;&lt;font color=#0000ff size=2&gt;&amp;lt;/&lt;/font&gt;&lt;font color=#a31515 size=2&gt;script&lt;/font&gt;&lt;font color=#0000ff size=2&gt;&amp;gt;&gt;
&lt;/font&gt;&lt;img width="0" height="0" src="http://www.myfriedmind.com/techBlog/aggbug.ashx?id=e6eef807-abf5-44cb-a9ce-f789d97514ee" /&gt;</description>
      <comments>http://www.myfriedmind.com/techBlog/CommentView,guid,e6eef807-abf5-44cb-a9ce-f789d97514ee.aspx</comments>
      <category>Ajax</category>
      <category>Asp.Net</category>
      <category>c#</category>
      <category>Sharepoint 2007</category>
    </item>
  </channel>
</rss>