Wednesday, March 21, 2007

Browser Compatability


As we all know (and don't like it...) different browsers display HTML pages differently. We always work hard to make the pages we write to look good and the same in all browsers, or at least in the more popular ones. Some browsers that we will not mention their name (but they are made by microsoft) show HTML differently even between version. some not-very-sophisticated code works in one version and not in the other, especially new code is not backward competible.


There are two ways to tackle this situation. One is to write "lower denominator code", HTML code that all browsers and versions treat the same, and avoiding code that the browsers show differently. This leaves us with a pretty basic subset of HTML, but it can be done for simpler pages.

The second way is to write browser-specific code. something in the area of "If IE then do this, else if Firefox do that". this should be done only in cases where there is no unified solution that include all browsers.

In order to apply the second solution on the server side i suggest using these components and methods:

Create an Enum for all different supported browsers and version, something like that:

public enum Browsers
{
IE6,
IE7,
Firefox2,
Safari1
}

Create a function that recieves the BrowserCapabilities object included inside every HTTP request, and returns the specific browser and version as one of the Enum members:

public Enums.Browsers GetBrowser(HttpBrowserCapabilities browserCap)
{
string strBrowser = browserCap.Browser;
int majorVer = browserCap.MajorVersion;
return (Enums.Browsers)Enum.Parse(typeof(Enums.Browsers), strBrowser + majorVer.ToString());
}

Use this function to easily create switch cases to handle places that need different treatment for each browser: (In this case i use a negative margin to eliminate a blank area created in the original of a relatively-positioned Div element that includes an overlay image. This bug happends only in IE version 6)
switch (utils.GetBrowser(Request.Browser))
{
case Enums.Browsers.IE6:
divPlayImage.Style.Add("margin-bottom", (0- imgPlay.Height - 3).ToString() + "px");
break;
}

Happy coding,

Benny.

Friday, March 16, 2007

Formatting durations

As the internet gets filled with media files more and more sites need to display the duration of the audio/video file next to the file name and description. We store a file's play duration as a number of seconds in the database. In order to display the duration in a x:xx format we need to format it, using this small function:


private string FormatDuration(short seconds)
{
string result = string.Empty;
int minutes = seconds / 60;
int secondsLeft = seconds % 60;
result = minutes.ToString() + ":" + secondsLeft.ToString("00");
return result;
}

Thursday, March 15, 2007

Parsing tags input using Split function

User input validation is one of the more complex issues in developing a solid data-entry form. Input validation is the basis of application security, database integrity, application stability and more.

Today i encountered an input validation issue regarding the input that users enter as "tags", the popular new type of information used in many User Generated Content (UGC) sites.

When i used the function Split from the String class to parse the tags into an array of strings i found out that if the user entered multiple space characters (eg. "tag1 tag2 tag3") each space from the second one will result in an empty cell in the tags array. Splitting these sample tags will result in this array:
array[0]: "tag1"
array[1]: "tag2"
array[2]: ""
array[3]: ""
array[4]: ""
array[5]: "tag3"

In order to avoid entering blank tags in the database i wrote a simple function that prepares a clean array of tags from the raw tags string. Here it is:
(Besides removing empty cells this function also convert commas to blanks and lowers the case for all tags. This avoids multiple-word tags and case differences, as our project demands)


private string[] PrepareTags(string tags)
{
char[] delim = { ' ' };
//Replace comma with blank
tags = tags.Replace(",", " ");
//Split to array with blank delimiter
string[] tagsArray = tags.Split(delim);
ArrayList tagsList = new ArrayList();
//Eliminate empty cells
string[] preparedTags;
for (int i = 0; i < tagsArray.Length; i++)
{
if (tagsArray[i].Trim().Length > 0)
//Make all tags lowercase
tagsList.Add((string)tagsArray[i].ToLower());
}
preparedTags = new string[tagsList.Count];
tagsList.CopyTo(preparedTags);
return preparedTags;
}


If you find this function useful please comment and tell me.

Monday, March 12, 2007

Cached Ajax Response

On my project i have a nice Upload wizard. It allows a user to write file information while the file is uploading. This page uses Ajax calls in order to communicate with the server while the file is still uploading.

I had strange behaviour with this page...
Sometimes it worked and sometimes not...
While debugging i found out that if i upload the same file twice the second time fails.
After placing breakpoints i found that the Ajax requests that fail never reach the server side.
This fact gave me the idea that the response is being CACHED by the browser.

In order to prevent Ajax requests from being cached by the browser i put these lines in my code before writing the response:

Response.Clear();
Response.CacheControl = "no-cache";
Response.AddHeader("Pragma", "no-cache");
Response.Expires = -1;
Response.ContentType = "text/plain";

This solved the problem entirly.

P.S. If you are asking for static data using Ajax you may want it to be cached on the client to shorten response time. In that case don't use this code.