Tuesday, January 29, 2008

Write your own DOM friendly extension methods for HtmlElement in Volta

logo-volta

I know there are GetById, GetById<> methods in Document object. But, I often miss a method that I feel should be in Volta, which iterates through its child nodes and find an element for me. Let us say, there is a HTML like the following:

<div id="divContainer">
<
b>Some text</b>
<
div id="firstDiv">
<
i>Some more text</i>
</
div>
<
div id="secondDiv">
Okay, I gotta go now
</div>
<
div anyAttribute="anyValue">
Babye
</div>
</
div>

The most important thing is, I can not get the last div by Document.GetById, because instead of id I chose anyAttribute. So, I wrote my own extension method which can run into not only Div but also any HtmlElement, and can find me the desired HtmlElement inside the prior one with the anyAttribute and anyValue. To make my intention clear, I'd like to show how I'd like to use that extension method:

var divContainer = Document.GetById<Div>("divContainer");
var anyDiv = divContainer.Find<Div>("anyAttribute", "anyValue");

if(anyDiv != null)
anyDiv.InnerHtml += "guys!";

So, I'd like to call my extension method Find<> which will take the type I'm looking for (in this case a Div) and that HtmlElement should have an attribute "anyAttribute" that contains "anyValue". Here is how I make up the extension method:

public static class HtmlExtensions
{
public static T Find<T>(this T parent, string attribute, string value)
where T : HtmlElement
{
var element = parent.FirstChild;

while(element != null)
if (element.IsProper<T>(attribute, value))
return element as T;
else
element = element.NextSibling;

return null;
}

public static bool IsProper<T>(this DomNode element, string attribute, string value)
where T : HtmlElement
{
if (element.GetType() == typeof(T) &&
element.Attributes != null &&
element.Attributes.GetNamedItem(attribute) != null &&
element.Attributes.GetNamedItem(attribute).Value == value)

return true;

return false;
}
}

This method can iterate only one depth. Multi depth implementation can be done by running a simple DFS which is left to you guys. Note one thing, I have called one extension method "IsProper" inside another extension method, and there is no harm in it. So, this is how you can add your own extension methods to the HtmlElement.

Saturday, January 26, 2008

Appearing on Microsoft Volta team blog

Microsoft Volta team blogged about me and one of my articles: http://labs.live.com/volta/blog/Volta+How+To+Flickr+Widget.aspx

VoltaTeamBlog

[New Article] ASP.NET AJAX Best Practices

While we develop AJAX applications, we often carelessly ignore giving up bad practices, which cause effects which are not so significantly visible when the site is not so large in volume. But, it’s often severe performance issue when it is the case for sites that make heavy use of AJAX technologies such as Pageflakes, NetVibes etc.

There are so many AJAX widgets in one page that little memory leak issues combined may even result the site crash into very nasty “Operation aborted”. There are a lot of WebService calls, lot of iterations among collection so that inefficient coding in a whole lead to make site very heavy, browser eats up a lot of memory, requires very costly CPU cycles, and ultimately causes unsatisfactory user experience. In this article many of such issues are demonstrated in the context of ASP.NET AJAX.

http://www.codeproject.com/KB/ajax/AspNetAjaxBestPractices.aspx

Friday, January 25, 2008

HttpRequestFactory vs. XMLHttpRequest in Volta

HttpRequestFactory was designed for use by tiersplitting internally and was not supposed to be exposed as part of the Volta API as Danny van Velzen from Microsoft Volta team told me today. So, its better if you use XMLHttpRequest instead because this factory class might not show up in the later releases. You will find this class in Microsoft.LiveLabs.Volta.Xml namespace.  As like as JavaScript's one, in this .NET version you can also Open URL, specify method name, and of course pass credentials. You can track response text, xml, status code, status text and also you can abort.

To retrieve your content, you must subscribe to ReadyStateChange event with a HtmlEventHandler which you can find in Microsoft.LiveLabs.Volta.Html namespace and check the status code. If it is 200 that means "HTTP OK", you can take the ResponseText or ResponseXML. See this example:

string content = string.Empty;
var request = new XMLHttpRequest();

request.ReadyStateChange += delegate()
{
if (request.Status == 200)
content = request1.ResponseText;
};

request.Open("POST", "http://tanzimsaqib.com/feed/", true);

However, you cannot fetch cross domain content by XMLHttpRequest. The Volta compiler creates client side JavaScript XMLHttpRequest and lets developers write code in .NET friendly way. So, I do not think there is any way to retrieve cross domain content in Volta, and leaving us on the same old HttpRequest class.

Friday, January 18, 2008

[New Article] Building a Volta Control : A Flickr Widget

This is my first article which is based on the first CTP of Volta considering its current limitations. You will see how you can create a Volta control that the compiler can convert into an AJAX Widget without requiring us writing a single line of JavaScript code: http://dotnetslackers.com/articles/aspnet/BuildingAVoltaControlAFlickrWidget.aspx

Monday, January 14, 2008

ASP.NET AJAX Best Practices: Avoid String concatenation, use Array instead

Don't you think the following block of code has written keeping every possible good practice in mind? Any option for performance improvement?

function pageLoad()
{
var stringArray = new Array();

// Suppose there're a lot of strings in the array like:
stringArray.push('<div>');
stringArray.push('some content');
stringArray.push('</div>');

// ... code edited to save space

var veryLongHtml = $get('divContent').innerHTML;
var count = stringArray.length;

for(var i=0; i<count; ++i)
veryLongHtml += stringArray[i];
}



Well, as you see the innerHTML of the div has been cached so that browser will not have to access the DOM every time while iterating through stringArray, thus costlier DOM methods are being avoided. But, inside the body of the loop the JavaScript interpreter has to perform the following operation:



veryLongHtml = veryLongHtml + stringArray[i];



And the veryLongHtml contains quite a large string which means in this operation the interpreter will have to retrieve the large string and then concatenate with the stringArray elements in every iteration. One very short yet efficient solution to this problem is using join method of the array like the following, instead of looping through the array:



veryLongHtml = stringArray.join(''); 



However, this is very efficient than the one we were doing, since it joins the array with smaller strings which requires less memory.

ASP.NET AJAX Best Practices: Avoid String concatenation, use Array instead

Don't you think the following block of code has written keeping every possible good practice in mind? Any option for performance improvement?

function pageLoad()
{
var stringArray = new Array();

// Suppose there're a lot of strings in the array like:
stringArray.push('<div>');
stringArray.push('some content');
stringArray.push('</div>');

// ... code edited to save space

var veryLongHtml = $get('divContent').innerHTML;
var count = stringArray.length;

for(var i=0; i<count; ++i)
veryLongHtml += stringArray[i];
}



Well, as you see the innerHTML of the div has been cached so that browser will not have to access the DOM every time while iterating through stringArray, thus costlier DOM methods are being avoided. But, inside the body of the loop the JavaScript interpreter has to perform the following operation:



veryLongHtml = veryLongHtml + stringArray[i];



And the veryLongHtml contains quite a large string which means in this operation the interpreter will have to retrieve the large string and then concatenate with the stringArray elements in every iteration. One very short yet efficient solution to this problem is using join method of the array like the following, instead of looping through the array:



veryLongHtml = stringArray.join(''); 



However, this is very efficient than the one we were doing, since it joins the array with smaller strings which requires less memory.