Sponsored

Wednesday, March 11, 2009

Using ColorPickerExtender Client-side Events

There have been question about how to utilize the client-side functionality of the ColorPickerExtender in order to improve customer experience. Here is an example of how to use a colorSelectionChanged client event.

Subscribing to the colorSelectionChanged event

You can subscribe to the event either via JavaScript code or ASP.NET mark-up:

    var cpe = $find("ColorPickerExtender1");
    cpe.add_colorSelectionChanged(changeColor);

Here $find is a standard function of the ASP.NET AJAX Framework that returns an instance of the AJAX component by BehaviourID; ColorPickerExtender1 is a BehaviourID of the ColorPickerExtender component and changeColor is your JavaScript function that will be called when the event occurs.

<ajaxToolkit:ColorPickerExtender ID="defaultCPE" runat="server"
TargetControlID="Color1"
    BehaviorID="ColorPicker1"
    OnClientColorSelectionChanged="changeColor"
/>

Make sure that the changeColor JavaScript function exists on the page otherwise you'll see a JavaScript error "changeColor is undefined". You may define a changeColor function like this:

function changeColor(sender) {
    sender.get_element().style.color = "#" + sender.get_selectedColor();
}

When your function is called after a user picked a color (i.e. clicked a mouse on the color palette) a sender argument will point to the instance of the ColorPickerExtender component that you can use inside your function. For instance, call a method get_element() to retrieve a reference to an input DOM element which the extender is attached to or use a get_selectedColor() method to retrieve a hexadecimal color code that the user selected. When assigning the color value to a DOM element style don't forget to prepend it with a '#' character.

Thursday, January 29, 2009

ASP.NET AJAX Compatibility Patch for Safari 3.x and Google Chrome

The problem I am going to talk about is not new but it somehow managed to concern not so many developers so far. However, it is a growing concern and more people would need a solution at some point.

The heart of the problem is there are two browsers with a growing number of users - Safari 3.x and Google Chrome, that ASP.NET AJAX framework is not compatible with.

One part of the problem is induced by a fact that both browsers report themselves as "Webkit" which is not supported by ASP.NET AJAX. This part of the problem affects both Safari and Chrome users.

The second part of the problem mostly affects Safari users because ASP.NET AJAX framework does "support" Safari (version 2.x) but in such a manner that makes your web application look like a total disaster in Safari version 3.x.

The suggested fix will help both cases. At least my tests showed quite a success. Ideally we would need an official patch from Microsoft but since they have their own plans and busy with the next .NET/ASP.NET 4.0 and VS 2010 I would assume that there will be no fix till those versions are out.

So let's stick to this solution for now. The solutions for the problem were suggested by a couple of people: http://forums.asp.net/p/1252014/2898429.aspx and http://blog.lavablast.com/post/2008/10/Gotcha-WebKit-(Safari-3-and-Google-Chrome)-Bug-with-ASPNET-AJAX.aspx. Since both solutions are absolutely the same I want to give both of them a credit.  
Now to the point, ASP.NET AJAX framework has a class Sys.Browser that represents a current browser and supports cross-browser compatibility for everything else. The solution simply extends the Sys.Browser class to support a Webkitbrowser:

Sys.Browser.WebKit = {};
if( navigator.userAgent.indexOf('WebKit/') > -1 )  {
    Sys.Browser.agent = Sys.Browser.WebKit;
    Sys.Browser.version = parseFloat(navigator.userAgent.match(/WebKit\/(\d+(\.\d+)?)/)[1]);
    Sys.Browser.name = 'WebKit';
}
That is all the code you need. To apply this code to your web application you will need to create a JavaScript file, let's say webkit.js and reference it in your application using standard ScriptManager server control. You can reference the fix as a file using this syntax:

<asp:ScriptManager ID="sm" runat="server">
    <Scripts>
        <asp:ScriptReference Path="~/Scripts/webkit.js" />
    </Scripts>
</asp:ScriptManager>
or embed it into an assembly (my preferred way) and reference it from the assembly as an embedded resource:

<asp:ScriptManager ID="sm" runat="server">
    <Scripts>
        <asp:ScriptReference Assembly="Scripts" Name="Scripts.webkit.js" />
    </Scripts>
</asp:ScriptManager>
Note that when you reference the fix from an assembly don't forget to add an assembly default namespace to the file name in the Nameattribute. In conclusion, according to my tests the fix eliminated problems with UpdatePanel, AjaxControlToolkitand Virtual Earth map control.

Thursday, January 15, 2009

Search Engine Friendly Error Handling

ASP.NET provides a standard way to handle errors in web applications by configuring a customError section in the Web.config file. Standard behaviour is to redirect a user from an erroneous page to an error page that in its turn shows some kind of more or less friendly explanation of what has happened.

 This approach is quite OK for intranet web applications but usually is not appropriate for a public web app accessible for search engines. The main problem here is that when error happens ASP.NET returns 302 "temporary redirect" response redirecting browser to the error page configured in the Web.config

If the erroneous page was accessed by a SE bot the bot would index a content of the error handling page under the original page's URL thus creating a wrong index entry.

Another problem is if the actual error on the page was that the requested content was not found. This scenario is quite regular on modern dynamic web sites that construct content pages dynamically based on a Url. In http world such a situation should be called as 404 "Not found" especially in the case of a bot visiting such a page.

But ASP.NET standard handling will once again respond 302 and let the bot include a not existing page in a search index.

What I am driving at is the correct error handling should always return a corresponding http status code for a SE bot with the appropriate content for the user.

So, how can we do that without writing too much code? Actually quite easy. Starting version 3.5 SP1 ASP.NET has a new attribute redirectMode in the customError configuration section:

<customerrors mode="RemoteOnly" defaultredirect="/errors/GenericError.aspx" redirectmode="ResponseRewrite">
The new redirectMode attribute can be assigned one of two values: ResponseRedirect (default) or ResponseRewrite. ResponseRewrite prevents the erroneous page being redirected with the code 302 to an error page however the content of the error page will be shown on the original page. Internally ASP.NET is doing Server.Execute of the error page instead of Response.Redirect as usual. So this is already a one third of work. The next thing we need to do is to return a correct http status code. It can be achieved by adding a few lines of code to the error page let's say to a Page_Load event handler:
int httpCode = 500;
Exception ex = Server.GetLastError();
if (ex is HttpException)
{
  httpCode = ((HttpException) ex).GetHttpCode();
}
Response.StatusCode = httpCode;
This code checks if the reason of the error was an HttpException (a standard .NET exception class) then it assigns an http code from the exception otherwise it returns 500. Now it's two third of work done. What left is to handle exceptions in your code properly. The best practices here are:
  • If your application can not return a requested content for any reason except your application's internal problems then throw an HttpException with the code 404 and it will be friendly handled by your error page.
    throw new HttpException(404, "Not found");
  • Map other your application's specific exceptions to standard  http codes and return them too.
  • If your application throws an exception internally then wrap the internal exception with HttpException using an appropriate http code.
    try
    {
    ...
    }
    catch (Exception ex)
    {
       throw new HttpException(code, message, ex);
    }
That's basically it. In conclusion just a few more notes. If an erroneous page happened to start rendering content before the error occurred you may want to clear it on the error page before outputting an error message:
Response.Clear();
If for some reason you can not use the new redirectMode attribute in the .config file (older framework, application specifics, etc.) then just add a few lines of code to the global.asax that do the same:
void Application_Error(object sender, EventArgs e)
{
    // Do something with the error, i.e. log, notify, etc. 
    Server.Transfer(errorpage);
}
It may be a good idea to clear an error status on the error page after you're done with error handling:
ClearError();
Now that is all.

Tuesday, December 9, 2008

FIX: HTML documents may not be displayed correctly in IIS 7.0 on Windows Vista

Recently I have finally upgraded to Windows Vista from Windows XP. Except regular trouble of upgrading your operation system that feels like moving to a new house (which is people say worse then an earthquake and flooding together) I was quite frustrated by a number of annoying problems with IIS 7 when first it's not installed by default (all right, security is tougher now, but can I at least have an option?), then not all of the components installed that required by ASP.NET and VS2008 (is it so difficult to suggest a correct package?), then again my web app does not work with the default App Domain (why did you guys call it "default" and the real default call "classic"?), and finally everything works but the site does not look like it should be.

I spent some time probing different setting of IIS and finally gave up and looked it up on the Internet. What a relief! It's a Microsoft bug and not me being an idiot! Actually it was submitted on March 17, 2007 and still not in SP1.

So the problem was that the entire static content of the web app including images and styles was not returning to a browser by IIS (content length 0 bytes) because IIS 7 initial configuration was incorrect when it was first installed on Vista.

I am not describing a fix here, read it here: http://support.microsoft.com/kb/930901/en-us

Wednesday, October 1, 2008

More About Color Picker ASP.NET AJAX Extender

I have published an article on Code Project about the Color Picker ASP.NET AJAX Extender. Please read it there.

Friday, September 26, 2008

Color Picker ASP.NET AJAX extender control

I was looking for a client-side color picker control and found it extremely difficult to find something that would satisfy to my requirements. I have found plenty of pure JavaScript controls written with various levels of proficiency and there was even one ASP.NET color-picker control that I almost liked but still my major requirement was not satisfied: I was looking for AJAX .NET Extender control - easy to use and based on a solid and proven platform.

So, I have researched what other color picker controls do and decided to write the one myself that I would base on Microsoft AJAX .NET platform. After some considerations I've decided to go even further and build an AJAX Control Toolkit Extender control.

As an example I took an AJAX Control Toolkit Calendar extender and in my Color Picker extender control I also internally used another AJAX Control Toolkit control: Popup extender.

Now, what are the advantages of implementing a client control as an ASP.NET AJAX extender?

  1. You use ASP.NET page mark-up to render the control content to the browser.
  2. No need to manually inject JavaScript, HTML and other resources.
  3. You develop JavaScript code in a standalone file leveraging ASP.NET AJAX framework and Visual Studio intellisense abilities.
  4. JavaScript per se is very well structured, easy to read and debug.
  5. Many of the hassles of JavaScript client coding such as cross-browser compatibility, event handling, asynchronous calls are taken care of by ASP.NET AJAX framework.

So, I have spent a few days coding the control and finally it's out there. I have created a Codeplex project for it so if you are interested just go there and download the control and a Demo Web site.

Now, just a few more words about the extender. First, this is how it looks:

Second, it's extremely easy to use. The extender attaches to an ASP.NET TextBox server control and to an optional button that can open a popup window and an element that samples a selected color in the background. User selects a color by clicking on a colored area. Below is a code example of using an extender on an ASP.NET page.

<asp:TextBox ID="TextBox1" runat="server" 
       Columns="7" MaxLength="7"></asp:TextBox>
  <asp:ImageButton ID="ImageButton1" runat="server" 
       ImageUrl="~/Images/icon_colorpicker.gif" />
  <cdt:ColorPickerExtender ID="cpe" runat="server" 
       TargetControlID="TextBox1"
       SampleControlID="ImageButton1"
       PopupButtonID="ImageButton1" />

Feel free to download the extender from the Codeplex, try it and post any comments or suggestions on the Codeplex project page.

Update 2020

Recently, I've visited the old and now archived CodePlex page for the ColorPickerExtender (https://archive.codeplex.com/?p=cpe) and found out that back in the day Microsoft had included that control on the official ASP.NET site (https://docs.microsoft.com/en-us/aspnet/web-forms/overview/ajax-control-toolkit/colorpicker/using-the-colorpicker-control-extender-cs). What a nice thing! Encouraged by this finding I've decided to resurrect the CPE and port it over to Angular, which is currently my favourite client-side framework. I will be introducing a new project on Git some time at the end of 2020, so stay sharp!

Friday, September 19, 2008

Axialis IconWorkshop™ Lite for VS 2008

It's been a little buzz around this free VS2008 plug-in but it really is true and there is a free version of the Axialis IconWorkshop for VS2008. If you want to download and install it please use the direct link because you won't be able to find this page on the Axialis web site. Though to be honest its functionality is not anyhow better then Paint.Net which is also free but fully-functional. Besides being called a VS plug-in it opens up in a separate window. But see for yourself.

Monday, September 15, 2008

Working with VEColor class of VirtualEarth SDK

If you ever wanted to set a color for a custom VEShape object of type polyline or polygon than you must be familiar with the VEColor class that is used to represent a color in VirtualEarth SDK.

I am sure there are reasons behind of the design of the VEColor class, but for those who are used to a standard Web color representation in a form of 6-digit hexadecimal number it's kind of weird to provide 3 integer number in order to construct a color.

So I was in a search for some convenient ways of converting between VEColor and standard Web color and first place I looked through was of course the VirtualEarth Map control because I thought that the VE developers themselves would need a way to perform the same exercise. No surprise there is a couple of non-documented VE objects to support such conversion technique.

Here is a code example of using those objects:

// Create a convertor class
var converter = new VEHexStringToColor();
// Converter returns an instance of a VEColor class
// Transparency value is always set to 1.0
var veColor = converter.Convert("aabbcc");
// Adjust transparency value
veColor.A = 0.7;
// Convert VEColor to a string with a leading '#'
var webColor = VEColorToHexString(veColor);alert(webColor);

Both objects are available on the page after you reference a VE Map control v6.1. Of course there is no guarantee of any support of those objects in any future versions of the VE Map control so use it at your own risk and have fun.

Tuesday, June 17, 2008

Scalable CSS for Ajax Control Toolkit Tabs

If you use Tabs control from AJAX Control Toolkit library you may have noticed that the default CSS definition provided with the control does not display properly when you increase font size on a page, that is the default CSS is not scalable.

Since Tabs allows you to override CSS it's quite easy to fix a problem. Just grab a correct CSS file with the set of images and assign a CssClass property a new class name:

<ajaxToolkit:TabContainer runat="server" CssClass="myTabs" ...>

Now it looks more appropriate: