Localizable entities with Nhibernate Part 1

In a recent project I face the need to localize some entity with nhibernate. First of all I found this interesting post of Ayende that show an interesting solution, but it does not fits well in my project. I need a localization scheme with these features.

  • Orthogonal to the user, and completely transparent
  • The user should be able to change localization text
  • The user can choose whathever language he desires, if no suitable localization exists the entity must returns a default localization
  • The user can add a new localization language for the entity even if the language is not actually present.

At first these features seems very complicated, and I begin to work on a possible scheme that satisfies all of them. First of all the concept of current language should be orthogonal to the user, it means that the user should ask nhibernate to load an entity without worrying of the language. This kind of problems can be solved by the Registry pattern from Fowler (POEAA). This pattern description states: “A well-known object that other objects can use to find common objects and services”, this seems to me a suitable pattern to store the concept of “Current Language”. First of all I create the interface of my Registry in another assembly.

public interface IRegistry {
LangCode CurrentLangCode { get; set;}
LangCode DefaultLangCode { get; set;}
}

As you can see this registry has only two property that can be used to get/set the current language and the default language, both of them stored as a custom LangCode object. I prefer to use a LangCode custom object because I’m working with a legacy database that stores lang code strings with char(5) fields, so if I simply use a string to store current lang code I’ll end in comparing “it” with “it ” because the database pads the string with space chars, due to the fact that the fields are fixed length strings. LangCode class is a very straightforward one:

public class LangCode : IEquatable<LangCode> {

internal LangCode() {
}

public LangCode(String langcode) {
mCode = langcode.Trim();
}

public String Code {
get { return mCode; }
set { mCode = value.Trim(); }
}
private String mCode;

#region Static lancode

public static LangCode It = new LangCode(“it”);
public static LangCode En = new LangCode(“en”);
public static LangCode De = new LangCode(“de”);

#endregion

#region IEquatable<LangCode> Members

public bool Equals(LangCode other) {
return String.Compare(this.mCode, other.mCode, true) == 0;
}

public override bool Equals(object obj) {
if (obj == null) return false;
if (obj.GetType() != typeof(LangCode)) return false;
return Equals((LangCode) obj);
}

public override int GetHashCode() {
return mCode.GetHashCode();
}

#endregion
}

I simply implement IEquatable interface and Equals() method, I also trim all lang code so I can use my legacy database that stores codes in fixed length string columns. To access Registry I simply used Windsor container and a static class:

readonly static IRegistry sRegistry = IoC.Resolve<IRegistry>();

static public LangCode CurrentLangCode {
get { return sRegistry.CurrentLangCode;}
set { sRegistry.CurrentLangCode = value; }
}

static public LangCode DefaultLangCode {
get { return sRegistry.DefaultLangCode; }
set { sRegistry.DefaultLangCode = value; }
}
}

This makes possible to use different concrete classes to implement the registry, for example for a web application I can store the current language in user session, while for simple windows application I simply set the language programmatically by code in member variables.

public class WinFormRegistry : IRegistry {

public LangCode CurrentLangCode {
get { return mCurrentLangCode; }
set { mCurrentLangCode = value; }
}
private static LangCode mCurrentLangCode = LangCode.En;

public LangCode DefaultLangCode {
get { return mDefaultLangCode; }
set { mDefaultLangCode = value; }
}
private static LangCode mDefaultLangCode = LangCode.En;
}

With castle Windsor I can specify in the app.config or web.config the right concrete class to use, this makes my Registry very flexible. Now the first point is satisfied, I have a registry that can be accessed from any class that needs to know current language or default languages. In the next post I’ll show you a possible scheme to handle a fully featured localized entity.

Alk.

Localizable Entities with Nhibernate – Part 2
Localizable Entities with Nhibernate – Part 3

Windsor Container, Resolve(IDictionary)

Castle framework is really interesting, but do not forget to checkout current trunk in subversion repository, since it is full of new and exciting features. In a little demo that I’m doing to made a screencast for dotnetmarche community, I show how to structure a simple web page to follow Design For Testability principles, and I made a really basic example of a page with a controller. Since the controller needs to use the session I abstracted the session with an interface

public interface ICustomWebContext {

    void AddToSession(String key, Object value);
    Object GetFromSession(String key);
    void ClearSession();
}

I admit that this is not really an exceptional interface J but it will live only for the sake of my screencast. Using this interface I can abstract the concept of session, so the controller is not forced to run inside a live asp.net application. For the website I plug into controller a simple class that simply stores objects into HttpContext.Current.Session, while for test I can use a simple Dictionary<String, object>. To assemble the object I use Windsor container, since it is lightweight and simple to use, but I need to use the current version in the trunk, since rc2 missed a functionality that I love too much. Here is the problem, page controller has this signature

public Page4Controller(IPageAddition page, ICustomWebContext context) {

it needs an instance of the IPageAddition interface, that abstract the methods of the UI interface and also need a concrete implementation of context. I need to create an instance of the Page4Controller whenever the page needs to perform some operation, and I need to pass the instance of the current page and the context. The page is different at each time while context is a singleton class. First I create a little helper class for Windsor

public static class IoC {

    private static IWindsorContainer _container =
         new WindsorContainer(
            new XmlInterpreter(new ConfigResource(“castle”)));

    public static T Resolve<T>() {
        return _container.Resolve<T>();
    }

    public static T Resolve<T>(string name) {
        return _container.Resolve<T>(name);
    }

    public static T Resolve<T>(params object[] values) {

        System.Collections.Hashtable arguments = new System.Collections.Hashtable();
        for (Int32 I = 0; I < values.Length; I += 2) {
            arguments.Add(values[I], values[I + 1]);
        }
        return _container.Resolve<T>(arguments);
    }
}

This is only a matter of convenience, the third resolve method is the interesting one, because it use container.Resolve<>(IDictionary) method, that is able to construct an object and lets the caller pass some of the dependencies. Caller code creates a Page4Controller object in this way.

Page4Controller controller = WebSite.IoC.Resolve<Page4Controller>(“page”, this);

Caller specify that the page argument should be passed the current instance of the page, while all other argument are passed according to the setting in config file.

<component
   id=PageControllerForPage4
   service=WebLogic3.Page4Controller, WebLogic3
   type=WebLogic3.Page4Controller, WebLogic3
   lifestyle=Transient/>
<
component 
         id=WebContext
         service=WebLogic3.ICustomWebContext, WebLogic3
         type=WebLogic3.StandardWebContext, WebLogic3 
         lifestyle=Singleton/>

 

As you can see I specifify that the Page4Controller class has a lifestyle of transient, because I need a fresh controller at each page postback and the ICustomWebContext dependency is satisfied by the StandardWebContext class. With this useful feature, we can use object with mixed dependencies, some of them will be resolved by Windsor according to the configuration file, while some others are resolved directly by the caller.

Alk.

Again on dynamic control creation in asp.net 2.0

In a previous post I explain best practices to follow when dealing with dynamic controls in asp.net 2.0, but I missed one important point. Try to insert this snippet of code in a blank page

   Protected Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs)
      Trace.Warn(
“clicked button “ + DirectCast(sender, Button).Text)
   
End Sub
 
   
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
      CreateButtons()
   
End Sub
 
   
Private Sub CreateButtons()
 
      
If Not Me.IsPostBack Then
         
Dim button As New Button
         button.Text = 
“Bottone che poi scompare”
         
AddHandler button.Click, AddressOf Button1_Click
         Page.Form.Controls.Add(button)
      
End If
      
Dim button2 As New Button
      button2.Text = 
“Button2”
      
AddHandler button2.Click, AddressOf Button1_Click
      Page.Form.Controls.Add(button2)
   
End Sub

In this code we create two buttons dynamically during the get of the page, but in each subsequent post only one button gets created, because IsPostBack is true. The behavior of the page can be surprising, pressing “button2” the first time does not fire the Click event, but subsequent clicks work as ususal. The problem is due to the fact that during the first rendering there are two buttons on the page, the first click does the first post on the page, now the code creates only one button and when the asp.net engine check the post variables to look for any event to be generated find this post variables (Sniffed with Fiddler).

__VIEWSTATE=/wEPDwUJNzgzNDMwNTMzZGQ=

Ctl23=Button2

As we can see the button is called ctl23 because it does not have an id, but when the page render in the first postback the first button does not gets rendered, so the button with text “Button2” now has Id Ctl22, and no event can be generated. In subsequent call the name of the control does not change so no problems happen. As a proof of this theory try to create the two buttons in this way.

      Dim button2 As New Button
      button2.Text = 
“Button2”
      
AddHandler button2.Click, AddressOf Button1_Click
      Page.Form.Controls.Add(button2)
      
If Not Me.IsPostBack Then
         
Dim button As New Button
         button.Text = 
“Bottone che poi scompare”
         
AddHandler button.Click, AddressOf Button1_Click
         Page.Form.Controls.Add(button)
      End If

The only differences is that the button that gets created only in the first call now is created after the button with text “Button2”, this means that the id of the button with text “button2” is Ctl22 at each post and all works as expected.

The obvious solution to this kind of problems is to assign an unique ID to each dynamically generated control so the id in the page will be unique and no problem will arise if controls tree change at each postback.

Alk.

 

Dynamic creation of controls in asp.net 2.0

Today I was discussing with a friend about dynamic creation of control in asp.net 2.0 pages. It comes out that the matter is not so easy. The first question is when the controls must be created to work correctly in page lifecycle? The story start with this snippet

protected void Page_Load(object sender, EventArgs e) {
   
this.form1.Controls.AddAt(0, new Button());
   
if (!IsPostBack) {
      DropDownList1.Items.Add(
“Value 1”);
      DropDownList1.Items.Add(
“Value 2”);
      DropDownList1.Items.Add(
“Value 3”);
 
   }
}

This code is wrong, if you run the page you can see that when the button is pressed the dropdownlist does not retain the values from the viewstate. The problem arise from the fact that asp.net 2.0 engine restore controls value from the viewstate following the ordinal position of the controls in the form. In the above example, at load we creates a button that is inserted as the first control of the form, subsequently viewstate is created. At this moment page layout has one button at position 0 and a ddl at position 1. When we do a postback, before load the asp.net engine restore the viewstate, but since restoration is done by ordinal position, at this moment the button is not still created, so the viewstate of the button is restored on the ddl. Possible solution are:

Create the controls in page_init event, in this way all dynamic controls are created when the viewstate is restored. This approach has the side effect that in init event the viewstate cannot be accessed because is not still restored

Add the control at the end of the page, so the order of controls does not change.

Use a placeholder or a panel control, position the placeholder where you want the control to be created and then add the control to controls collection of the placeholder.

Solution number 3 is the best, you can choose where to position the dynamic control and you can create the control on load event, when the viewstate was restored and all other control can be accessed without problem. A little question remains, how can a control created after the restore of the viewstate can retain its value between postback? Lutz Roeder’s Reflector comes to help. If you check the add method of ControlsCollection class you can notice that this function calls AddedControl() method of the owner control. This means that when we add a button inside a placeholder the AddedControl of the placeholder gets called. Inside the AddedControl we can see that the viewstate of the added control gets restored explicitly, so it can work as expected.

When you need to create dynamic control in a page, to avoid any problem, use placeholder controls to host dynamically created controls.

Alk.

Pay attention to Membership.GetUser()

Yesterday I was looking at database usage made by some pages of a project that I’m coordinating. With the profiler I saw with horror that a page made about 40 query to the asp.net user database at every post or get. Inspecting the code I realized that the developer has inserted some row based logic for a gridview, He handled the RowDataBound event (fired once for each row) and in the code He calls Membership.GetUser(). Since most of the major scalability problems with asp.net applications derive from I/O it is better to reduce the calls to membership API function. A possible solution is using the session to cache user data, or if the session is not a suitable choice, it is possible to use httpcontext, in this way if a page is composed by several user control, and each one needs to interact with the membershipuser object, only the first call goes to the database, and subsequent one will find the object in memory.

Alk.