Posts tagged with webforms

Investigating MonoRail

Fighting WinForms

I hate fighting with a technology to get it to do what I want because it means I either have the wrong expectation or wrong technology.

With web development I expect strict web standard support and clean code that is easy to maintain.

I am, therefore, tired of fighting with WebForms and seeing as I’m not prepared to change my expectation then the technology must change.

Looking at MonoRail

Ruby on Rails is very fast, elegant and powerful but comes with a bunch of unknowns. The IDE’s I’ve tried have been so-so, there is no support for IntelliSense so I’m forced to remember exact property and method names. There are concerns about performance and scalability and I find the Ruby language itself cryptic.

My current .NET environment has all these things, so what I’m really looking for is an alternative to the WebForms element itself. It also has a powerful framework, tons of samples, and C# is not only enjoyable but very in-demand :)

MonoRail seems to be just what I am looking for but there are a number of things keeping me away. I decided to spend an hour watching a screen cast on WinForms and MonoRail from Ayende @ Rahien’s blog. It calmed some concerns but raised a few others…

NHibernate mapping files

NHibernate provides the core ORM system within MonoRail and normally requires XML mapping files to do so.

I really don’t want or need another abstraction layer here – my tables are freshly modeled and represent my domain classes very well. Rails, Subsonic and LINQ to SQL are all happy to just do it/

Thankfully a project called ActiveWriter gives you a very LINQ to SQL-like experience in dragging tables off, changing names and properties if you want and doing the magic for you.

ActiveRecord template

I still don’t like this mix of static and instance methods providing some sort of split between what should really be two classes but I can live with it.

There is also a Repository option mentioned which perhaps solves this, I shall have to investigate it further.

View engines

There are a number of view engines available for MonoRail but the primary ones are NVelocity and Brail.

As I already have C# and JavaScript in my project and I have no desire to add another language unless there is a good reason to do so. If they want to stop people writing too much view code then what is wrong with a subset of C#?

The template engines also mean giving up strong typing (everything is passed to the view in a type-less property bag accessed with a string key!) and a complete lack of IntelliSense (the demo stalls as fields are mistyped on occasion proving just how useful this is).

HTML injection

Yes, in this day and age HTML injection should be a long-dead concern and yet even the built in SmartGridComponent will happily squirt out data without encoding it and thus allowing data from anywhere to contain HTML ready to be injected into an unsuspecting page.

Ayende has investigated the issue now and is working on getting a fix into the tree.


Localizing .NET web applications

It seems that globalization often makes the wish list of many a web site until the client realizes professional quality translations require a significant investment of time and money.

On occasion however smaller web applications with their limited vocabulary are prime targets for localization globalization and it can be quite feasible to translate the couple of hundred strings involved.

Here’s a very brief whirlwind overview of what’s involved.

Create the default language resource file

Create a new folder inside your App_GlobalResources folder to contain your language resource files. Then create a new resource file (e.g. Localization\Language.resx) to use when no translation exists for the user’s preferred language.

Detect the user’s browser settings and switch

In .NET 1.1 this required a couple of lines of code in your global.asa.cs:

public void Application_BeginRequest(object sender, EventArgs e) {
    Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(Request.UserLanguages[0]);
    Thread.CurrentThread.CurrentUICulture = new CultureInfo(Request.UserLanguages[0]);


Sander Rijken points out that .NET 2.0 lets you do this with a line in your web.config <system.web> section instead:

<globalization culture="auto" uiCulture="auto" />

or indeed at individual page level with:

<@ Page ... Culture="auto" UICulture="auto">

Localize the classes

For every bit of code that sets a string that will end up on the user’s display you now have to move that into the language resource file and replace the code with a reference to it. So if for example you had;

if (name.Length == 0) error.Text = "Please enter a name";

Then you move “Please enter a name” into the resource file and give it a sensible key such as NameBlankError and modify the above line to read;

if (name.Length == 0) error.Text = Resources.Language.NameBlankError;

There is a Resource Refactoring Tool to do this for you now! Just right-click the string, choose Extract to resource and fill in the blanks.

Localize the pages

Unlike the WinForms designer the WebForms one doesn’t support multi-language so you’re instead forced to do it by hand. One way is to remove all the text from the page and place it into the resource language file.

Then create a private void Localize() method in each page that simply looks something like;

public void Localize() {
    Title = Resources.Language.LoginPageTitle;
    loginButton.Text = Resources.Language.LoginPageLoginButton;
    reminderButton.Text = Resources.Language.LoginPageReminderButton;

Obviously you need to call this from the page, I find that calling it from Page_PreRender works a treat.

One disadvantage to this technique is your page itself ends up looking very blank in the designer or duplicates text that soon gets out of date. You could avoid this by leaving the default-language text in the page and not calling localize if you are running in that language. Be sure to put “\***” or something in the default language resource file for it though so that if it’s missing for other languages you immediately spot the missing text during testing.

Don’t treat types as strings

If you have a number, treat it as a number and pass it around as a number. The same applies to dates etc.

If you need to pass over to SQL etc. then use a parameterized query, they’re fast and will take care of all the regionalization stuff for you!

To get those pesky strings in and out of the correct types see the following extra steps!

Always use .ToString() to format output

Almost all basic .NET types include locale-aware formatting and so keep an eye on the ToString methods. Remember even numbers are formatted differently across the globe. 1,234.00 in England and the US becomes 1.234,00 in various parts of Europe.

Be very careful of outputting currencies. .NET won’t convert the amount for you but you could easily find yourself with the wrong currency symbol and therefore a totally different price!

Always use .TryParse to read input

When accepting information from users hand over that string to TryParse for it to try and work out what’s going on. It will helpfully return a boolean indicating if it did the job okay – if not time to use that localized error-message.

Auf wiedersehen!