Monday, October 29, 2007

appendChild fails when using ASP.NET AJAX library

I was struck with a strange behavior when using the ASP.NET AJAX library.

I have a time-proved control that uses AJAX (hand-made) to query a database to retrieve the data as the user types, in other words, an auto complete text box. Multi column, themeable, the works.

Anyway, recently I used this control inside an ASP.NET AJAX UpdatePanel because I needed the ability to hide or display this control in a post back event without refreshing the whole page.

Well, this control of mine creates an hidden DIV that it appends to the body of the document on its initialization phase. However, when loading the page, the entire page fails with an JavaScript exception and the browser navigates to an exception page.

With a lot of tries and errors I managed to work around the issue, but the problem remains.

One other thing I noticed is that for some reason the UpdatePanel has a different hierarchy than the rest of the page.

I don't have time right now to pursue why the ASP.NET AJAX library behaves like this, but I'll look into it in the future.

Wednesday, October 24, 2007

UpdateProgress does not show up when AssociatedUpdatePanelID is set

I'm currently working on a little ASP.NET AJAX project and got stuck with what seems a bug on ASP.NET AJAX UpdateProgress control.

As I've searched through the net (thanks Google), apparently it's really a bug, as you can attest here.

For what I've seen a lot of people have encountered this bug, but no one has attempted to find the root of the problem... until now.

Well, I dug into the ASP.NET AJAX client scripts to find WTF was going on and why the damn control does not appear when it should (as far as the documentation, and expected behavior goes).

With no further ado, here is the code:

function Sys$UI$_UpdateProgress$_handleBeginRequest(sender, arg)
{
var curElem = arg.get_postBackElement();
var showProgress = !this._associatedUpdatePanelId;
while (!showProgress && curElem)
{
if (curElem.id &&
this._associatedUpdatePanelId === curElem.id)
{
showProgress = true;
}
curElem = curElem.parentNode;
}
if (showProgress)
{
this._timerCookie =
window.setTimeout(this._startDelegate,
this._displayAfter);
}
}
OK, so what we have here?

This little function, which is a method of the UpdateProgress client DOM, is the responsible for showing the UpdateProgress control on the client during the asynchronous post back.

When this function is fired it gets the element firing the post back event, then it checks if it has an associated UpdatePanel, if it does not have and associated UpdatePanel it is shown immediately (i.e., after the amount of time specified in the DisplayAfter property).

The problem is when it HAS an UpdatePanel associated.

Unless the control firing the event is a child of the UpdatePanel, the UpdateProgress control will not be shown.

And THAT's the problem.

If the event is fired anywhere else outside the UpdatePanel, no luck.

Yes, I know that I could show the UpdateProgress by calling the async functions, but what the heck?

I didn't have enough time at the moment to goo deep enough to find how it could be fixed, but at least now we have a good explanation WHY the damn panel does not show.

Tuesday, October 23, 2007

Updating ASP.NET projects to AJAX

OK, you have an ASP.NET project and decided to add the AJAX funcionality, using the ASP.NET AJAX 1.0 toolkit.

You downloaded the toolkit, installed, added the System.Web.Extensions reference, and, after you added the ScriptManager in your page, you got a script error telling that Sys was not an object.

Well, grasshopper, there is a little bit more than simply add the reference.

To really convert an ASP.NET application to use AJAX, you need not only to add the reference, but make the following changes on the Web.config file:
  • In the <configSections> add:
    <sectionGroup 
    name="system.web.extensions"
    type="System.Web.Configuration.SystemWebExtensionsSectionGroup,
    System.Web.Extensions,
    Version=1.0.61025.0,
    Culture=neutral,
    PublicKeyToken=31bf3856ad364e35">
    <sectionGroup
    name="scripting"
    type="System.Web.Configuration.ScriptingSectionGroup,
    System.Web.Extensions,
    Version=1.0.61025.0,
    Culture=neutral,
    PublicKeyToken=31bf3856ad364e35">
    <section
    name="scriptResourceHandler"
    type="System.Web.Configuration.ScriptingScriptResourceHandlerSection,
    System.Web.Extensions,
    Version=1.0.61025.0,
    Culture=neutral,
    PublicKeyToken=31bf3856ad364e35"
    requirePermission="false"
    allowDefinition="MachineToApplication"/>
    <sectionGroup
    name="webServices"
    type="System.Web.Configuration.ScriptingWebServicesSectionGroup,
    System.Web.Extensions,
    Version=1.0.61025.0,
    Culture=neutral,
    PublicKeyToken=31bf3856ad364e35">
    <section
    name="jsonSerialization"
    type="System.Web.Configuration.ScriptingJsonSerializationSection,
    System.Web.Extensions,
    Version=1.0.61025.0,
    Culture=neutral,
    PublicKeyToken=31bf3856ad364e35"
    requirePermission="false"
    allowDefinition="Everywhere" />
    <section
    name="profileService"
    type="System.Web.Configuration.ScriptingProfileServiceSection,
    System.Web.Extensions,
    Version=1.0.61025.0,
    Culture=neutral,
    PublicKeyToken=31bf3856ad364e35"
    requirePermission="false"
    allowDefinition="MachineToApplication" />
    <section
    name="authenticationService"
    type="System.Web.Configuration.ScriptingAuthenticationServiceSection,
    System.Web.Extensions,
    Version=1.0.61025.0,
    Culture=neutral,
    PublicKeyToken=31bf3856ad364e35"
    requirePermission="false"
    allowDefinition="MachineToApplication" />
    </sectionGroup>
    </sectionGroup>
    </sectionGroup>
  • Find or create the <httpHandlers> section and then add:
    <remove 
    verb="*"
    path="*.asmx"/>
    <add
    verb="*"
    path="*.asmx"
    validate="false"
    type="System.Web.Script.Services.ScriptHandlerFactory,
    System.Web.Extensions,
    Version=1.0.61025.0,
    Culture=neutral,
    PublicKeyToken=31bf3856ad364e35"/>
    <add
    verb="*"
    path="*_AppService.axd"
    validate="false"
    type="System.Web.Script.Services.ScriptHandlerFactory,
    System.Web.Extensions,
    Version=1.0.61025.0,
    Culture=neutral,
    PublicKeyToken=31bf3856ad364e35"/>
    <add
    verb="GET,HEAD"
    path="ScriptResource.axd"
    type="System.Web.Handlers.ScriptResourceHandler,
    System.Web.Extensions,
    Version=1.0.61025.0,
    Culture=neutral,
    PublicKeyToken=31bf3856ad364e35"
    validate="false"/>
  • Find or create the <httpModules> section and then add:
    <add 
    name="ScriptModule"
    type="System.Web.Handlers.ScriptModule,
    System.Web.Extensions,
    Version=1.0.61025.0,
    Culture=neutral,
    PublicKeyToken=31bf3856ad364e35"/>
  • Find or create the <system.webServer> section and then add:
    <validation validateIntegratedModeConfiguration="false"/>
    <modules>
    <add
    name="ScriptModule"
    preCondition="integratedMode"
    type="System.Web.Handlers.ScriptModule,
    System.Web.Extensions,
    Version=1.0.61025.0,
    Culture=neutral,
    PublicKeyToken=31bf3856ad364e35"/>
    </modules>
    <handlers>
    <remove
    name="WebServiceHandlerFactory-Integrated" />
    <add
    name="ScriptHandlerFactory"
    verb="*"
    path="*.asmx"
    preCondition="integratedMode"
    type="System.Web.Script.Services.ScriptHandlerFactory,
    System.Web.Extensions,
    Version=1.0.61025.0,
    Culture=neutral,
    PublicKeyToken=31bf3856ad364e35"/>
    <add
    name="ScriptHandlerFactoryAppServices"
    verb="*"
    path="*_AppService.axd"
    preCondition="integratedMode"
    type="System.Web.Script.Services.ScriptHandlerFactory,
    System.Web.Extensions,
    Version=1.0.61025.0,
    Culture=neutral,
    PublicKeyToken=31bf3856ad364e35"/>
    <add
    name="ScriptResource"
    preCondition="integratedMode"
    verb="GET,HEAD"
    path="ScriptResource.axd"
    type="System.Web.Handlers.ScriptResourceHandler,
    System.Web.Extensions,
    Version=1.0.61025.0,
    Culture=neutral,
    PublicKeyToken=31bf3856ad364e35" />
    </handlers>
And then, grasshopper, your ASP.NET application will be trully AJAX enabled.

Monday, October 22, 2007

Web Folder Icons

I was just making some house cleaning, i.e., browsing through my computer to delete some unused files when I get a look at the My Web Sites folder inside the My Documents folder. And it has a very ugly icon.

So, I decided to create a new one.

Now, just a bit of warning... I'm not a designer, but I think it was nice enough for me to post here.

Take a look yourselves.

Web Folder Icon 01 Web Folder Icon 02

Sunday, October 21, 2007

I think there's something wrong with Blogger...

This week I'm working on some updates to the projects pages I have on this site. Adding a few tweaks here and there and some minor cosmetics stuff.

One of the stuffs I'm adding are RSS/Atom feeds for the articles I write.

I don't use any fancy editor for the articles I write (I think I'm more like an old-fashioned kind of guy... sometimes I even use Notepad to write some simple HTML... but that's just me :-), so to add the feeds I need to create them myself.

Anyway, to do this I took a look at the Blogger-generated feeds.

Blogger gently provides each blog with two distinct feeds in RSS and Atom formats, as you can see on the picture. And that's what I wanted to add to my articles.

For this blog the address for the feeds are:
As you can see two very distinct files, automatically generated for each entry I write on Blogger.

Or are they?

I'm a curious guy, so I downloaded both files from the website and here are the first lines for each file:

RSS:
<?xml version='1.0' encoding='UTF-8'?>
<feed
xmlns='http://www.w3.org/2005/Atom'
xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/'>
<id>tag:blogger.com,1999:blog-19732699</id>
<updated>2007-10-18T21:53:47.346-03:00</updated>
<title type="'text'">PJ on Development</title>
<link
rel='alternate'
type='text/html'
href='http://pjondevelopment.50webs.com/blog/'/>

Atom:
<?xml version='1.0' encoding='UTF-8'?>
<feed
xmlns='http://www.w3.org/2005/Atom'
xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/'>
<id>tag:blogger.com,1999:blog-19732699</id>
<updated>2007-10-18T21:53:47.346-03:00</updated>
<title type="'text'">PJ on Development</title>
<link
rel='alternate'
type='text/html'
href='http://pjondevelopment.50webs.com/blog/'/>
It's just me or both files are one and the same?

Yes, I've checked the files physically, they are saved in TWO different files. However, the RSS file has the wrong contents.

You can attest this by yourself, just download the files at the links provided and compare.

Saturday, October 13, 2007

I was curious...

about where Google keeps all the space they give...
I finally got the answer from the guys at The Joy of Tech!

Question: How was Windows ME created?

Answer: An unbalanced Balmer's Peak...

Well... at least according to the guys at XKCD.

Some nice tools

Today I was browsing the Net to find some additions to the other parts of my little corner on the web... namely, I was trying to find some fee comments tools and all.

While Haloscan does provide the basics, it lacks the ability to display the comments on the same page where they are related to.

And then through Techcrunch I found what I needed, a simple comment tool that allow me to add comments to any page I want, for a very nice price: Free!

The guys at JS-Kit provides free comments, ratings and pools, free of charge.

I'm currently in the process of updating the other parts of this site and soon you'll be able to see them in action.

Monday, October 08, 2007

Quick Finger!

How fast can you click?

Test your reaction time here.

Sandcastle tweeks

Like I told a little earlier, I'm currently using Sandcastle and SHFB to create my help files, and I think most of us use the <see langword="null"> in our XML docs, hoping that it would be translated into something like "null (Nothing in Visual Basic)".

And when I compiled my help file I found it was being replaced with nullNothing.

Which was not exactly what I was expecting...

So, poking here and there I added the template below to the following Sandcastle file:
Sandcastle\
Presentation\
Shared\
transforms\
utilities_reference.xsl
And that finally translated it right, although not quite using <see langword="..."/>, instead a construct like <langword name="..." />.

<!-- Support for the tag <langword name="" /> -->
<xsl:template match="langword@name">
<xsl:choose>
<xsl:when test="@name='null' or @name='Nothing'">
<span class="keyword">null</span>
<xsl:text> (</xsl:text>
<span class="keyword">Nothing</span>
<xsl:text> in Visual Basic)</xsl:text>
</xsl:when>
<xsl:when test="@name='static' or @name='Shared'">
<span class="keyword">static</span>
<xsl:text> (</xsl:text>
<span class="keyword">Shared</span>
<xsl:text> in Visual Basic)</xsl:text>
</xsl:when>
<xsl:when test="@name='virtual' or @name='Overridable'">
<span class="keyword">virtual</span>
<xsl:text> (</xsl:text>
<span class="keyword">Overridable</span>
<xsl:text> in Visual Basic)</xsl:text>
</xsl:when>
<xsl:otherwise>
<span class="keyword">
<xsl:value-of select="@name" />
</span>
</xsl:otherwise>
</xsl:choose>
</xsl:template>

Sandcastle and HTML Help Builder.

I'm currently creating, what I hope to be, a very professional WebControl, and therefore with all the bells and whistles it can have, and this includes end user documentation.

Writing technical documentation after any software is build is a royal pain in the... well, you know where.

Anyway, I usually write components documentation using the Visual Studio built-in XML comments, which permits me to write the docs as I work in the means and bits of the software.

So far so good, but when I needed to create the actual help files, I got stuck.

Then in order to produce the help files I shop around for a nice documentation automata.

My first thought was the West Wind HTML Help Builder which I used when I worked on a small company some years ago. Back then it provided me with a very nice experience creating help files.

However, it was not the winner because it works by importing and exporting the XML comments to its proprietary format, and when importing the XML comments back into the code it messes up with them.

One thing must be said about the West Wind company, though, it has one of the best relation with the costumer I've ever seen in any software company.

When I wrote complaining about the issues I was having with their products, the Developer Manager himself wrote me back, in a matter of hours and reported every single issue I had with, either a 'thank you for the feedback it will be taken in consideration for a next release' or a 'oops, my bad, that was not supposed to happen', and not with some automated anonymous reply. If I ever have a software company, I'll make sure that my costumers will be treated the same manner.

I got side tracked... Let me get back to the business.

My second attempt was with NDoc, an open source help builder, that interprets the XML comments and render them in a help file.

It was nice and easy but the main developer kill the project after some personal problems, as reported here. I understand his motivations, and fully support it.

And it was reading the note about the death of NDoc, that I learned about Sandcastle.

Sandcastle is package of command line utilities to create help files from the XML comments, completely automated and customizable.

Command line utilities are good, but if you throw in some GUI makes them even better, and that's what Eric Woodruff did. He created the Sandcastle Help File Builder, or SHFB for short.

It really improved my day, and made my help files to be created simply at the push of a button.