Wednesday, January 28, 2009

SQL Server Management Studio not installed with Sql Server 2005 Installation

I came across this problem when trying to install Sql Server Management Studio and other client tools. Basically, for many different reasons, Management Studio and other client tools will not install after you've installed SQL Server 2005 server components. The error that is thrown is below -

Name: Microsoft SQL Server 2005 Tools Express EditionReason: Your upgrade is blocked. For more information about upgrade support, see the "Version and Edition Upgrades" and "Hardware and Software Requirements" topics in SQL Server 2005 Setup Help or SQL Server 2005 Books Online.
Build version check:
Your upgrade is blocked because the existing component is a later version than the version you are trying to upgrade to. To modify an existing SQL Server component, go to Add or Remove Programs in Control Panel, select the component you would like to modify, and then click Change/Remove.


A screen shot of this problem is here:



The problem here is basically that SQL Server 2005 installer seems to think that a higher version or something of SQL Server is already installed on this machine and therefore blocks the current installation by disabling the checkbox that could've made all our lives much easier.


sql-server-2005-management-studio-installation


As the obvious rectification step, I tried to find that missing prior installation of SQL Server but as expected, it was nowhere to be found and also for some reason this problem can't always be rectified by reinstalling SQL Server. So, we can't uninstall the previous version that SQL Server installer thinks is already there and we are stuck. So what gives? It turns out that we can set SKUUPGRADE to 1 while installing from the command prompt - E:\>setup.exe SKUUPGRADE=1 - This enables that silly checkbox to allow installation (or upgradation) of the client components. Below is how this command prompt looks on my system for reference -


sql-server-2005-management-studio-installation


Once you run the installer with SKUUPGRADE ON, you should be able to see the option to install SQL Server Management Studio in the installer. Below is a screen shot that shows how it looks now (please ignore the Integration Service thing as that's disabled in the picture for an entirely different reason) -


sql-server-2005-management-studio-installation


Now when you click Next, you should see the below -


/sql-server-2005-management-studio-installation


Now click "Install" button and install the client components! But why is it so, how would a normal user know that he needs to do it via command prompt with some flag, why isn't that flag available as some advanced installation option in UI itself  and why doesn't the error message provide some info about this possible (and in many cases, only) solution? Well, I've to say that Microsoft and specifically whoever designed this Sql Server 2005 installed must be [...fill this one yourself...]

Saturday, January 17, 2009

Fetching Page Titles using jquery Ajax - RSH page title implementation

How to fetch Titles of HTML pages from URLs using jquery-ajax


There are many cases when we want to know the Titles of HTML pages without actually visiting them. One particular instance of this problem is when we are using RSH (Really Simple History). This is because with RSH and/or Ajax page navigation, the page never reloads and so browser never changes the title of the page either. In this case, we need to programmatically fetch the titles and update the current page title with the fetched one.

Unfortunately, there is no really clean way of fetching a page title through javascript other then fetching the whole page through Ajax and then parsing the HTML to extract the title. This is the technique that I'm going to elaborate on in this article.

Using jquery, the lines of code required is deceptively simple though! You can get the whole thing done, from fetching the HTML and updating the current title, in just about 2-3 lines of code! Below is how -

$.get('yourlink.com', function(data){
document.title = data.toString().substring(data.toString().indexOf("<title", 0) + 7, data.toString().indexOf("</title", 0));
});

Yes, that was it! I used jquery's $.get(link, callback) method that gets the contents of the link (passed as the first argument) through Ajax and then I just extracted the page title from the fetched HTML by javascript String.substring(indexStart, indexEnd) method. You'll also notice that the $.get()'s callback has the argument called "data" that contains the returned or fetched HTML for the provided link. It works fine performance wise as well as we are not really doing any resource intensive operations on the fetched HTML (like displaying it somewhere, for example)

Another thing I'd like to note is the use of String.substring() method. It's not the cleanest way of doing it and a more "correct" way is to use javascript regular expression as in the below example -

document.title = data.toString().match(/\<title\>(*)\<\/title/);

But the problem is that javascript has some limitations when it comes to regular expressions and the above code throws a invalid quantifier error. So, I decided to use the substring method in this case.

To find how to use RSH (Really Simple History) to solve Ajax back button problem, click - Implementing RSH (Really Simple History) for Ajax driven pages

To learn how to call webservices easily using jquery and JSON, click - Calling Webservices with jquery's Ajax and JSON without using ASP.NET's ScriptManager

Thursday, January 15, 2009

The Controls collection cannot be modified because the control contains code blocks (i.e. <% ... %>)

The Controls collection cannot be modified because the control contains code blocks (i.e. <% ... %>)

So recently, I got the above error while trying to inject some dynamic tags into the head section of an ASP.NET 2.0 master page. Turns out that it's not possible to write a code like Header.Controls.Add(yourControl); if you are using code blocks to refer to stylesheets and js files and such -


<link href="<%= ResolveUrl("~/css/style.css") %>" rel="stylesheet" type="text/css" media="screen" />

<script type="text/javascript" src="<%= ResolveUrl("~/js/json.js") %>"></script>
. etc

So what gives? The most obvious solution is to of course get rid of code blocks but that's not always possible and might break some references if the user lands at some subfolders etc in your website.

Next solution is to use databinding....i.e., replace "<%=" with "<%#" in the code blocks. So the above css and js references become the following -


<link href="<%# ResolveUrl("~/css/style.css") %>" rel="stylesheet" type="text/css" media="screen" />

<script type="text/javascript" src="<%# ResolveUrl("~/js/json.js") %>"></script>
. etc

Since we are basically using the data binding expression "<%#" now for the head tag, you need to call the DataBind method after replacing "<%=" with "<%#" . That's just one extra line of code in your page load method -

protected void Page_Load(object sender, EventArgs e)
{
.....
.....
Head1.DataBind();
}

And, that's all there is! Problem solved!

Wednesday, January 14, 2009

javascript error invalid quantifier in string.match regular expression

Yesterday I was trying to write some little regular expression to extract the title of a page from it's html and got the below error -

invalid quantifier *)\<\/title

The actual code that generated this error was the following -

data.toString().match(/\<title\>(*)\<\/title/);

The code works just as expected and extracts the page titles but it seems javascript doesn't support back references or something and that results in the "invalid quantifier" error in both Firefox and Internet Explorer.

Anyhow, I replaced it with a substring (looking for <title and <\/title) and that works fine too. But if you know how to write a regular expression that does it without throwing this error, please share....

Tuesday, January 6, 2009

Could not load file or assembly System.Web.Extensions Version=1.0.61025.0 Culture neutral PublicKeyToken or one of its dependen

So today I tried to download and compile one of my old ASP.NET projects on a new system and ran into a host of errors! First I thought someone had made changes and checked in buggy code but Vault showed no changes for a few weeks! Among others was the below error -

Could not load file or assembly 'System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=
31bf3856ad364e35' or one of its dependencies. The system cannot find the file specified. C:\Users\Owner\Documents\Visual Studio 2005\Websites\...\web.config

The culprit here is the System.Web.Extensions DLL from the old 1.x version (as the error message indicates). And the solution is to just download and install the Ajax extensions (ASP.net Ajax).

The fun part though is - why Ajax extensions are required at all? That project doesn't use any of the Ajax controls! So why do we need to install an additional library? I guess it's because of the ASP.net Menu control being used in the project. But anyways, the solution is simple so let's just implement and get over with it!

Ajax Extensions can be downloaded from - ASP.NET AJAX 1.0

Once you download, install and restart your system, this particular error should disappear.

In some other cases though (specially for ASP.net Ajax Extensions 3.5 library), the installation doesn't seem to register the DLLs in GAC (Global Assembly Cache). If that happens, just register the following files in GAC -

System.Web.Extensions.dll (this is that ASP.NET Ajax Extensions file)
System.Web.Extensions.Design.dll
Microsoft.Data.WebClient.dll
Microsoft.Data.Web.dll
Microsoft.Data.Web.Design.dll

Please note that some of these files might already be registered in GAC so it might help to look them up first. Also, as you might already know, when checking if the file exists in GAC, always look at the name AND the version of the assembly because in .NET, just the name doesn't uniquely identify an assembly or DLL (this is how we can have System.Web.Extensions.dll Version 1.x and System.Web.Extensions.dll Version 3.x in the same folder in GAC).

So that should take care of the "Could not load file or assembly 'System.Web.Extensions, " error for all versions of System.Web.Extensions.dll

Happy coding and a very wishing a very happy 2009 to you!

To learn how to manage history with Ajax without using ASP.NET ScriptManager, click - Ajax History back button with RSH (Really Simple History)

To see a performance comparison of UpdatePanels with RSH, click - ASP.NET Ajax UpdatePanel slow performance compared to jquery and RSH - When to use and not use UpdatePanels

To learn how to catch textbox change event without using ASP.NET Ajax, click - Textbox onchange event in javascript / client side

Thursday, January 1, 2009

Handling textbox onchange event in javascript

How to detect a change in textbox (or html input) on the clientside (javascript)? This is a common problem when we want to do something as soon as textbox (input box) change "event" is fired.

Different ways textboxes (input fields) can be changed

1) Textbox change event fired by keyboard,

2) Textbox change event raised because of copying into textbox via ctrl-c and ctrl-v (and mac equivalent)

3) Textbox change event raised by copying into textbox via context menu (right mouse click and then left mouse click)

4) Textbox change event fired by Autofill applications - this is often overlooked and difficult to control because the user could be using a variety of form filling applications out there including roboform, google's autofill, yahoo's autofill and so on.

5) Textbox change triggered by the history stored by the browser - This is browser specific (firefox, safari) but still tricky as user hasn't typed anything, he/she has just moved focus to the textbox (via mouse click, tabs etc) and selected the values present in history by either mouse click or pressing enter key!

Specific example: We have a textbox (input field) for zipcodes and as user finishes typing the zipcode we want to update city and state fields to show the city/state for the entered zipcode. This is useful for doing a dynamic real time validation as well so that we can tell the user that his zipcode is invalid as soon as he enters it.


Possible solutions

1) Textbox onblur event - This is very good and works most of the time. But it'll be fired even if you move your mouse over the textbox so if your textbox change event handling mechanism involves any graphical changes (making things visible/invisible etc) then it might be disruptive.

2) Textbox mouseout event - Works but not a complete solution as you need to handle keyboard and copy paste events too. Further, mouseout event is triggered when user clicks somewhere outside the textbox and not when he finishes typing! So, if your text change handler does things like updating another controls etc based on the new text in the textbox, then it won't work.

3) Textbox onchange event - By far the best if combined with some additional code to disable copying/pasting something in the textbox. The copying/pasting can be easily handled in windows by detecting and invalidating control key press. One example of the code would be -

function OnTextChange(obj, e)
{
var isCtrl = false;
if(window.event) {
key = e.keyCode;
isCtrl = window.event.ctrlKey
}
else if(e.which) {
key = e.which;
isCtrl = e.ctrlKey;
}
if(isCtrl)
return false;
}

Code presented above is not optimal and works only in windows but just to give some idea. Further, we still have the Autofill or Form filling applications or selecting the value from history (firefox) that can still change the textbox without triggering any event.

4) Some browser specific solutions - onpaste attribute for input boxes (textbox) in firefox and I believe some safari specific attributes are also present. Some autofill variety of attributes are also present that can stop the autofilling for the whole form.

5) In the context of ASP.net, one solution is to put the textbox in an updatepanel and catch the textbox's server side change event! But in my view UpdatePanels can get very slow in a variety of cases and severely disrupt the user experience and are recommended only if the scope is limited, user responsiveness is not a huge problem or you have a reason to believe that the they will perform consistently across all browsers and operating systems.

Most solutions work as a combinations of above and by limiting the ways the user can actually enter the data, might solve the problem of handling the onchange event. I personally think that limiting the ways user can enter the data again disrupts the experience by violating the principle of least surprise! A user who is used to copying/pasting the SSN, zipcode or address (or any difficult to type/remember field) might hit back if ctrl-v doesn't do anything ("form is broken"). Another user who relies on autofill / form-fillers a lot might again abandon the form midway. Allowing the user to freedom to use whatever tools he wants to use to complete the form will obviously result in better results.


Final Solution for detecting any type of change in textbox

So, as you can see the core issue is that there is no textbox change event built in the browsers! This is logically so too because browser has no way of knowing when the user has finished changing the textbox other then some out of focus or mouse out events but they don't help us if we want to handle the textbox change immediately after use has finished it.

This is more of a hack and not a very neat / clean solution but the good news is that it takes care of *all* scenarios in which the user can change a textbox! Keyboard, mouse, pasting, selecting from history, autofill - they will all be handled perfectly without compromising user's experience.

The basic premise is to check the textbox for any changes every 1-2 seconds and if any change is detected, trigger the onchange event handler. Sample code is below -

1. Include this code in your scripts section -

<script language="javascript" type="text/javascript">
checkLastTextBoxValue($("[id$=textBox]").val());
</script>

This will basically run the checkLastTextBoxValue function as soon as the page is loaded. "textBox" is the id of your textbox (or input field) control. I've added the $ sign to take care of the ASP.net's textbox control's client id issue.

2. A sample function definition would be as follows -

function checkLastTextBoxValue (oldValue)
{
if($("[id$=textBox]").val() != oldValue)
{
if(String($("[id$=textBox]").val()).length == 5) //This is for USA zips
{
zip = $("[id$=textBox]").val();
textBoxOnChangeEventHandler(zip);
}
}
setTimeout("checkLastTextBoxValue('" + $("[id$=textBox]").val() + "')", 1000);
}


This code has three things to be noted -

a. if($("[id$=textBox]").val() != oldValue) - we compare "old value" with the "current value" in the textbox to simulate "onchange" event for the textbox! Not elegant but crafty and wickedly accurate!

b. textBoxOnChangeEventHandler(zip); - we do what needs to be done after we have "detected" a change in the textbox here.

c. setTimeout("checkLastTextBoxValue('" + $("[id$=textBox]").val() + "')", 1000); - pretty much the core of this textbox change event handling mechanism, this basically sets up the checkLastTextBoxValue function to run after a second. This doesn't eat up or block CPU though as we are taking 1000 milliseconds worth of break (and it can be more depending on our requirement) between the calls.

So after much research and caffeine, I figured that this is the most robust and user-responsiveness-friendly solution for detecting textbox or input field changes.

Feel free to comment.