Search This Blog

Thursday, March 11, 2010

Don't try to access controls in InitializeCulture()

InitializeCulture() is an empty protected virtual method in the Page class. So it is empty in the inherited class too that the IDE generates. When overriding it there is no need to call the base method.

What is noteworthy is the fact that is IS VERY EARLY ON, in the page lifecycle. Way before any controls exist. So most postback handlers that depend on controls are worthless for setting the culure in the thread, BECAUSE THEY ARE ALL LATE.

So how do we do a dropdown or a listbox to switch languages? Isn’t the dropdown a server control? Here is the magic that keeps so many people, that are enamored with localization, stumped.

There is a Http collection called the “form data set”  which is passed in every request. It is a name value collection. The keys are the name attributes of the html elements in the form tag. The values depend on the element. For a dropdown that value is the selected value (if no value, then the selected text, if none then the first item) These are what is known as “successful control” rules. At the time of submission the browser gathers up these values and submits the collection along with the request.

Notice no aspnet so far. The aspnet representation of that collection is the HttpRequest.Form property. Its type isSystem.Collections.Specialized.NameValueCollection and thenicest thing is, IT HAS NOTHING TO DO WITH SERVER CONTROLS. How do we know? Just try retrieving the values from a regular html form element without runat=server and you will know; all without the aspnet runtime doing anything more than reading the browser request.

So we get it for free, and we get it right away and we get it every time.This is the key concept. Plus the collection items map to form elements. So we can grab values out of it inside the InitializeCulture() method and never wait for the full controls to be built. The HttpRequest is exposed as the Request property of the page class.

the server control
<asp:DropDownList runat="server" ID="ddl" AutoPostBack="true" />

renders as the html element, with both the name and value attributes the same(provided not declared in a template like a user control or a master page)
<select name="ddl" id="ddl">

Here is a sample of that code.   Here is a video demo

EVERY PAGE NEEDS THE THREAD SET DE NOVO, because the thread dies at the end of the page lifecycle. So it becomes a pain to do this code over and over again. We can inherit from our own page class that overrides this method and never have to see it from code behind. The problem is that OO intimidateas the hell out of newbies. Also the class would be too closely coupled with the form element under question and I myself have a paranoia of coupling business logic. User controls and master pages do not support the InitializeCulture() method.
So System.Globalization is really in the way of code globalization! ;)
Here is a solution how to do a language switch dropdown in a master page with globalized code.

Happy Dotnetting... :)

1 comment:

  1. Thank you so very much!! I've been struggling with this for over a day and I'm on a tight schedule! Thank you again!

    Who knew InitializeCulture was called very early on that no controls were created yet, yet you could access them via their html rendition?! Brilliant!


Leave your suggession & comment...