<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-3513941556916290977</id><updated>2012-02-17T03:35:41.033+02:00</updated><category term='Callback'/><category term='History'/><category term='ASP.NET'/><category term='.NET'/><title type='text'>Code in a bucket</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://deadburger.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3513941556916290977/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://deadburger.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Iiro Rahkonen</name><uri>http://www.blogger.com/profile/05423204025460075002</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>1</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-3513941556916290977.post-3067731877435808604</id><published>2009-10-23T16:44:00.002+03:00</published><updated>2009-10-23T17:30:15.975+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='ASP.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='Callback'/><category scheme='http://www.blogger.com/atom/ns#' term='History'/><title type='text'>ASP.NET Ajax History and callbacks</title><content type='html'>&lt;p&gt;&lt;span style="font-family:arial;"&gt;A few weeks ago I run into a problem with the ASP.NET Ajax History, when I enabled it on my site my callbacks to the server broke and I started to investigate it and found the solution finally.&lt;/span&gt;&lt;/p&gt;&lt;span style="font-family:Arial;"&gt;&lt;/span&gt;&lt;span style="font-family:arial;"&gt;&lt;p&gt;&lt;br /&gt;I found that the &lt;strong&gt;WebForm_DoCallBack &lt;/strong&gt;is using the pages form action as the url to load the callbacks and when the hash like &lt;strong&gt;MyPage.aspx#h=352564 &lt;/strong&gt;is added to the page by the History the callback is invalidated and it throws an exception and the callback won't go through.&lt;/p&gt;&lt;p&gt;So to fix it I made a HttpModule that altered the &lt;strong&gt;WebForm_DoCallBack&lt;/strong&gt; function and removed the history section from the calling url like:&lt;/p&gt;&lt;p&gt;First in the HttpModules BeginRequest event I registered a filter for all .axd files:&lt;/p&gt;&lt;pre class="csharp" name="code"&gt;        void context_BeginRequest(object sender, EventArgs e)&lt;br /&gt;       {&lt;br /&gt;           if (this._context.Request.Url.AbsoluteUri.IndexOf(".axd", StringComparison.InvariantCultureIgnoreCase) != -1)&lt;br /&gt;           {&lt;br /&gt;               this._context.Response.Filter = new CallBackFilter(this._context.Response.Filter);&lt;br /&gt;           }&lt;br /&gt;       }&lt;/pre&gt;&lt;p&gt;Then in the filters Write method I did:&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;pre class="csharp" name="code"&gt;&lt;br /&gt;       private Stream stream;&lt;br /&gt;       private StreamWriter streamWriter;&lt;br /&gt;       StringBuilder responseHtml;&lt;br /&gt;&lt;br /&gt;       public CallbackFilter(Stream strm)&lt;br /&gt;       {&lt;br /&gt;           stream = strm;&lt;br /&gt;           responseHtml = new StringBuilder();&lt;br /&gt;           streamWriter = new StreamWriter(stream);&lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;     public override void Write(byte[] buffer, int offset, int count)&lt;br /&gt;     {&lt;br /&gt;           string strBuffer = Encoding.Default.GetString(buffer, offset, count);&lt;br /&gt;&lt;br /&gt;           if (strBuffer.Contains("WebForm_DoCallback"))&lt;br /&gt;           {&lt;br /&gt;               Match m = Regex.Match(strBuffer, "(xmlRequest\\.open\\(\"POST\", )(theForm.action)(, true\\);)");&lt;br /&gt;               string newString = m.Groups[1].Value + m.Groups[2].Value + ".replace(/(#h=\\d+)/, '')" + m.Groups[3].Value;&lt;br /&gt;               strBuffer = strBuffer.Replace("xmlRequest.open(\"POST\", theForm.action, true);", newString);&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;               responseHtml.Append(strBuffer);&lt;br /&gt;               string finalHtml = responseHtml.ToString();&lt;br /&gt;               byte[] data = Encoding.Default.GetBytes(finalHtml);&lt;br /&gt;               streamWriter.Write(finalHtml);&lt;br /&gt;               streamWriter.Close();&lt;br /&gt;           }&lt;br /&gt;           else&lt;br /&gt;           {&lt;br /&gt;               stream.Write(buffer, offset, count);&lt;br /&gt;               stream.Close();&lt;br /&gt;           }&lt;br /&gt;     }&lt;/pre&gt;&lt;p&gt;You should notice that the &lt;strong&gt;".replace(/(#h=\\d+)/, '')" &lt;/strong&gt;is injected to the JavaScript and it assumes that the History key is &lt;strong&gt;h&lt;/strong&gt; and the value is add numeric. Finally I registered the module in web.config and expected it to work, but no. &lt;/p&gt;&lt;p&gt;I Googled a little and found that the &lt;strong&gt;HttpModules&lt;/strong&gt; don't handle&lt;strong&gt; .axd&lt;/strong&gt; files correctly. The reason is that the writer that writes the JavaScript, CSS etc. out doesn't allow any more writes to it, and this can be solved only with reflection in the modules &lt;strong&gt;PostRequestHandlerExecute-event&lt;/strong&gt; like this:&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;pre class="c#" name="code"&gt;        void context_PostRequestHandlerExecute(object sender, EventArgs e)&lt;br /&gt;       {&lt;br /&gt;           var response = ((HttpApplication)sender).Context.Response;&lt;br /&gt;           var httpWriterField = typeof(HttpResponse).GetField("_httpWriter",&lt;br /&gt;                                 BindingFlags.NonPublic  BindingFlags.Instance);&lt;br /&gt;           var ignoringFurtherWritesField = typeof(HttpWriter).GetField("_ignoringFurtherWrites",&lt;br /&gt;                                            BindingFlags.NonPublic  BindingFlags.Instance);&lt;br /&gt;           var httpWriter = httpWriterField.GetValue(response);&lt;br /&gt;           ignoringFurtherWritesField.SetValue(httpWriter, false);&lt;br /&gt;       }&lt;/pre&gt;&lt;p&gt;That was a tip from another &lt;a href="http://daniel-richardson.blogspot.com/2008/11/how-to-apply-filter-to-content-returned.html"&gt;blog&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Now the callbacks work perfectly and the line:&lt;br /&gt;&lt;strong&gt;xmlRequest.open("POST", theForm.action, true);&lt;/strong&gt;&lt;br /&gt;in the ASP.NET JavaScript resource file is replaced with:&lt;br /&gt;&lt;strong&gt;xmlRequest.open("POST", theForm.action.replace(/(#h=\\d+)/, ''), true);&lt;/strong&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;I'm sure that the are other uses for this "injection" technic too.&lt;/p&gt;&lt;p&gt;This is not the cleanest solution to this problem, I'm sure, but it works!&lt;/p&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3513941556916290977-3067731877435808604?l=deadburger.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://deadburger.blogspot.com/feeds/3067731877435808604/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://deadburger.blogspot.com/2009/10/aspnet-ajax-history-and-callbacks.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3513941556916290977/posts/default/3067731877435808604'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3513941556916290977/posts/default/3067731877435808604'/><link rel='alternate' type='text/html' href='http://deadburger.blogspot.com/2009/10/aspnet-ajax-history-and-callbacks.html' title='ASP.NET Ajax History and callbacks'/><author><name>Iiro Rahkonen</name><uri>http://www.blogger.com/profile/05423204025460075002</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>
