An average web site offering membership and protected content for its members requires users to sign up by visiting a sign-up or register page that allows a user to enter some information and create an account. A couple of pieces if information that users are commonly asked to enter are a User name or Login name and user's email. One potential problem with such user input is checking that entered login name and/or email address are available for registration and haven't been used by other users. When it's the case multiple attempts of entering available values can be very annoying and frustrating for users even making them to refuse registration on a web site. So improving user experience when validating login name and email is quite an important task.
Sponsored
Wednesday, June 24, 2009
Monday, June 22, 2009
How to set programmatically a value of a watermarked TextBox via JavaScript
$get(textBoxId).value = someText;
then the value displayed in the TextBox on the page will change to the set value but the watermarked look will still be present and other AJAX Control Toolkit TextBox extenders (like a Calendar extender, for instance) will not recognize the new value.
This happens because the TextBoxWatermark extender can not recognize and intercept your JavaScript operation since it's designed to serve user interactions. However there is a correct way of programmatic access to the TextBox's value. We modify the code above like that:
var textBox = $get(textBoxId);
if (textBox.AjaxControlToolkitTextBoxWrapper) {
textBox.AjaxControlToolkitTextBoxWrapper.set_Value(someText);
}
else {
textBox.value = someText;
}
The explanation is that most of the TextBox extenders from the AJAX Control Toolkit including a TextBoxWatermark extender use a special proxy class AjaxControlToolkitTextBoxWrapper to manipulate with the input elements. The proxy adds a special property AjaxControlToolkitTextBoxWrapper to the input element that contains a reference to itself allowing to access the value of the input element correctly. Similarly, if you need to get a value of a watermarked TextBox you do it like this:
var textBox = $get(textBoxId), text;
if (textBox.AjaxControlToolkitTextBoxWrapper) {
text = textBox.AjaxControlToolkitTextBoxWrapper.get_Value();
}
else {
text = textBox.value;
}
Tuesday, June 2, 2009
New version of ASP.NET AJAX Control Toolkit released
The new release of ASP.NET AJAX Control Toolkit is available for download. Bertrand Le Roy has written a very informative post about it.
What I particularly like in this new release is that the Color Picker extender is now included in the Ajax Control Toolkit. Hooray!
Along with the new Toolkit release there come a whole bunch of new tutorials and videos. Among them there are this particularly nice tutorial about the Color Picker extender and another excellent video tutorial by Joe Stagner. Thank you folks for such a great job!
What that means for the Color Picker Extender users is that they don't have to download it separately from Codeplex anymore because it is included in the Ajax Control Toolkit. For those who cannot yet switch to the new version of ACT the original Color Picker Extender control will continue to be available on Codeplex. During the next few days I will prepare and upload a new release synced up with the Ajax Control Toolkit.
It is very educating to read people's opinions about the new release of ACT in response to blog posts and on Codeplex. In general, the responses are positive, but occasionally there are some complaints, mostly about little things.
I would like to remind everybody that Ajax Control Toolkit is a completely community-based initiative (with, of course, the initial kick-off help from Microsoft) and people who work on it take time out of their personal calendars so let's be more tolerant and if you've come across something really bad please use the Issue Tracker.
As I mentioned before, I specifically was interested in reading responses about the ColorPicker. Interestingly, all the complaints were about its look and feel, not about functionality. I admit that the UI it provides is rather simplistic but here is my question back: why don't you all take some time and come up with feedbacks and suggestions on what can be improved?
Since the ColorPicker was publicly available on CodePlex it's been downloaded more then 2000 times (and I don't count downloads of ACT source code) and only a few people suggested something about improving it. I take it as everybody has been satisfied.
Now that the CPE is a part of the ACT and has a bit more visibility I suggest that people who have suggestions or concerns please don't hesitate to speak up.
Wednesday, May 27, 2009
Survey: Ajax usage among .NET developers
The survey:
http://www.zoomerang.com/Survey/?p=WEB22973CYKW2H
Friday, May 1, 2009
Enabling a WCSF solution for sub-Web Application Project
If in your Web Client Software Factory (aka WCSF) solution you use Web Application Project (as opposed to Web Site Project) for your web site you are able to use a so called sub-Web Application Project in order to further modularize your web application.
If you created a WAP WCSF solution from scratch this option will be available. If, however, you converted your Web Site WCSF solution to WAP WCSF solution or upgraded from the previous version of WCSF this option may not appear when you are trying to add a new business module to your solution.
Visibility of the "Create as sub-Web Application Project" checkbox depends on one single property of a solution file and if you don't see the checkbox open the .sln file with any text editor and check out that it contains the follwoing content:
GlobalSection(ExtensibilityGlobals) = postSolution
...
IsWCSFSolutionWAP = True
...
EndGlobalSection
Usually this section is located in the bottom of a .sln file and the red line is the key to solving the problem. If you don't see the line in your solution file simply add it and reload the solution in Visual Studio. Problem solved.
Monday, April 27, 2009
How to Improve ASP.NET UpdatePanel Performance
Since ASP.NET AJAX UpdatePanel was first introduced it has earned a strange mix of reputation. From one hand it has become a tool of first choice for many ASP.NET developers who wanted an easy way of introducing an AJAX-like behavior for their ASP.NET web apps. From another hand it has earned a lot of criticism from seasoned web developers because of certain performance consequences associated with complex usage scenarios.
Well, everything may be good and may be evil based on how we use it. From my experience consious and judicious use of UpdatePanel is the key to saving its benefits and avoiding potential problems.
Below I suggest a number of rules that help achieving better results when using UpdatePanel.
- Avoid automatic refreshing of UpdatePanel; always stay in control of which UpdatePanel and when refreshes: set UpdateMode property to Conditional (the default value is Always).
- Minimize the content of the UpdatePanel: the
<ContentTemplate>should only include controls that are neccessary to refresh. For instance if user input requires server-side validation include only an error message mark-up in the UpdatePanel and leave the rest of the form outside. - Try to keep the partial postback trigger controls outside of their respective UpdatePanels unless its neccessary to change their markup.
- Try to stick to a simple rule: one trigger for one UpdatePanel. If you need to refresh multiple UpdatePanels during one request add a trigger control to only one of those UpdatePanels and refresh the others programmatically in an event handler on the server. The idea is to avoid uncontrollable refreshing of unnecessary UpdatePanels.
- Since ViewState is updated with every partial postback request turn the ViewState off on a page that contains the UpdatePanel wherever possible or store the ViewState on the server to avoid transferring it forth and back with every async request.
- Since Page runs through its lifecycle during every partial postback and executes methods like Page_Load or Page_PreRender make sure that logic that is unneccessary for refreshing UpdatePanel is not executed by wrapping it in
if(!ScriptManager.IsInAsyncPostBack). - If you use UpdatePanel event handlers like Init, Load, PreRender and Unload make sure that code inside these event handlers does not execute unless neccessary by checking
Page.IsPostBackandScriptManager.IsInAsyncPostBackproperties. - If you trigger an UpdatePanel programmatically from the client-side (via JavaScript) make sure that its event handler check for the event trigger value using
Request.Params["__EVENTTARGET"]ot avoid unnecessary execution path. - If you programmatically update Page's Header (Title, etc.) or other Page's content that is outside UpdatePanel make sure that this code never gets executed during partial postbacks. First of all its not neccessary since page does not refresh but also it may be dangerous because the content may not be handled properly by a browser.
Conclusion
There may probably be more tricks and tips regarding usage of UpdatePanel but those mentioned above have been proven by real exeprience. I would also recommend understanding how UpdatePanel works behind the scene and never hesitate using Fiddler to investigate what your web app's doing.
Wednesday, March 11, 2009
Using ColorPickerExtender Client-side Events
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
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); }
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.
