I've spent about half an hour trying to determine why the DataFormatString format would not be applied to cell values in a GridView. The short answer: set the HtmlEncode property of the BoundField to false!

Now for the long answer:

A while ago I wrote a small article about how to format the data in your autogenerated GridView columns. At the end of the post I added a small update that explained why I set the HtmlEncode to false. It was, in my opinion, a GridView bug.

However, I didn't realise at the time that the same thing applies to normal GridView BoundFields as well. The thing is, in order to display a value in a bound cell, it FIRST applies the HtmlEncoding to the value CAST TO STRING, THEN it applies the FORMATTING. Here is the reflected source:


/// <summary>Formats the specified field value for a cell in the <see cref="T:System.Web.UI.WebControls.BoundField"></see> object.</summary>
/// <returns>The field value converted to the format specified by <see cref="P:System.Web.UI.WebControls.BoundField.DataFormatString"></see>.</returns>
/// <param name="dataValue">The field value to format.</param>
/// <param name="encode">true to encode the value; otherwise, false.</param>
protected virtual string FormatDataValue(object dataValue, bool encode)
{
string text1 = string.Empty;
if (!DataBinder.IsNull(dataValue))
{
string text2 = dataValue.ToString();
string text3 = this.DataFormatString;
int num1 = text2.Length;
if ((num1 > 0) && encode)
{
text2 = HttpUtility.HtmlEncode(text2);
}
if ((num1 == 0) && this.ConvertEmptyStringToNull)
{
return this.NullDisplayText;
}
if (text3.Length == 0)
{
return text2;
}
if (encode)
{
return string.Format(CultureInfo.CurrentCulture, text3,
new object[] { text2 });
}
return string.Format(CultureInfo.CurrentCulture, text3,
new object[] { dataValue });
}
return this.NullDisplayText;
}



At least the method is virtual. As you can see, there is no way to format a DateTime, let's say, once it is in string format.

Therefore, if you ever want to format your data in a GridView by using DataFormatString, you should make sure HtmlEncode is set to false! Or at least create your own BoundField object that implements a better FormatDataValue method.

Now, this is a stupid post. And By stupid I mean that kind of thing that if you hear about it you think "Oh, it was obvious", but if it happends to you you waste a lot of time trying to fix, then you think "Oh, it was obvious. If I blog about it I will sound stupid". Well, this kind of blog posts are the most important, I think, so here it is, sounding stupid:

I had a div, absolutely positioned and of fixed width, with a long text inside that would just not wrap! That means the div would either expand its width to accomodate my text (Internet Explorer) or bleed the text out (FireFox). Was it white-space:nowrap? No! Was it that some of the table cells that contained elements had the "noWrap" attribute? No! What the hell is going on?!

Solution and explanation: wrapping occurs only on NORMAL SPACES, not &NBSP;. The text inside my div didn't really have any spaces in it, it was one continuous string of words joined by the innocent &nbsp;.

It was great! Not only the setting was nice (the four star Smart hotel is exactly what I had expected a hotel should be, except the restaurant, maybe), but the weather was cool, the presentation helpful, the tutor (Aurelian Popa) was above expectations and the people pleasant. Not to mention a week away from boring stuff. ;) I feel it would be pointless to detail what we did there, since it was either my own personal life or the actual workshop (which involves work), so I will give you some impressions of the technology and point you towards the resources that would allow you to go through the same learning process.

The whole thing was about WPF and SilverLight and I can tell you two conclusions right now:
WPF/XAML/SilverLight are a great technology and I expect a lot of .Net applications to migrate towards it in the next 6 to 12 months.
The complexity of this technology is likely to put a lot of people off, therefore the tools like Expression Blend and the Visul Studio interface become completely indispensable and must evolve to have great ease of use and become more intuitive.

The entire presentation model allows one to use any graphical transformation available, including 3D, on any part of the interface. The controls are now without appearance. They come with a default appearance that can be totally replaced with your own. A weird example is to use a 3D cube with video running on each side as a button. Of course, the whole thing is still work in progress and some stuff is yet difficult to do. Besides, you know Microsoft: a lot of complicated things are easy to do, while some of the simplest are next to impossible.

You can taste the Microsoft confidence on this by watching them release an entire design oriented suite (Expression) and working on making Silverlight available on all platforms and browsers. Just the fact that Silverlight can access directly the browser DOM is enough to make me remove all those patchy javascript scripts and replace them with nice Silverlight C# code.

Enough of this. Go learn for yourself!

Tools:
Silverlight is at version 2 beta 2. That is painfully obvious when new bugs are introduced and beta 1 applications break. The Expression Blend tool is at version 2.5 June 2008 CTP and it has also a long walk ahead towards becoming useful. Visual Studio 2008 performs rather well when faced with XAML and WPF stuff, but the Resharper 4.0 addon helps it out a lot. You need the Visual Studio 2008 Silverlight Tools, too. After this compulsory tool kit you could also look at Snoop, Blender and Expression Deep Zoom Composer.

Learning material:
Simplest thing to do is to go to Silverlight Hands-on Labs or download the WPF Hand-on labs and download them all and run through the documentation script that is included with each one. There are video tutorials about how to use the tools, too. Here is one for Blend. Of course, all blogs and materials available online at the search of a Google are helpful, as well.

Community:
As any community, it depends on your desired locality and interests. You can look for local .Net / WPF groups or browse for blogs half way around the globe from you. From my limited googling during the workshop I can see that there are people talking about their issues with WPF and SL, but not nearly enough: the technology still needs to mature. I haven't really searched for it, but I've stumbled upon this site: WindowsClient.NET that seems to centralize WPF, Windows Forms and a bit of Silverlight information.

I wanted to write this great post about how to make Web User Controls that would have templates, just like Repeaters or GridViews or whatever, face any problems, then solve them. Unfortunately, MSDN already has a post like this: How to: Create Templated ASP.NET User Controls. So all I can do is tell you where to use this and what problems you might encounter.

I think the usage is pretty clear and useful: whenever you have as?x code that repeats itself, but has different content, you can use a templated Web User Control. The best example I can think of is a collapsable panel. You have a Panel, with some javascript attached to it, a hidden field to hold the collapse state, some buttons and images and texts to act as a header, but every time the content is different.

Now with the issues one might encounter. In Visual Studio 2005 you get an error, while in VS 2008 you get a warning telling you the inner template, whatever name you gave it, is not supported. This is addressed by the
[ PersistenceMode(PersistenceMode.InnerProperty) ]
decoration of the ITemplate property of the control.
Then there is the issue of the design mode, where you get an ugly error in all Visual Studio versions: Type 'System.Web.UI.UserControl' does not have a public property called '[yourTemplatePropertyName]'. As far as I know there is no way of getting rid of this. It is an issue within Visual Studio. However, the thing compiles and the source as?x code is warning free. I think one could easily sacrifice some design time comfort to reusability.

Update: this fix is now on Github: Github. Get the latest version from there.

The scenario is pretty straightforward: a ListBox or DropDownList or any control that renders as a Select html element with a few thousand entries or more causes an asynchronous UpdatePanel update to become incredibly slow on Internet Explorer and reasonably slow on FireFox, keeping the CPU to 100% during this time. Why is that?

Delving into the UpdatePanel inner workings one can see that the actual update is done through an _updatePanel Javascript function. It contains three major parts: it runs all dispose scripts for the update panel, then it executes _destroyTree(element) and then sets element.innerHTML to whatever content it contains. Amazingly enough, the slow part comes from the _destroyTree function. It recursively takes all html elements in an UpdatePanel div and tries to dispose them, their associated controls and their associated behaviours. I don't know why it takes so long with select elements, all I can tell you is that childNodes contains all the options of a select and thus the script tries to dispose every one of them, but it is mostly an IE DOM issue.

What is the solution? Enter the ScriptManager.RegisterDispose method. It registers dispose Javascript scripts for any control during UpdatePanel refresh or delete. Remember the first part of _updatePanel? So if you add a script that clears all the useless options of the select on dispose, you get instantaneous update!

First attempt: I used select.options.length=0;. I realized that on Internet Explorer it took just as much to clear the options as it took to dispose them in the _destroyTree function. The only way I could make it work instantly is with select.parentNode.removeChild(select). Of course, that means that the actual selection would be lost, so something more complicated was needed if I wanted to preserve the selection in the ListBox.

Second attempt: I would dynamically create another select, with the same id and name as the target select element, but then I would populate it only with the selected options from the target, then use replaceChild to make the switch. This worked fine, but I wanted something a little better, because I would have the same issue trying to dynamically create a select with a few thousand items.

Third attempt: I would dynamically create a hidden input with the same id and name as the target select, then I would set its value to the comma separated list of the values of the selected options in the target select element. That should have solved all problems, but somehow it didn't. When selecting 10000 items and updating the UpdatePanel, it took about 5 seconds to replace the select with the hidden field, but then it took minutes again to recreate the updatePanel!

Here is the piece of code that fixes most of the issues so far:

/// <summary>
/// Use it in Page_Load.
/// lbTest is a ListBox with 10000 items
/// updMain is the UpdatePanel in which it resides
/// </summary>
private void RegisterScript()
{
string script =
string.Format(@"
var select=document.getElementById('{0}');
if (select) {{
// first attempt
//select.parentNode.removeChild(select);


// second attempt
// var stub=document.createElement('select');
// stub.id=select.id;
// for (var i=0; i<select.options.length; i++)
// if (select.options[i].selected) {{
// var op=new Option(select.options[i].text,select.options[i].value);
// op.selected=true;
// stub.options[stub.options.length]=op;
// }}
// select.parentNode.replaceChild(stub,select);


// third attempt
var stub=document.createElement('input');
stub.type='hidden';
stub.id=select.id;
stub.name=select.name;
stub._behaviors=select._behaviors;
var val=new Array();
for (var i=0; i<select.options.length; i++)
if (select.options[i].selected) {{
val[val.length]=select.options[i].value;
}}
stub.value=val.join(',');
select.parentNode.replaceChild(stub,select);

}};"
,
lbTest.ClientID);
ScriptManager sm = ScriptManager.GetCurrent(this);
if (sm != null) sm.RegisterDispose(lbTest, script);
}



What made the whole thing be still slow was the initialization of the page after the UpdatePanel updated. It goes all the way to the WebForms.js file embedded in the System.Web.dll (NOT System.Web.Extensions.dll), so part of the .NET framework. What it does it take all the elements of the html form (for selects it takes all selected options) and adds them to the list of postbacked controls within the WebForm_InitCallback javascript function.

The code looks like this:

if (tagName == "select") {
var selectCount = element.options.length;
for (var j = 0; j < selectCount; j++) {
var selectChild = element.options[j];
if (selectChild.selected == true) {
WebForm_InitCallbackAddField(element.name, element.value);
}
}
}
function WebForm_InitCallbackAddField(name, value) {
var nameValue = new Object();
nameValue.name = name;
nameValue.value = value;
__theFormPostCollection[__theFormPostCollection.length] = nameValue;
__theFormPostData += name + "=" + WebForm_EncodeCallback(value) + "&";
}

That is funny enough, because __theFormPostCollection is only used to simulate a postback by adding a hidden input for each of the collection's items to a xmlRequestFrame (just like my code above) in the function WebForm_DoCallback which in turn is called only in the GetCallbackEventReference(string target, string argument, string clientCallback, string context, string clientErrorCallback, bool useAsync) method of the ClientScriptManager which in turn is only used in rarely used scenarios with the own mechanism of javascript callbacks of GridViews, DetailViews and TreeViews. And that is it!! The incredible delay in this javascript code comes from a useless piece of code! The whole WebForm_InitCallback function is useless most of the time! So I added this little bit of code to the RegisterScript method and it all went marvelously fast: 10 seconds for 10000 selected items.

string script = @"WebForm_InitCallback=function() {};";
ScriptManager.RegisterStartupScript(this, GetType(), "removeWebForm_InitCallback", script, true);



And that is it! Problem solved.

This is mostly a noob post, but I had to write it because I've had to work with a project written by a colleague of mine and her method of maintaining value across postbacks was to use HiddenFields. I will explore that option and the ViewState option.

First of all, what are the advantages of using a hidden field? I can see only two:
1. it would work even if ViewState is disabled
2. its value is accesible through javascript
The disadvantages are:
1. it creates additional HTML markup
2. it can only store stuff in string format
3. its value is accesible through javascript

I would not use the hidden field option mainly because it gives people the ability to see and change the value through simple javascript manipulation. It's a security risk, even if most of the times you don't really care about the security of some value maintained through postback. I would use it only when _I_ need to change that value through javascript.

For some code, I assume I want to store an integer value called MyValue. There will be a field called _myValue that will store the value during a cycle, but it is used mainly for caching (reading Request and ViewState is slow) and it is declared like this:

private int? _myValue;


Now, about the structure of such a code. The simplest method is to actually create a (or many) hidden field(s) in your page. You can then use the values directly. It is simple, but hardly maintainable:

Markup:

<asp:HiddenField id=hfMyValue runat=server>

C# code:

public int MyValue
{
get
{
if (_myValue == null)
{
if (String.IsNullOrEmpty(hfMyValue.Value)) MyValue = 10;
else _myValue = Int32.Parse(hfMyValue.Value);
}
return _myValue.Value;
}
set
{
hfMyValue.Value = value.ToString();
_myValue = value;
}
}


I've wrapped the functionality of the hidden field in a property so I can easily use it through my code.

Another method of doing this is to use the RegisterHiddenField method of the ScriptManager like this:

C# code only:

public int MyValue
{
get
{
if (_myValue==null)
{
if (Request["MyValue"] == null) MyValue = 10;
else _myValue = Int32.Parse(Request["MyValue"]);
}
return _myValue.Value;
}
set
{
PreRender -= MyValue_Registration;
PreRender += MyValue_Registration;
_myValue = value;
}
}

void MyValue_Registration(object sender, EventArgs e)
{
if (_myValue.HasValue)
ScriptManager.RegisterHiddenField(this, "MyValue", _myValue.Value.ToString());
}


As you can see, there is no need of my changing the markup. There is the ugly part of having to attach to the prerender event to register the hidden field because the ScriptManager doesn't have any way of accessing the registered hidden field after you did it or at least a way to un-register it. Registering it again doesn't change its value, either.

In both these cases the value is accessible through javascript:

<script>var myValue=parseInt(document.getElementById('<%=hfMyValue.ClientID%>').value);</script>
<script>var myValue=parseInt(document.getElementById('MyValue').value);</script>


But there is an easier way of storing the values through postback, and that is by using ViewState. In order to do that, your object needs only to be Serializable. It can be anything from a string to a complex DataSet. There is no way to access it through javascript, though. Here is the C# code for it:

public int MyValue
{
get
{
if (_myValue == null)
{
if (ViewState["MyValue"] == null) MyValue = 10;
else _myValue = (int)ViewState["MyValue"];
}
return _myValue.Value;
}
set
{
ViewState["MyValue"] = value;
_myValue = value;
}
}


Doesn't that look a lot simpler? And the beauty of it is, the ViewState can be sent inside the markup, as in the default behaviour, but it can just as easily be stored on the server, either by using a SessionStatePersister or by other ways.

Update: Also, a more complicated, but a lot more flexibile way of doing things is described on the DimeBrain blog: Frictionless data persistence in ASP.NET WebForms.

This annoying error appeared out of nowhere in a project that used to work. I thought that the fault was of the new AjaxControlToolKit and the way it tries to register a CSS file. I was about to make really complex and , apparently, useless changes to my code until I've stumbled upon Rick Strahl's blog. It is not in the entry, but further down in the comments, but it's there.

Here is a distilled version: the error is not a page error, but a naming container control error. That means that if you do this in a PlaceHolder, let's say, it will only throw an error if the PlaceHolder has code blocks. The same applies to the header! The problem was not AjaxControlToolKit, but my own modifications to the MasterPage, where I had added script blocks with a dynamic URL.

So I added the script tags from the codebehind using this:

private void AddHeaderScript(string src)
{
HtmlGenericControl hgc=new HtmlGenericControl("script");
hgc.Attributes.Add("type", "text/javascript");
hgc.Attributes.Add("language", "JavaScript");
hgc.Attributes.Add("src", src);
Page.Header.Controls.Add(hgc);

}
. I don't know how this would work during an Ajax postback, but I wasn't interested in this, being a MasterPage thing. And it worked.

So, next time you get this error, be sure you know what control generated it. It can be solved by putting an extra PlaceHolder or, as is this case, replacing just some specific few code blocks.

and has 3 comments
Update: the title of the post should have been "Text searching in general, not as I expected". I did a quick test in javascript. Do 1000 indexOf and then 1000 search(RegExp object) in a long text and measure time. Here are the results:
Internet Explorer 7: search 90% of indexOf time!
FireFox: search 355% of indexOf time!?!
Chrome: search and indexOf same speed.


Update February 2016: I've tried it again, with Firefox 44.0.2, Chrome 48.0.2564.109 m and Internet Explorer 11.0.9600.18163 and indexOf is marginally faster than regex for all of them. For the case insensitive search, Firefox and Chrome take 50% than indexOf, while Internet Explorer is not only the fastest, but also only adds 4% when searching case insensitive.

It makes sense to have the same implementation of indexOf and regular expressions as in .Net for the Microsoft browser, so I am not that surprised, but what happened with FireFox? My hypothesis is that they used Boyer-Moore in indexOf (as any decent programmer should have!) yet used a simpler implementation for their regular expression engine.

A few days ago I was preaching that IndexOf with StringComparison.Ordinal is the fastest thing for text searching. I was even implying that it uses the Boyer-Moore algorithm from a Windows system library written in c++. I was dead wrong!

Thanks to Meaflux who told me that the Internet said things differently, I delved even further into the code, past the .NET code and into the library code of mscorwks.dll where the IndexOfString method that ordinal IndexOf uses, written in c++, appears to be a pathetic linear algorithm!!

Even worse, the Boyer-Moore algorithm is used in the .NET framework in the Regex class! The Regex class is written entirely in managed code, even if it uses all sorts of cool hacks. I've also tried a Boyer-Moore implementation from Codeproject that also included the Apostolico-Giancarlo, BCL, Horspool and Turbo Boyer Moore algorithms. IndexOf was slower!

Anyway, the code is simple: take a one megabyte Harry Potter text book and search a 100 byte text from somewhere near the middle of the text. Use IndexOf with StringComparison.Ordinal, then Regex with both variants, compiled and ad-hoc creation, then the class from CodeProject.

    Results for 100 tries:
  • Ordinal IndexOf - 390 milliseconds
  • Normal IndexOf - 2380 milliseconds (6 times slower!!)
  • AdHoc Regex - 190 milliseconds (take into acount the creation of the regex 100 times plus the use of Regex.Escape 100 times on the search pattern)
  • Compiled Regex - 160 milliseconds
  • Codeproject Boyer-Moore - 230 milliseconds


Would you have believed this?

Maybe the algorithm was better because the search string was 100 bytes, so I made it 12 bytes and redid the test:

    Results for 100 tries:
  • IndexOf - 440 milliseconds(more than with 100 bytes!)
  • Normal IndexOf - 2410 milliseconds!!
  • AdHoc Regex - 235 milliseconds
  • Compiled Regex - 230 milliseconds
  • Codeproject Boyer-Moore - 368 milliseconds (a lot more, similar to IndexOf, yet still less)


Ok, maybe the problem was that the string in which I searched was big. Let's make it 5000 bytes!

    Results for 100000 (1000 times more operations):
  • Ordinal IndexOf - 1109 milliseconds
  • Normal IndexOf - 1109 milliseconds
  • AdHoc Regex - 2500 milliseconds
  • Compiled Regex - 375 milliseconds!!!
  • Codeproject Boyer-Moore - 1312 milliseconds (finally something slower than IndexOf)


So Regex appears to be best for string searching in most cases!

Update: after optimizing the Boyer-Moore class and adding my own goodness to it, I made more tests. The Boyer-Moore algorithm can be improved by adding more preprocessing, therefore it is more and more efficient as the pattern size increases and the number of pattern searches decreases. In those cases (pattern length of a few thousand characters) Regex is not so good, especially if one has to Escape the entire sequence and instantiate the class on each search. Anything over 500 characters in search pattern length made Regex perform less than the most preprocessing BM I've used.

Well, I don't know who still uses it, but I had this old application that we reused and it had a Login control in the login page (obviously!). And I got tired of always entering the name and password every time I tested the site, so I went to the username and password TextBoxes and added a Text="something" bit. And it didn't work.

Why? First of all the TextBox control with TextMode="Password" ignores the Text property completely. Then the Login control only acknowledges the values of the two TextBoxes on change.

The solution: add a value="something" instead of Text="something" and it will be added like an oldfashioned HTML attribute. And it will also fire Changed since the value the .Net control is string.Empty.

That's all, folks, remember to remove this in the production site :)

and has 0 comments
Petru Jucovschi was nice enough to invite me to a software development training organised by Microsoft and partly presented by him. The first of the two days of training was about the theory behind software development practices like agile development and CMMI, part presented by Victor Mihail from Trilex. The second was about the Team System Foundation Server and Visual Studio 2008 Team Edition integrating for a better software development practice.

Well, I am working on remembering everything that was said and done and I will make some longer posts that will describe at length what was presented.
As a short summary, I was familiar with a lot of the concepts from the first part, since I've done a little research into agile development in order to pass it on to my managers. The theory and principles behind Agile were detailed, then the major Agile methodologies were described, including eXtreme Programming, Scrum and (very shortly) MSF. Also concepts of Test Driven Development.
The second part was also partly known to me as I have seen another similar presentation at the previous RONUA meeting, but this time it lasted for 8 hours, so I had the opportunity to ask questions and see things done step by step. Basically, TFS is the tool that combines project management, business analysis, architecture, development, debugging and testing into a single useful bunch. The issue tracking is linked to reporting, integrated with Microsoft Project and Microsoft Excel and concepts like Continuous Integration are directly available along a better source control solution than Visual Source Safe. Bottom line, I can barely wait to start work in a rational, managed way.

Stay tuned for the details.

Well, someone asked me today about why his dynamically generated GridView throws a 'Object reference not set to an instance of an object.' exception at DataBind when he sets AllowPaging to true. I replicated the error and looked at the stack trace, it looked like this:
   at System.Web.UI.WebControls.GridView.BuildCallbackArgument(Int32 pageIndex)
at System.Web.UI.WebControls.GridView.CreateNumericPager(TableRow row, PagedDataSource pagedDataSource, Boolean addFirstLastPageButtons)
at System.Web.UI.WebControls.GridView.InitializePager(GridViewRow row, Int32 columnSpan, PagedDataSource pagedDataSource)
at System.Web.UI.WebControls.GridView.CreateRow(Int32 rowIndex, Int32 dataSourceIndex, DataControlRowType rowType, DataControlRowState rowState, Boolean dataBind, Object dataItem, DataControlField[] fields, TableRowCollection rows, PagedDataSource pagedDataSource)
at System.Web.UI.WebControls.GridView.CreateChildControls(IEnumerable dataSource, Boolean dataBinding)
at System.Web.UI.WebControls.CompositeDataBoundControl.PerformDataBinding(IEnumerable data)
at System.Web.UI.WebControls.GridView.PerformDataBinding(IEnumerable data)
at System.Web.UI.WebControls.DataBoundControl.OnDataSourceViewSelectCallback(IEnumerable data)
at System.Web.UI.DataSourceView.Select(DataSourceSelectArguments arguments, DataSourceViewSelectCallback callback)
at System.Web.UI.WebControls.DataBoundControl.PerformSelect()
at System.Web.UI.WebControls.BaseDataBoundControl.DataBind()
at System.Web.UI.WebControls.GridView.DataBind()
at Malaka.Page_Load(Object sender, EventArgs e) in c:\Inetpub\wwwroot\ScrollableFixedHeaderGrid\Malaka.aspx.cs:line 14
at System.Web.Util.CalliHelper.EventArgFunctionCaller(IntPtr fp, Object o, Object t, EventArgs e)
at System.Web.Util.CalliEventHandlerDelegateProxy.Callback(Object sender, EventArgs e)
at System.Web.UI.Control.OnLoad(EventArgs e)
at System.Web.UI.Control.LoadRecursive()
at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)


So, the error occurs at the BuildCallbackArgument method in the GridView object. I used Lutz Roeder's Reflector to see the source of the GridView object and I got to this piece of code:
        private string BuildCallbackArgument(int pageIndex)
{
if (string.IsNullOrEmpty(this._sortExpressionSerialized))
{
this._sortExpressionSerialized = this.StateFormatter.Serialize(this.SortExpression);
}
return string.Concat(new object[] { "\"", pageIndex, "|", (int) this.SortDirection, "|", this._sortExpressionSerialized, "|\"" });
}


The error appears to be thrown by the StateFormatter property returning null. It's source is:
        private IStateFormatter StateFormatter
{
get
{
if (this._stateFormatter == null)
{
this._stateFormatter = this.Page.CreateStateFormatter();
}
return this._stateFormatter;
}
}


Got it? It assumes you already added the GridView to a Page. Well, this is the usual issue with the GridView.

Solution: Add the GridView to your Page (or to a fictive Page) and then DataBind it.

and has 0 comments
The level of satisfaction one gets from anything is inversely proportional with the level of expectation they have. I knew that in the RONUA meeting on the 9th there will be only two presentations, with subjects I can't use right now and with speakers I didn't exactly feel compelled to listen to. So, of course, I liked it!

But there was something more. Both speakers seemed more mature, more anchored on the subject than usual. It's not that Aurelian Popa did not seem overly arrogant or that the ever helpful Petru Jucovschi didn't have a lot more information than was humanly possible to present in the alloted time and resources, but their performance seemed way better than I was used to.

The subjects were pretty clear: WPF and VS TFS. If you are scared by acronyms you probably shouldn't be reading this :), but I did provide tooltips for them, so move the mouse over them.

The first presentation showed an ObservableCollection (new stuff from .Net 3.0 which allows notification on changing elements) containing SolarSystemItems, objects that encapsulated an image, a diameter, a name, an orbit and a temperature. It started from a simple listbox then, by changing only the presentation (Style) and the way data is presented (DataTemplate) in the XAML file, it gradually changed to a picture+details listbox, a combobox also with picture and everything, then with a details box next to it showing the current selected object, with filtering, sorting, grouping, etc. The grand finale was making the same listbox look like a solar system image, with selectable planets and the details on tooltip, with orbits and everything. The demo can be downloaded and seen at Beatriz Costa's blog.

The second presentation I was more interested in, since our company plans to use Visual Studio TFS to manage our work. Since that would mean a shift from the current Excel+Email+Messenger, I was glad to learn that the TFS learning curve is steep and usage can also start from source control only, moving ever so slightly towards a comprehensive development strategy, with testing, reporting, configurable XML files that describe any process (with out of the box or downloadable versions for MSF, Scrum, XP, CMMI) , etc.

I was surprised to see that not only the session was free, but we also received some gifts from Microsoft for attending. That included the MSDN subscription that I won, the WPF book that my colleague won, a kit with all kinds of goodies that I can't remember won by our boss and 40% discount for some Microsoft products for each. We cleaned house! No free food though :)

My conclusion was that the RONUA meetings are (as far as I have seen) the most techie, interesting and to the point Microsoft events. The MSDN briefings are nice, too, with more budget allocated to them and so on and so on, but they will never be able to replicate the sort of "gang of IT people" feel of the RONUA's meetings. And with people that are ever more implicated and interested in presenting, it can only get better.

Thanks for Raheel for presenting me this problem and the opportunity to fix it.

As you may know from a previous post of mine, Ajax requests differ from normal requests. At the Page level, the rendered content is changed to reflect only the things that changed in the UpdatePanels and the format is different from the usual HTML and it is also very strict. Any attempt to blindly add things to the string sent from the server will result in an ugly alert error. And who does indiscriminately add ugly content to your Ajax requests? "Free" servers that inject commercials in your pages!

So, what can you do? Patch the Ajax engine to remove the offending ads. Here is a simple example for a server that added crap at THE END of the content, crap that did not contain any '|' characters. This is important, as the patch looks for the last '|' character and removes all the things after it.

C# Code

private void LoadApplyPatch()
{
ScriptManager sm = ScriptManager.GetCurrent(Page);
if (sm == null) return;

string script =@"
if (window.Sys&&Sys.WebForms&&Sys.WebForms.PageRequestManager) {
Sys$Net$WebRequestExecutor$get_responseData=function() {
if (arguments.length !== 0) throw Error.parameterCount();
if (!this._responseAvailable) {
throw Error.invalidOperation(String.format(Sys.Res.cannotCallBeforeResponse, 'get_responseData'));
}
if (!this._xmlHttpRequest) {
throw Error.invalidOperation(String.format(Sys.Res.cannotCallOutsideHandler, 'get_responseData'));
}

var content=this._xmlHttpRequest.responseText;

// this is the added code, the rest is taken
// from the ASP.Net Ajax original code
var index=content.lastIndexOf('|');
if (index<content.length-1)
content=content.substring(0,index+1);


return content;
}
}"
;

ScriptManager.RegisterStartupScript(Page,
Page.GetType(), "adMurderer", script, true);
}

Update: I've posted the source and binaries for this control on Github. Free to use and change. Please comment on it.

This is the story of a control that shrinks the content sent from an UpdatePanel to down as 2% without using compression algorithms. I am willing to share the code with whoever wants it and I only ask in return to tell me if and where it went wrong so I can find a solution. Even if you are not interested in the control, the article describes a little about the inner workings of the ASP.Net Ajax mechanism.

You know the UpdatePanel, the control that updates its content asynchronously in ASP.Net, allowing you to easily transform a normal postback based application in a fully fledged Ajax app. Well, the only problem with that control is that you have to either put a lot of them on the page in order to update only what changes (making the site be also fast as you would expect from an Ajax application) but hard to maintain afterwards, or put a big UpdatePanel on the entire page (maybe in the MasterPage) and allow for large chunks of data to be passed back and forth and also other clear disadvantages, some detailed in this blog entry.

Not anymore! I have made a small class, in the form of a Response.Filter, that caches the previously rendered content and instructs the browser to do the same, then sends only a small fraction of the data from the server to the browser, mainly what has changed. There is still the issue of the speed it takes the browser to render the content, which is the same no matter what I do, like when rendering a huge table. It doesn't matter that I send only the changes in one cell, the browser must still render the huge grid. Also, if, for some reason, the update fails, I catch it and I send to the server that the updatepanel must be updated again, the old way.

Enough; let's talk code. I first had to tap into the content that was sent to the browser. That can only be done at Page render level (or PageAdapter, or Response.Filter and other things that can access the rendered content). So I did catch the rendered content in a filter, I recognized it as Ajax by its distinctive format, and I only processed the updatePanel type of token.

Here I had a few problems. First I replaced the updatePanel token with a scriptBlock token that changed the innerHTML of the update panel div element. It all seemed to work until I tested it a little. I discovered that the _updatePanel javascript method of the PageRequestManager object used by the normal ajax rendering on the browser was doing a few extra things, so I used that one instead of just replacing the innerHTML, resulting in a lower speed. But that didn't help either, because it failed when using validators. Even if I did replace the updatePanel token with a correct javascript block, it still got executed a bit later than it should have.

The only solution I had was to replace the _updatePanel method with my own. Itself having a small block of code that disposed some scriptblocks and some other stuff, then a plain innerHTML replace, I could not 'override' it, since it would change the innerHTML with some meaningless stuff (the thing I would send from the server), then I would parse and change the innerHTML again, resulting in bad performance, flickering, nonsense on screen, etc. So I just copy pasted the first part and added my own ApplyPatch function instead of the html replace code line.

Now, here I met another issue. The innerHTML property of an html element is not a simple string. It gets parsed immediately when set and it recreates when read, as explained in this previous article of mine. The only solution for that was create my own property of the update panel div element that remembers the string that was set. This solved a lot more problems, because it meant I could identify the content to be replaced by simple position markers rather than through regular expressions (as was my initial idea). That property would not get changed by custom local javascript either, so I was safe to use it.

About the regular expression engine in Javascript: it has no Singleline option. That means you can only change the content line by line. I could have used Steve Levithan's beautiful work, but with the solution found above, I would not need regular expressions at all.

The only other issue was with UpdatePanels inside UpdatePanels. I found out that in this case, only parent UpdatePanels are being rendered. That meant that the custom property I added to the child panel would disappear and break my code. Therefore I had to keep a tree of the updatepanels in the page and clear all the children cached content when the parents were being updated. So I did that, too.

What else? What if somehow the property would get deleted, changed, or something else happened, like someone decided to recreate the update panel div object or something like that? For that I made a little HttpHandler that would receive an UpdatePanel id and it would clear its cached content. Then, on return from the asynchronous call, the javascript would just push another update panel refresh using __doPostBack(updatePanelId,""). I don't particularily like this approach, since it could back fire with multiple UpdatePanels (as you know, only one postback at a time is supported), but I didn't find a better solution yet. Besides, this event should normally not happen.

So, the mechanism was all in place, all I had to do was make the actual patching mechanism, the one that would find the difference between previously rendered content and current content, then send only the changed part. First thing I did was remove the start and end of the strings that were identical. As you can imagine, that's the most common scenario: a change in the UpdatePanel means all the content up to the change remains unchanged and the same goes for the content after the change. But I was testing the filter with a large grid that would randomly change one cell to a random string. That meant two changes: the previous position and the last. Assuming the first change was in one of the starting cells and the last was in one of the cells at the end, then the compression would be meaningless. So I've googled for an algorithm that would give me the difference between two files/strings and I found Diff! Well, I knew about it so I actually googled for Diff :) It was in the Longest Common Substring algorithm category.

Anyway, the algorithm was nice, clear, explained, with code, perfect for what I wanted and completely useless, since it needed an array of m*n to get what I needed. It was slow, a complete memory hog and I couldn't possibly use an array of 500000x500000. I bet they were optimizations that covered this problem, but I was miserable so I just patched up my own messy algorithm. What would it do? It would randomly select a 100 characters long string from the current content and search for it in the previous content. If it found it, it would expand the selection and consider it a Reasonably Long Common Substring and work from then on recursively. If it didn't find it, it would search a few times other randomly chosen strings then give up. Well, actually is the same algorithm, made messy and with no extra memory requirements.

It worked far better than I had expected, even if it clearly could have used some optimizations. The code was clear enough in detriment of speed, but it still worked acceptably fast, with no noticeable overhead. After a few tweaks and fixes, the class was ready. I've tested it on a project we are working on, a big project, with some complex pages, it worked like a charm.

One particular page used a control I have made that allows for grid rows and columns to have children that can be shown/hidden at will. When collapsing a column (that means that every row gets some cells removed) the compressed size was still above 50% in up to 100 patch fragments. When colapsing a row, meaning some content from the middle of the grid would just vanish, the size went down to 2%! Of course, putting the ViewState into the session also helped. Gzip compression on the server would complement this nicely, shrinking the output even more.

So, I have demonstrated incredible compression of UpdatePanel content sent through the network with something as small and reusable as a response filter that can be added once in the master page. You could use it for customers that have network bandwidth issues or for sites that pay for sent out content. It would with sites made with one big UpdatePanel placed in the MasterPage as well :).

If you want to use it in your sites, please let me know how it performs and what problems you've encountered.

I have been working on an idea, one that assumed that if you remember the content sent to an UpdatePanel, you can send only the difference next time you update it. That would mean that you could use only one UpdatePanel, maybe in the MasterPage, and update only changes, wherever they'd be and no matter how small.

However, I also assumed that if I set the innerHTML property of an HTML element, the value will remain the same. In other words that elem.innerHTML=content; implied that elem.innerHTML and content are identical at the end of the operation. But they were not! Apparently the browser (each flavour in its own way) interprets the string that you feed it then creates the element tree structure. If you query the innerHTML property, it uses the node structure to recreate it.

So comparing the value that you've fed it to the actual value of innerHTML after the operation, you see quoted attribute values, altogether removed attributes when they have the default value, uppercased keywords, changed attribute order and so on and so on. FireFox only adds quotes as far as I see, but you never know what they'll do next.

On the bright side, now that my idea had been torn to shreds by the browser implementation, I now have an answer to all those stuck up web developers that consider innerHTML unclean or unstructured and criticize the browsers for not being able to render as fast when using DOM methods. The innerHTML property is like a web service. You feed it your changes in (almost) XML format and it applies it on the browser. Since you pretty much do the same when you use any form of web request, including Ajax, you cannot complain.