Translating an Asp.NET site to Another Language Using .resx Files

translating the .resx files to another language does not require any programming knowledge at all

Translating a properly globalized site in asp.net is simple and does not require the least bit of development knowledge... which is good, because most developers I know barely have a grasp on their own [non-programming] language. This post should probably come after one on how to globalize your asp.net site, but I have an urgent need to explain how to do this first (someone has volunteered to translate my open-source project Slick-Ticket to Spanish; thanks Victor!).

how does it work?

First of all, you should understand how this actually works, it may make it easier. Every page in a site has access to two types of resources (when I say resources here I am referring to strings, words or phrases): Global Resources, and Local Resources - these resources are held in .resx files. Global Resources are commonly used resources that all pages can see, and Local Resources are resources that only a specific page can see. Each language/dialect has a specific code, which you can see here: Language Codes (you can see your default setting in your browser options, for IE, check Tools->Internet Options->Languages). Each page then has place-holders where it will substitute a specific language's resource if it is available. For example, if your browser's settings are set to Mexican Spanish (es-mx) and you are trying to view example.aspx, asp.net will look for the example.aspx.es-mx.resx file to fill in the text. If that file is not present, it will default back down to the default resx file which is example.aspx.resx.

simple enough, how do I edit them?

.resx files are just xml files, and can be edited in a text editor, but that can be very confusing and error prone as there is no syntax and/or structure checking. I recommend you use a program such as Visual Studio if you have it, or Visual Web Developer (free) if you don't; alternatively, there are a few more options such as Mads Kristensen's .NET resource editor application for .resx files, and Resx Editor on SourceForge.

Once you have your editor, just go through and edit the column to be translated, and *ONLY* that one column, messing with the key/name field will break the translation completely.

folder structure

This is the only part that might be a bit confusing. Each folder that contains .aspx, .ascx, etc. files (files with words to be translated) will have their own App_LocalResources folder, and in this folder, there will be a corresponding *.aspx.resx file for each file. Also, any additional languages will be held in a folder with the language abbreviation, and a corresponding file for each file as well. For example, in the admin folder shown here, you can see that it has it's own App_LocalResources folder, in that folder is each corresponding default (in blue) .resx file and there is a folder for each additional language. Here you see the en-us folder (English - United States) and in that you see the same .resx file, but each is named *.en-us.resx (in red) instead of just *.resx. This is the same for each folder, so you will see many App_LocalResources folders. If you forget to change any of them, it will be pretty apparent when you run the program and a lot of stuff does not match up.

Then there is the App_GlobalResources folder in the root; the same thing applies here, just do the same and translate the value column.

Remember that asp.net will first look for your desired language, and use it if it is there, if not, it will drop down to the default.

a couple notes

A couple things to keep in mind, if you see any html markup (not the best practice, but sometimes necessary), remember this:

<do_not_edit>edit_this</do_not_edit>


Also, if you see brackets with a number in them (i.e. {0}, {2}, etc.), be sure to leave those, the developer is using that as a word placeholder.

that's it

Now, as long as it is available, your users will see your site in their preferred language. It is a bit tedious to translate, but much easier than walking through the markup and screwing things up that way. Also, if a resx file is ever missing, it will not error out, it will simply use the default for any parts that are not available.

'System.Web.UI.WebControls.ListItem' in Assembly 'System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' is not marked as serializable

Error drove me nuts... simple solution

You get this error when you are trying to Bind a DropDownList in a GridView, but the problem is that you are using the wrong property to bind it...

instead of:
SelectedItem='<%# Bind("some_value") %>'

use this:
SelectedValue='<%# Bind("some_value") %>'

Simple, but easy to overlook.

FormFields for ASP.net - New Open Source Project

transform and simplify your markup by allowing inclusion of form validation, uniform display, Linq-to-SQL integration and databinding with minimal effort

ASP.net forms are already simple, there are many tools such as DetailsView, ListView, etc. that can make our lives easier, but sometimes they just won't do. In those cases, we have to resort to writing repititous code for forms, that is what FormFields was developed for. Writing markup over and over for things such as validation, regular expressions, dropdownlist databinding, etc gets old really fast, so I developed a way to simplify it as much as possible.

Take for example a date entry field. You have your TextBox, then the CompareValidator to make sure it's a valid date, then a Mask to limit the user's input, a RequiredFieldValidator to make sure they enter something, a WaterMarkExtender to guide the user and finally a CalendarExtender to make input easier.

Now this is great stuff for a UI, and not too hard to write, but when you have to do more and more entry fields such as SSN, phone number, a dropdown, then a CheckBoxList; building forms can quickly become cumbersome and hard to understand, become incredibly tedious and turn into a ton of markup.

This is the markup required to do everything mentioned above:

<div class="form-field">
  <h3>
    <asp:RequiredFieldValidator ID="rfvSchoolDate" runat="server" ControlToValidate="txtSchoolDate" ErrorMessage="Required" CssClass="right validate" Display="Dynamic" />
    <asp:CompareValidator ID="cvSchoolDate" runat="server" ControlToValidate="txtSchoolDate" ErrorMessage="Invalid Date" CssClass="right validate" Display="Dynamic" Operator="DataTypeCheck" Type="Date" />
    School Date
  </h3>
  <asp:TextBox runat="server" ID="txtSchoolDate" CssClass="full" />
  <ajax:MaskedEditExtender ID="meeSchoolDate" runat="server" Mask="99/99/9999" MaskType="Date" TargetControlID="txtSchoolDate" />
  <ajax:calendarextender runat="server" id="calSchoolDate" TargetControlID="txtSchoolDate" Format="MM/dd/yyyy" PopupPosition="TopLeft" />
  <ajax:TextBoxWatermarkExtender ID="tweSchoolDate" runat="server" TargetControlID="txtSchoolDate" WatermarkCssClass="light full" WatermarkText="mm/dd/yyyy" />
</div>


All of that can be replaced with just this:

<formField:textBox ID="tb_SchoolDate" runat="server" Type="Date" Required="True" Title="School Date" />


Yes, it is just that easy. The payout and styling is all inherited from a single class and is easy to customize while making for uniform displays. There are multiple different presets for it including SocialSecurityNumber, Date, ZipCode, and a ton more.

This is not only for TextBox fields, it also works for CheckBox, DropDownList, ListBox, CheckBoxList and RadioButtonList. And it not only formats everything the same and takes care of validation (anything that is not automated can be easily added) but it also takes care of databinding as well. Instead of making a datasource, adding an initial entry, binding it to the data and adding a RequiredFieldValidator, you can simply do this:

<formField:dropDownList ID="ddl" runat="server" Title="Category" L2STableName="categories" Required="True" />


No DataSource needed, it is all taken care of within the control itself (this is using Linq-to-SQL and the defaults).

documentation and download

I just wanted to give a quick overview of what it does, I have it fully documented and have more examples here: http://formfields.naspinski.net and it is available for download from CodePlex. I hope some people get some use out of this and I would love if people would want to jump in and add new features.

stuff I still want it to do

It does not render in the designer, and you can't put them into the toolbox - I do not know how to do this just yet, I would love for someone to jump in and help out on this one!

I am taking a much needed 30 day vacation, so no new posts/updates will be happening for a while, but I will be right back to advancing this project when I get back.

Shout it kick it on DotNetKicks.com

MCPD 3.5 Certified

took the 70-567 upgrade test today

The test was suprisingly easy compared to the tests required to get the MCPD 2.0. As long as you have been using 3.5 features such as Linq, some WCF, etc. you should be fine in taking it. A lot of the questions weren't even 3.5 specific, many were simple 2.0 stuff that should be trivial if you already have the MCPD.

There were a couple tricky ones that confused me a bit. Whitout getting into too much detail, I will say that there are questions with more than one correct answer, though one may not be as 'ideal' as another, so here you would have to pick the 'most correct' answer. Also, there was a definite typo that threw me off... remember Microsoft: 'asymmetric encryption' is one-way, I think you got mixed up there.

Oh yeah, I passed :)

Asp.Net vs php : speed comparison

why is the myth that php is faster than Asp.Net so prevalent? Asp.Net is faster than php, here are the facts

So many times I have heard php pushers claim that php is so much faster than Asp.Net and that Asp.Net is clunky and slow. The most annoying part is that everything I have read (that is not factless opinion), and I mean everything, says that this is wrong; but for some reason, this myth is widely accepted. It has become a religious argument that ignores the facts.

Instead of arguing this point over and over, I decided to put it here so I can simply refer people to it to set them straight. Keep in mind that I wrote strictly php for over 4 years, it is a great and powerful language that I have nothing against. Not to mention you should not choose your development language by speed, but by what works for you (more on that later). This post is not there to pick sides (though I am now Asp.Net biased of course), just to show the facts.

compiled vs interpreted languages

First of all, at the very base of the argument it has to be realized that the two languages are very different. Asp.Net is an optimized and compiled language, meaning code you enter is reduced to a set of machine-specific instructions before being saved as an executable file. Even if you do not explicitly compile your code before you deploy it, it compiles the first time it is run, then after that it runs as compiled code. Php on the other hand is an interpreted language, meaning it is saved as the code your write and run directly from that code. It is widely accepted and proved many times over that Compiled programs generally run faster than interpreted ones because interpreted programs must be reduced to machine instructions at runtime. Here is a quote from Wikipedia that shows just how much faster they can be: "A program translated by a compiler tends to be much faster than an interpreter executing the same program: even a 10:1 ratio is not uncommon. The mixed solution's efficiency is typically somewhere in between."

the numbers

Now that the theory of why it is faster is out of the way, let's get to some cold hard numbers, so we can put this debate to rest.

The following charts and benchmarks are taken from WrenSoft and quite simply show the difference. Please follow the link if you want an in-depth description of the test.

This first graph shows the time taken to generate and display results for a search a small website.


As you can see, the average time for the php site: 0.1500 seconds, the time for Asp.Net: 0.0150 seconds... that is a HUGE difference, the php search takes 10 times as long! The next one does the same with a larger site, and the results are not much different.


Php took an average of 1.0097 seconds while the Asp.Net run took 0.0810 seconds; php took more than 12 times as long to run, the numbers are there.

Now those tests were run with basically the same code translated into different languages, so there isn't much ammunition in the 'it was coded poorly' argument. But, there is still the [valid] argument that the above tests were run on a Windows machine, and since .Net is native to Windows, it was an unfair trial, so now we will look into the statistics running on Linux, so php will have the 'home-field' advantage; not to mention, c# will be running on Mono.

These benchmarks are taken from shootout.alioth.debian.org who has numerous benchmarks for all sorts of languages and is a fantastic resource. For these tests, I am choosing to compare both vs the baseline of 'Clean' so it is easier to compare; here are the results:






As you can see, even on Linux, .Net is faster across the board; often many times faster. The only other tests I can think would be interesting to run is to compare scalability and such; I would be very interested if anyone has benchmarks for such things.

can we finally focus on what matters?

Go ahead and google asp.net vs php speed and you will see that almost all of the posts scream that php is faster, but you will not find any links or evidence backing this up. The whole point of this for me is not even really to show that that Asp.Net is faster, I already knew that; it is to possibly help curb the ridiculous assertions that it is faster. It has basically turned into a religious argument, not a fact based one and that is just silly to me. As in many other things, it seems as if enough people yell something long and hard enough, it becomes 'truth' - it simply is not.

Developing in php is fine, a huge number of amazing applications and websites are written in it by much more skilled coders than myself. That said, you shouldn't choose your language on speed, as development preference is much more important; use php if you feel it is a superior language, but don't push bad information. Most importantly focus on what matters: code in what language you can do your best work in, you don't need to justify it to anyone else, prove that it is faster/better or convert anyone else to using you language - you have better things to do.

But... Asp.Net is faster than php. Period.

Shout it kick it on DotNetKicks.com

Using html label tags with asp.net

I am amazed to see how many asp.net programmer do not use this

The label tag is extremely useful and easy to use, it boggles my mind why more Asp.Net devs do not use it. Remember, I am talking about the html label tag, not the asp.net asp:label which produces a span.

what does it do?

Many of you probably know what it does, but many may not. Quite simply, it makes bunch of text clickable for the related form element. For example, here I am not using a label:
Click Me:

As you can see, you need to click on the textbox itself to get focus on it, clicking on 'Click Me' does nothing. Below, I am using a label tag around the title:

how do I use it?

The syntax is simple! For regular html, this is all you need to do:

<h5><label for="txt">Click Me:</label></h5>
<input id="txt" type="text" />


For asp.net markup, it's a little more, but still incredibly simple:

<h5><label for="<%= txt.ClientID %>"></label></h5>
<asp:TextBox ID="txt" runat="server" />


Notice that some inline magic had to be done to account for the sometimes crazy nested control names that asp.net can dish out. This works for any kind of form element, it's great. Some asp.net controls like CheckBox, RadioButton, etc. employ it with the 'Text' property, but controls like DropDownList, TextBox, etc. do not.

so why aren't you using it?

Make your users lives just a little easier and go wrap all of you form element titles in label tags, it's stupid not to.

EDIT: As Frederik pointed out below, you can use the asp:label if you set the AssociatedControlID which will work just as well. I just prefer to use the html label tag as it is less markup; thanks Frederik!

Extensions for simplifying DropDownList interaction

Extensions for setting the selected value and removing an item from DropDownLists

I love extensions, they make my life so much easier. Simple things that I can do in a coupole lines of code, I now do in even fewer thanks to my almighty extensions. Here are a couple of super simple ones for easy interaction with DropDownLists

setting the selected value

Sometimes it is a pain to set the selected value of a DropDownList, if it is there, it works fine, but if not, it is a pain in the butt. Here is what I use to set mine:
DropDownList1.Set("some_value");

It's just that easy, and if it's not in the ddl, it will work just as well. Here is the extension code:
public static void Set(this DropDownList ddl,
 string findByVal)
{ // attempts to set a DDL to the 'findByVal'
  try
  { 
    ddl.SelectedIndex = ddl.Items
     .IndexOf(ddl.Items.FindByValue(findByVal)); 
  }
    catch { };
}

removing an item

Once again, we all know the code for this, but an extension makes it easier, and also hanldes it if the item is not there:
DropDownList1.RemoveItem("Any");

And the code:
public static void RemoveItem(this DropDownList ddl, 
 string item)
{
  try { ddl.Items.Remove(ddl.Items.FindByText(item)); }
  catch { }
}

Normally I discourage a blank catch{} but in this case, the only error you would be encountering is if the item is not there, so unless you are worried bout that, you should be fine.

Store update, insert, or delete statement affected an unexpected number of rows (0). Entities may have been modified or deleted since entities were loaded. Refresh ObjectStateManager entries.

Confusing error while using an EntityDataSource with a GridView update

Linq-to-Entities baffled me yet again today. I was simply trying to bind an EntityDataSource to a GridView then do an update. It worked as expected, even with the foreign keys... but that was only if I used the auto-generated columns. When I tried to make the fields myself with TemplateFields, all hell broke loose and this error popped up.

While this may make sense to some people, it made none to me, so I basically just started changing things one-by-one until something broke. When I changed AutoGenerateColumns to 'false' it would break. But... if I added in a BoundField that had the primary key in it, it would work? Ok, great, but I didn't want the user to see the primary key field, they don't care about it, so I set that BoundField to Visible="false"; it broke again.

solution

You need to explicitly include a BoundField of the primary key! Since I didn't want the user to see my primary key, I had to resort to hiding it via css:

<asp:BoundField DataField="my_primary_key" ItemStyle-CssClass="hidden" HeaderStyle-CssClass="hidden" />


Where 'hidden' is a class in css that has it's display set to 'none'. Not sure why Entities can't figure this out like all the other DataSources...

Installing ELMAH for simple error logging

This is easily the simplest error logging method I have ever used - it is fantastic!

Error logging is one of the necessary evils of programming. No matter how good you think your program is, it is going to have errors (even with my code, which is flawless... ha). If you are not logging errors some way, you should be, right now!

ELMAH is an error logging framework for Asp.Net and it literally could not be easier and more convenient. You can go from reading this post to having ELMAH logging your errors, publishing RSS feeds and all sorts of other crap in a matter of 5 minutes. This tutorial deals with SQL Server, but you can also store your errors in many other ways such as XML, memory, Oracles, etc. - most of them are well documented... did I say this tool is awesome yet?

get what you need

Go to the download page and download whatever version you want; I am using 1.0 BETA 3. Then simply copy the (the proper one based on your .Net version) Elmah.dll to your bin folder; that's really all you need to do. Alternatively, if you you double-click on demo.cmd it will lauch a demo with Cassinni - I was very impressed with this little added functionality!

make your error logging table is SQL

Pretty much a no brainer here: there is a file called SQLServer.sql in the db folder you just downloaded; run it on the database you want to store the errors in. I used an existing DB so I could just reuse permissions and connectionStrings.

set up your web.config

Just a few changes to your web.config, and you will be up and running. First, add this into your <configSections>:

<sectionGroup name="elmah">
  <section name="security" requirePermission="false"
    type="Elmah.SecuritySectionHandler, Elmah" />
  <section name="errorLog" requirePermission="false"
    type="Elmah.ErrorLogSectionHandler, Elmah" />
  <section name="errorMail" requirePermission="false"
    type="Elmah.ErrorMailSectionHandler, Elmah" />
  <section name="errorFilter" requirePermission="false"
    type="Elmah.ErrorFilterSectionHandler, Elmah" />
</sectionGroup


Next, add this new section directly below your <configSections>:

<elmah>
  <security allowRemoteAccess="yes" />
  <errorLog type="Elmah.SqlErrorLog, Elmah"
    connectionStringName="some_con_string" />
</elmah>


Be sure to set this up with the proper connectionString. Note that I allow remote access, be sure to change this if you don't want to. Now go into the <httpHandlers> section and add this:

<add verb="POST,GET,HEAD" path="elmah.axd"
  type="Elmah.ErrorLogPageFactory, Elmah" />


And the last thing you need to do is add this to your <httpModules> section:

<add name="ErrorLog" type="Elmah.ErrorLogModule, Elmah" />


you are now logging errors

No need to do anything else. Now just navigate to ~/elmah.axd and you will see your error log. All unhandled errors will be logged, no matter what your customErrors is set to! Also, if you want to log handled errors you just grab them with this:
ErrorSignal.FromCurrentContext().Raise(ex);

Where ex is your Exception.

I can't give enough praise for this tool, it is just awesome! Much better than my crappy home-brewed error logging and so much more easy to use.