here are so many new features to discuss and master in ASP.NET, this article series may never be finished. Thus far, we’ve covered the following:
This time, I am going to focus on the new Profile service in ASP.NET 2.0 that allows you to build personalizable Web sites. In addition, I will take this opportunity to show you how ASP.NET has simplified the globalization and localization of Web applications.
To illustrate these new features, I will first build an ASP.NET 2.0 Web application that shows how localization is done in ASP.NET 2.0. This application will allow users to choose their preferred language. (In the example, a choice of English or Chinese is offered.)
Once the user has selected a preferred language, you can design your site to display in that language each time the user visits. I’ll show you how to provide that functionality using the Profile service.
Localizing a Web Application
|Figure 1. Control: Populate the default form with the four controls shown.|
To begin, I’ll first build a simple ASP.NET 2.0 Web application using Visual Studio 2005 (Beta 1). I’ll populate the default form with the following controls (see Figure 1):
Populate the DropDownList control with the following items and values:
|English||en-US||Display the page in English|
|Chinese||zh-CN||Display the page in Chinese|
|Auto Select||Auto||Display the page using the language set in IE’s language preference.|
Once the form is populated, you want to create an external resource file that contains all the localized language version information used by the form, such as dates, times, and currency information. Visual Studio 2005 will generate this file for you when you select Tools -> Generate Local Resource (see Figure 2).
|Figure 2. Think Local: You have to generate the local resources your application will need to perform a translation.|
Once the resources are generated, you will find a new folder named LocalResources under your project in Solution Explorer. The Default.aspx.resx file contains resources used by Default.aspx for the default culture (which is English). Right-click on this file and select Copy, and then right-click on LocalResources and select Paste. This new folder will contain the resources for your other language?in my example, Chinese. I named the new file Default.aspx.zh-CN.resx (see Figure 3).
|Figure 3. Adding Languages: The LocalResources folder contains the resource files for the languages you support.|
Figure 4 shows the content of these two resource files. I have changed the content of the Default.aspx.zh-CN.resx file to display Chinese characters. (To follow along you will either need to configure Windows for Chinese input or use a third-party language add-in. For simplicity, you may elect to use a Western language, such as French or Spanish, instead). During runtime, the ASP.NET controls will automatically retrieve the strings stored in the resource files (according to the language preference set in the Web browser). This is known as Implicit Localization.
|Figure 4. West to East: The left side, Default.aspx.resx, contains local resources for English and the right, Default.aspx.zh-CN.resx, contains the Chinese equivalents.|
In ASP.NET 2.0, you can simply add two new attributes?”Culture” and “UICulture”?to the @Page directive of a page and the ASP.NET runtime will automatically localize your application based on the resource files you have created:
<%@ Page Language="VB" Culture="auto" UICulture="auto" AutoEventWireup="false" CompileWith="Default.aspx.vb" ClassName="Default_aspx" meta:resourcekey="PageResource1" %>
To test the application, open Internet Explorer and set your language preference to Chinese by going to Tools -> Internet Options. Click on the Languages… button and select Chinese (see Figure 5).
Once you’ve changed your language preference in the browser, you’re done. The ASP.NET application will now display in Chinese (see Figure 6).
Persisting User’s Preferences
While the automatic localization feature in ASP.NET 2.0 is useful, it would be much more useful if you could let the user choose the desired language while running the application instead of setting it in IE ahead of time. So I am now going to enhance my application to let users choose their preferred language using a drop-down list. In essence, the user can either set the language preference in IE, or he can select the language via the drop-down list control on the page.
Unfortunately, the Implicit Localization method discussed earlier only works when the language preference is set in IE. To let users choose their preferred language without setting the language preference in IE, you need to use Explicit Localization.
To use Explicit Localization, first create a new special folder known as Resources in Solution Explorer. Then add two resource files under the Resources folder (right-click on the Resources folder and select Add New Item…. Select Assembly Resource File) and then populate it with the content shown in Figure 7.
|Figure 5. Picking China: Select Chinese from your preferences in IE to test the localization capabilities you’ve built.|
To remember a user’s language preference, I will use the new Profile service in ASP.NET 2.0. Think of the Profile service as a mechanism to persistently store a user’s information, somewhat similar to the Session object. However, a session object is only valid throughout the entire duration of the session; after the session has expired the Session object is no longer available. The Profile service, however, retains its information for as long as you want, until you explicitly remove it from the data store.
To see how the Profile service work, let’s add the following Profile properties definitions into Web.config:
To use these Profile properties, you can simply reference them like this:
Profile.language = "en-US" Profile.Info.LastModified = Now Profile.Info.DateSelected = Calendar1.SelectedDate
Note that the
|Figure 6. Lost in Translation: The Web application can now translate between two different languages.|
But for right now I just want to use the Profile object to store the user’s language preference. Once the user has selected a language in the drop-down list box and clicked the Set button, I can save the language preference in the “language” property.
Sub btnSet_Click(ByVal sender As Object, _ ByVal e As System.EventArgs) Profile.language = ddlLanguage.SelectedItem.ValueEnd Sub
Also, I can save the date that the user has selected in the Calendar control using the Info.DateSelected property (the use of the Calendar control in this example illustrates how to persist the date data type in the profile property). The Info.LastModified property allows me to express the time and date that the property was last modified:
Sub Calendar1_SelectionChanged(ByVal sender As Object, _ ByVal e As System.EventArgs) Profile.Info.DateSelected = Calendar1.SelectedDate Profile.Info.LastModified = NowEnd Sub
When the page is loaded, I can retrieve the values saved in the Profile object and then set the Calendar control to the date previously saved.
Sub Page_Load(ByVal sender As Object, _ ByVal e As System.EventArgs) Handles Me.Load Calendar1.SelectedDate = Profile.Info.DateSelectedResponse.Write("Date set on " & _ Profile.Info.LastModified)End Sub
To display the page in the language chosen by the user, I have to handle the setting of the current page culture in the Page_PreInit() event (see Listing 1). I’ll walk through the code in this event so you’ll have a better idea of how it works.
First, you declare a variable of type CultureInfo. This variable will hold culture information based on the language selected by the user.
Dim lang As System.Globalization.CultureInfo
The first step is to check if this is a postback. A postback can occur when the user refreshes a page or when the user clicks on one of the controls in the page. If this is a postback, I will check the language selected by the user (through the drop-down list). If the selected language is “Auto” (users can choose “Auto” if they want the language setting to always match the preference set in IE) I do not need to proceed further; the ASP.NET runtime will perform the localization:
'===see if this is a postback=== '---which language did the user select... Dim selectedLang As String = _ Request("ddlLanguage") '---if language is Auto then let the page decide ' automatically If selectedLang = "Auto" Then ddlLanguage.SelectedIndex = 2 Exit Sub End If
If the language selected is not Auto, I will load the culture information from the language drop-down control using the culture code (such as “en-US” and “zh-CN”):
If selectedLang IsNot Nothing Then '---a postback lang = New _ System.Globalization.CultureInfo(selectedLang) Else
|Figure 7. Filling Out: Here are partial contents for the two resource files.|
However, if the page is loading for the first time, I’ll check the Profile object to see if the user has previously saved the language preference. If so, I will use the saved language preference to obtain the culture information, which the user can then immediately change using the language drop-down. As usual, if the language is set to “Auto,” there is no need to process any further.
'====page is loading for the first time==== '---retreive language preference from profile ' obj If Profile.language <> "Auto" Then lang = New _ System.Globalization.CultureInfo( _ Profile.language) Select Case Profile.language Case "en-US" : _ ddlLanguage.SelectedIndex = 0 Case "zh-CN" : _ ddlLanguage.SelectedIndex = 1 Case "auto" : _ ddlLanguage.SelectedIndex = 2 End Select Else '---if language is auto, then exit ddlLanguage.SelectedIndex = 2 Exit Sub End If End If
With the culture information obtained, I can now set the CurrentCulture and CurrentUICulture properties of the current thread to the new language:
'---set the current thread to the selected ' culture System.Threading.Thread.CurrentThread._ CurrentCulture = lang System.Threading.Thread.CurrentThread._ CurrentUICulture = lang
Finally, change the display texts in controls (such as the Label controls) using the localized string (through the Resources class):
'---display localized strings lblWelcomeMessage.Text = _ Resources.Resource.WelcomeMsg.ToString Page.Title = _ Resources.Resource.PageTitle.ToString lblSelectLanguage.Text = _ Resources.Resource.SelectLanguage.ToString
Unlike with implicit localization, we are now explicitly retrieving strings to display from the resource files. This is known as Explicit Localization.
You can now either allow the ASP.NET runtime to automatically localize the Web page for you, or you can use the Profile object to let users select (and persist) their language preference.
Storing Objects in Profile
So far I have limited discussion to the localization process. But I’ll now focus my attention on the Profile properties:
By default, the data type of a Profile property is String. Hence the following properties definitions are equivalent:
However, you can use any data types supported in the .NET Framework. Moreover, you can also use your own custom data type (as long as it is serializable).
Consider the following example. Assume I have a class, Class1.vb, in my project:
_Public Class CombinedInfo Public DateSelected As DateTime Public LastModified As DateTime Public Language As StringEnd Class
I can add a Profile property named combinedInfo of type CombinedInfo:
To use the Profile property, I can save an instance of the CombinedInfo class into the combinedInfo profile property:
Shared cinfo As New CombinedInfo '---set the value of the CombinedInfo object cinfo.Language = ddlLanguage.SelectedItem.Value cinfo.DateSelected = Calendar1.SelectedDate cinfo.LastModified = Now '---assign to the profile property Profile.combinedInfo = cinfo '---retrieve the profile property Dim info As CombinedInfo info = Profile.combinedInfo
Also note the serializeAs attribute. In the above example I set it to “Xml.” This means that the CombinedInfo object would be serialized and persisted as an XML string. Alternatively, you can also use Binary serialization. Do note that for XML serialization only public members are serialized.
Examining the Data Persisted by the Profile Object
Before concluding this article, I’ll examine the data that have been persisted by the Profile object discussed in the above example. As soon as the Profile object is used, an Access database file would be created in the Data folder under your project (default in Beta 1, unless you explicitly specify to use SQL Server for the Profile Provider).
In the ASPNetDB Access database, the aspnet_Profile table shows the information stored by the Profile object (see Figure 8).
|Figure 8. Aspnet_Profile Table: The table shows the information stored by the Profile object.|
There are a few interesting things to note here.
- The PropertyNames field stores the Profile properties that have been saved with their corresponding values stored in the PropertyValuesString field.
- The UserID associated with this Profile object corresponds to my login user name?”WINXP-Wei-Meng Lee” in this case. This is because I am using the default Windows authentication in my application. For the Profile object to work, you need a way to identify a user, either by his login ID (for Windows authentication), or for Forms authentication, you need to explicitly enable anonymous identification so that the ASP.NET runtime can use a GUID as a identifier for an anonymous user:
Up Close and Personal
In this article, I have illustrated several new features in ASP.NET 2.0:
- The use of Implicit Localization to allow Web pages to automatically localize based on the language preference set in IE.
- The use of Explicit Localization to allow users to choose their own desired language without needing to set the language preference in IE.
- The use of the Profile service in storing information input by your users, thereby allowing you to personalize your site.