Changhong's Technical Blog

  Home  |   Contact  |   Syndication    |   Login
  13 Posts | 0 Stories | 82 Comments | 3 Trackbacks

News

Archives

Post Categories

Blogs I read from kiwis...

Blogs I read...

Saturday, November 29, 2008 #

In my previous post, I discussed how return statement is executed in try-finally clause. So in following program:

            string str = "original string";

      try {

            return str;

      } finally {

            str = "changed in finally";

      }

 

the original value will be returned instead of the value changed in finally block. Would this feature be useful anywhere? Well, I can’t find anything in C#, but I can think up an example in javascript.

 

First, let’s have a look of following javascrip code:

            function createDiv() {

            var div = document.createElement("div");

            div.onclick = function () {  }

}

 

This looks quite ordinary javasript code, doesn’t it? But can you spot a potential memory leak in the code?

 

To prove there is a memory leak, let’s just open following html page in IE7:

<html>

  <body>

    <script type="text/javascript">

      function createDiv() {

        var div = document.createElement("div");

        div.onclick = function () {  }

      }

      for (var i = 0; i < 100000; i++) {

        createDiv();

      }

    </script>

  </body>

</html>

 

 

This is what happened after I refreshed the page a few times. For each refresh, the memory usage was increased by approximately 100M, and it would never go down. Even I went to another page or closed the tab page, the memory was still held by IE7. Shut down IE is the only way to reclaim the memory back! (Note: this memory leak won’t happen in firefox 3)

The cause of the memory leak is circular reference. As you may know, calling a javascript function will create an object.  This object is not accessible from your code, but it is used for javascript to maintain its scope chain. So, in the code above, when createDiv is called, a scope object is created which has a property “div” which points to a div object created by document.createEmelemt(“div”).  Then “div” object’s onclick property is assigned with a function object defined inside function “createDiv”.  As the function for onclick lives inside the closure, it has a reference of its parent scope object. So, have a look of the following picture, there is clearly a circular reference. That's why it causes memory leak.

 


So, how can we fix the problem? Of course, the easiest way is to assign div = null or move onclick function outside the createDiv like this:

 

function createDiv() {

            var div = document.createElement("div");

            div.onclick = function () {  }

            div = null;

}

 

or

 

function createDiv() {

            var div = document.createElement("div");

            div.onclick = handleClick;

      }

function handleClick() {};

 

But what if onclick need to access a variable defined in createDiv and you want to return div from createDiv? Now, try-finally will help.

 

function createDiv() {

            var div = document.createElement("div");

            var greeting = "hello world!";

            div.onclick = function() { alert(greeting); };

            try {

                  return div;

            } finally {

                  div = null;

            }

      }

 

Now, in the try block, div is returned properly, and the link between createDiv scope object and div object is guaranteed to be broken by assigning createDiv’div variable (note, it is just the div variable, not the div object itself) to null in the finally block.

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

Friday, November 28, 2008 #

If you see some code like this, you know there is something very wrong.

 

 

Why on earth should I have to deal with System.Xml, System.Threading, System.IO, System.Diagnostics, System.Runtime.InteropServices, System.Security.Cryptography, System.Net, System.Net.Sockets in a Form class?

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

Thursday, November 27, 2008 #

So what is the output for following program?

public class SimpleTest

{

      public static void Main(string[] args) {

            Console.WriteLine(GetString());

            Console.ReadLine();

      }

     

      private static string GetString() {

            string str = "original string";

            try {

                  return str;

            } finally {

                  str = "changed in finally";

            }

      }

}

It looks very simple, but most of my developer friends and I all had the wrong answer. In the college, we were all told that finally block is guaranteed to be executed before a method returns, right? So it should display “changed in finally”, shouldn’t it? Unfortunately, this is a wrong answer. The program will actually print “original string”!

So, why? The answer is pretty simple. Though “return str;” is just one statement in C#, it is made of a few IL instructions. So if we have a look the complied IL code, the program first loads the “original string” and stores it in location0, then in the try block, it loads the value from lcoation0 and then store it into location1. In the finally block, it loads string “changed in finally” and store it to location0. And at the end, it loads the value from location1 onto stack for return value and exits the method.

So we can simply put, the string “original string” is prepared for return before the finally block gets executed, that is why the “original string” was returned from the method.

.method private hidebysig static string  GetString() cil managed

{

  // Code size       24 (0x18)

  .maxstack  1

  .locals init (string V_0,

           string V_1)

  IL_0000:  nop

  IL_0001:  ldstr      "original string"

  IL_0006:  stloc.0

  .try

  {

    IL_0007:  nop

    IL_0008:  ldloc.0

    IL_0009:  stloc.1

    IL_000a:  leave.s    IL_0015

  }  // end .try

  finally

  {

    IL_000c:  nop

    IL_000d:  ldstr      "changed in finally"

    IL_0012:  stloc.0

    IL_0013:  nop

    IL_0014:  endfinally

  }  // end handler

  IL_0015:  nop

  IL_0016:  ldloc.1

  IL_0017:  ret

} // end of method SimpleTest::GetString

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

Saturday, October 04, 2008 #

Some interesting books are going to be released later this year and can be pre-ordered from Amazon now.


Concurrent Programming on Windows by Joe Duffy Nov 2008


Framework Design Guidelines: Conventions, Idioms, and Patterns for Reusable .NET Libraries (2nd Edition) by Krzysztof Cwalina and Brad Abrams Nov 2008


Windows® Internals: Including Windows Server 2008 and Windows Vista, Fifth Edition by Mark Russinovich and David A. Solomon Nov 2008


Programming Entity Framework by Julia Lerman Jan 2009


Data Services with Silverlight 2 by John Papa Dec 2008

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

Friday, October 03, 2008 #

Jeremy D. Miller, kicked off a good discussion on how many projects should be in a Visual studio solution with his latest post Separate Assemblies != Loose Coupling.

There are also a few more good posts on same topic:

·         Chad Myer’s Project Anti-Pattern: Many projects in a Visual Studio solution

·         Scott Hanselman’s Assembly Fiefdom: What’s the right number of assemblies / libraries?

·         Ayende’s The two project solution

·         Jacob Lewallen’s Projects in Visual Studio

I completely agree with Jeremy that we should keep number of assemblies minimum and do not separate until it is 100% necessary. Until not a long ago, I actually tended to have many projects in my solution. I think I was largely influenced by .NET Petshop 4.0 which I used for a reference project a few years ago. If you want to know what its project structure looks like. Here is it:

So, you can see, for such small application, there are 22 projects and a few of them just contain only one interface file. I would say this is a ridiculous overkill today, but to be honest, I kind of liked it a few years ago. It made me feel it was well designed/ structured/separated, and I can proudly tell my friends that I am working on a huge enterprise system which has  dozens of projects.

After worked with a couple of systems having a lot of projects, I have completely changed my mind. One system I worked with, it has 3 Visual Studio solutions for server, client and some sort of infrastructure level stuff. The sever solution has more than 80 projects, client has around 50 and infrastructure has more than 20. It wasn't me who created so many projects in the first place. I said I liked many projects, but I wouldn't go that far. Having so many projects slows down everything, if I accidentally kick off a “Rebuild”, I would have to go and get myself a cup of tea, have a chat with every colleague in the office, and come back. The time wasted, actually isn’t the biggest problem, more important problem is, developers get frustrated with it, and frustrated developers don’t enjoy working on it, they will not try to recompile immediately after they make a change, they will not do enough tests, they will not check in quickly. For example, if a developer is to add a new feature into the system, he will only rebuild the system and test it after he thinks he has completed the task, instead of breaking down the task into a number of smaller ones, and targeting one at the time.  Another important problem is, the project structure should provide some sort of high level overview of the system, i.e. how many components / layers in the system, how do they communicate to each other. Try to get a good picture of a system from a hundred projects is like to figure out how a car works from its nuts and bolts.

Another system I worked with has about 60 projects. Not as many as the first one, but it has more complicated dependencies among the projects. I couldn’t even rebuild whole solution from Visual Studio, because there is some wired circular reference, and of course I couldn’t run from Visual Studio too. What I had to do is to build the individual project I have made changes, copy all the assemblies to a particular location and run it from there, if I need debug through, I had to attach to the process from Visual Studio. So if anyone thinks separated assemblies enforce separation of concerns or decoupling, I could tell you, no, it won’t help you do that.

So, how many projects I will have in a Visual Studio solution? I think for a small application, something around 5 should be enough. For a more complicated system, 10 would be still reasonable. 20 projects probably is the maximum for both a developer and Visual Studio to manage effectively and efficiently, so, I would be very carful and reluctant to go over 20.

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

Sunday, September 21, 2008 #

A few months ago, I came cross this problem that I had 2 databases in my project, so that my model classes might map to tables from different databases. It took me a while to work out how to deal with it in ActiveRecord. Today, I had a same problem again, even though I still got my last project’s source code, it still took me a couple of hours to get everything right. So, I think I’d better to write it done, just in case that I will have to do it again or anyone else may need it.  

The Scenario:

Database 1:      MyDatabase                             Table:  Product

Database 2:      MyProfileDatabase                   Table: UserProfile

Model Class:    Product, UserProfile

 The Code:

First, just define Product class as normal ActiveRecord model class:

[ActiveRecord]

public class Product : ActiveRecordBase<Product>

{

    [PrimaryKey("ProductID")]

    public string Id { get; set; }

   

    //...

}

 

Create an abstract base class for MyProfileDatabase.  All classes map to tables in MyProfileDatabase will inherit from this base class. Note: it has to be abstract. This was what I missed out and caused some fun time to find out.

 

public abstract class ProfileActiveRecord<T> : ActiveRecordBase<T>

{

}

 

Define UserProfile class which inherits from ProfileActiveRecord.

[ActiveRecord]

public class UserProfile : ProfileActiveRecord<UserProfile>

{

    [PrimaryKey("UserID")]

    public int Id { get; set; }

 

    //....

}

 

ActiveRecord Configration:

<activerecord>

  <config>

    <add key="hibernate.connection.driver_class"

         value="NHibernate.Driver.SqlClientDriver" />

    <add key="hibernate.dialect"

         value="NHibernate.Dialect.MsSql2005Dialect" />

    <add key="hibernate.connection.provider"

         value="NHibernate.Connection.DriverConnectionProvider" />

    <add key="hibernate.connection.connection_string"

         value="server=localhost;database=MyDatabase;Integrated Security=True" />

  </config>

 

  <config type="SomeNamespace.Core.Models.ProfileActiveRecord`1, SomeNamespace.Core">

    <add key="hibernate.connection.driver_class"

         value="NHibernate.Driver.SqlClientDriver" />

    <add key="hibernate.dialect"

         value="NHibernate.Dialect.MsSql2005Dialect" />

    <add key="hibernate.connection.provider"

         value="NHibernate.Connection.DriverConnectionProvider" />

    <add key="hibernate.connection.connection_string"

         value="server=localhost; database=MyProfileDatabase; Integrated Security=True" />

  </config>

</activerecord>

Initialize Active Records:

XmlConfigurationSource source = new XmlConfigurationSource("ActiveRecord.xml");

Type[] types =

    {

        typeof(Product),

        typeof(ProfileActiveRecord<>),

        typeof(UserProfile)

    };

ActiveRecordStarter.Initialize(source, types);

 

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

Thursday, September 11, 2008 #

I was writing some WPF testing code today. It was extremely simple code which just programmatically creates a Rectangle and adds it to a canvas. The code this something like this:

    Rectangle rectangle = new Rectangle

    {

        Fill = new SolidColorBrush(Colors.Blue),

        Stroke = new SolidColorBrush(Colors.Blue),

        Width = 150,

        Height = 120

    };

    rectangle.SetValue(Canvas.LeftProperty, 100);

    rectangle.SetValue(Canvas.TopProperty, 100);

    canvas.Children.Add(rectangle);

 

However, I got an exception on rectangle.SetValue(Canvas.LeftProperty, 100), saying "'100' is not a valid value for property 'Left'."

 

It didn’t take me long to release that Canvas.LeftProperty actually requires a double instead of an integer, but I was surprised that it couldn’t handle an integer. Normally, in a .NET program, we wouldn’t have to worry about the implicit cast from integer to double, right? So, I was just curious and want to find more about how DependencyObject.SetValue is implemented and wanted to have a look of the .NET framework code.

 

Normally, when I want to do this, I will just use .NET Reflector, but I just heard from my friends that I can debug into .NET framework code. So, why not give it a go?

 

So, followed ShawnBurke's great post Configuring Visual Studio to Debug .NET Framework Source Code, I got my Visual Studio set up and ready to go.

 

Now, fire up my program, set a break point, and in the CallStack panel, there are list of items are greyed out which are the .NET Framework code as Visual Studio doesn’t have the debug symbols. So, just right click, and "Load Symbols", Visual Studio will load them from the debug symbol server you have specified (ShawnBurke’s post above explains how to do it).

 

 

When the debug symbols loaded (it may take a few minutes. PresentationFramework.pdb has 12Mb and PresentationCore.pdb has 16Mb), you will know as greyed out items on CallStack turn black.

Hit F11, now, you can see this:

 

 

 

Cool, isn’t it? We are now in .NET framework source code! Writing a .NET program could be as cool as writing in java! (just kidding)

 

After I played around a bit and dug through some .NET framework code, I found it pretty much just check the value passed in is an instance of the type DependencyProperty defined of. The code is something like this:

 

    if (!propertyType.IsInstanceOfType(value))

    {

        return false;

    }

 

If it returns false, an exception will be thrown from SetValueCommon.I guess WPF could have done better to handle an integer as a double, after all, if we want to set a location programmatically, normally we would just use an integer, right? Anyway, it is not really my point for this post. I really just want to show how to debug into .NET framework code here.

 

Pretty cool, isn’t it? So, what is not so cool?

Well, did find a couple of things not as cool as I expected.

 

  • You have to load debug symbols every time you run the program. It will load from your local cache once it is downloaded from the server, so it won’t take long. But you do have to right click the CallStack, and "Load Symbols" every time.
  • In .Net Framework code, variable values will not be shown properly. You will have "Cannot evaluate expression because the code of the current method is optimized."

 

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

Wednesday, September 10, 2008 #

Recently, I have been working on maintaining two “legacy” systems. One is in VB6, implemented by a person who was not a programmer, but only trained a few weeks for VB6. The code quality is extremely poor. There are even no indentations in the code, and all variables are not properly named, for example, if there are 5 text boxes on a form, they will be just named as Text1(0), Text1(1)…Text(4).  So, I guess I don’t have to say too much and you get a picture of what it looks like. Another system is done with .NET 1.1 using C#, and it is written primarily by a guy who, is considered as a coding hero or maybe, more precisely, a coding cowboy. I didn’t work with any VB stuff before this one, and I have been using C# for 4-5 years.

So, how easy I found maintaining these two systems? This probably will surprise you, but I do find maintaining the VB system is much easier.

Why I find maintaining the VB system is easier? Let me tell you what I normally do to fix a bug. Normally, I will start from finding the form. All the form files are inside one folder, and thank god, they are named properly. So it is not a big deal to find it. And then I will find the control, normally a button which triggers off the function which has a problem. I will then double click on the button, and it will take me to the event handler in the code view. There are normally at least a few hundred lines of spaghetti code. I do sometimes find it is a bit frustrating to work on some code like this, but I will tell myself to be patient, and normally it won’t take too long to locate the line has problem, and fix it normally not a big problem, and I won’t have to worry about fix this one will cause another ten bugs elsewhere because there is no code sharing at all.

While, fixing a bug in the .NET system is completely a different story. Normally finding a file is a big challenge. There are more than 50 projects in the solution (not because the system is large, it could be just 5 – 10), a project may contain only one file, but there are 10000 lines code in it and dozens of class definitions. There are interfaces which you will never find what class implemented it, and there are stuff may be loaded into system via reflection on runtime. There might be some super complicated and wired inheritance structure. Sometimes I get impression, that it is designed not to be found.  I don’t want list of the problems here, I guess everyone has worked on this kind of system knows what I am talking about.

The point I want to raise here is, in term of maintainability, maintaining a well implemented object-oriented system might be easier than a well designed procedural system, but maintaining an object-oriented crap is even more difficult than doing a procedural crap. Also, no architecture is generally better than over-architecture. I think there are some reasons:

  • An object-oriented language itself is more complicated than a procedural language. The cool features like inheritance and polymorphism are all adding complicity and indirection into the program. Note, complicity and indirection are very bad thing, so if they don’t buy you anything, they should not be there.
  • A procedural language might not express well (spaghetti code), but it doesn’t lie, but an object-oriented language does. It could deceive you by using cool stuff like inheritance, reflection, delegate, extension methods, etc.

So, don’t take it for granted that an object-oriented language will automatically make your system more maintainable. What does make an object-oriented language work is the “loose coupling, high cohesion”, is single responsibility principle, is the open-close principle. It is not the cool language features or cool design patterns.

    

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

Monday, September 08, 2008 #

If you use resharper with Visual Studio 2008, you may have noticed that it keeps suggesting you use implicitly typed local variable declaration i.e. the var keyword. To me, it is a bit annoying.

 

You can actually find why people think it should exist in the first place:http://resharper.blogspot.com/2008/03/varification-using-implicitly-typed.html

 

There are some valid points, but I am not convinced. I think it is less readable in most of the case. I can’t agree with Ilya that it induces better naming for local variables or better API. You got to name your variables properly no matter what you use, right? It won't make a good programmer better, but it will make a bad programmer even worse.

 

I do agree that compare to

Dictionary<string, Employee> employees = new Dictionary<string, Employee>();

That var employees = new Dictionary<string, Employee>();

does have same readability and it does save you a few key strikes. The benefit is really small, and you have to make judgment on it. The problem is you may have different ideas at different time and different team members may have their own habit. So, in your team, if the coding standard is “Use var whenever you think it good”, it will inevitably cause inconstant coding style. I would rather avoid it by having “Never use var”, you would lost too much after all.

 

So, if you don't like it neither, this is the way to turn it off. From “Resharper” menu, go to “Options…”, and from “Code Inspection”, then from “Inspection Severity”, find "Use Var keyword when possible” and set to “Do not show”

 

 
  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

Sunday, September 07, 2008 #

I had this problem today. It looks very simple, but actually took me a while to find a solution. The problem is: I have a Winforms DataGridView, and its first column is an unbound CheckBox column which is used to select/unselect a row. I want to hook up the check/uncheck event so that I can execute some logic after a row is selected or unselected. As this is Winforms, there is no way I can hook up an event from a control’s child element. But, it is quite obvious that we can hook up DataGridView’s OnCellvalueChanged event and put the logic there. So I had some code like this:

private void EmployeesGrid_OnCellValueChanged(object sender,  

     DataGridViewCellEventArgs e)

{

     if (e.ColumnIndex == 0 && e.RowIndex > -1)

     {

        bool selected = (bool)_gvEmployees[e.ColumnIndex, e.RowIndex].Value;

        _gvEmployees.Rows[e.RowIndex].DefaultCellStyle.BackColor =

selected ? Color.Yellow : Color.White;

     }

}

 

Here, for demonstration, I just simple change the background color of a row depending on if the checkbox column is checked or not. It all works fine except the background color won’t change until you move your mouse cursor out of the cell. The reason for that is OnCellvalueChanged event won’t fire until the DataGridView thinks you have completed editing. This makes senses for a TextBox Column, as OnCellvalueChanged wouldn’t broth to fire for each key strike, but it doesn’t for a CheckBox.

 

After trying a few different events, I finally find a workaround, and it is very simple. I just need to hook up on CellMouseUp event and explicitly exit edit mode there. Some sample code is here:

 

private void EmployeesGrid_OnCellMouseUp(object sender,  

     DataGridViewCellMouseEventArgs e)

{

     if (e.ColumnIndex == 0 && e.RowIndex > -1)

     {

        _gvEmployees.EndEdit();

     }

}

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

Saturday, February 17, 2007 #

 

I thought I understand ViewState, until I came cross this exception:

Failed to load viewstate.  The control tree into which viewstate is being loaded must match the control tree that was used to save viewstate during the previous request.  For example, when adding controls dynamically, the controls added during a post-back must match the type and position of the controls added during the initial request.

 

This is a question asked by someone on a .NET mailing list. My first guess of what causing the problem is that on a page postback, when LoadViewState() is invoked to restore the saved ViewState values to the page and its controls (both Control tree and ViewState tree have been created at this stage), somehow, the ViewState tree doesn't match the control tree. So when ASP.NET tries to restore a ViewState value to a control, no control or a wrong control is found and then the exception occurs.

Note: the ViewState tree (type of Triplet or Pair) is NOT the ViewState property (type of StateBag) of the page or any of its controls. You can think it as an object representation of the ViewState value on the html page (the __VIEWSTATE hidden field), which contains all the values need to be written back to the controls during a page postback. If you don't change the default behavior, during the page initialize/load phrase, the ViewState tree will be created by de-serializing the value __VIEWSTATE field by LoadPageStateFromPersistenceMedium(), and the values on the ViewState tree will be put into the controls ViewState bag in LoadViewState() . During the page save/render phrase, the ViewState tree will be created again by SaveViewState (), then serialized and written onto html page by SavePageStateToPersistenceMedium ()

So, I thought I could reproduce same exception with something simple like this:

Defualt.aspx

<form id="form1" runat="server">

<asp:Button ID="btnPostback" runat="Server" Text="Postback" />

</form>

Default.aspx.cs

public partial class _Default : Page

{

    protected override void OnInit(EventArgs e)

    {

        base.OnInit(e);

        if (!IsPostBack)

        {

            Button btnClickMe = new Button();

            form1.Controls.Add(btnClickMe);

        }

    }

}

It is indeed a very simple page with a button named btnPostback created statically on .aspx file, and another button named btnClickMe created dynamically in Page.OnInit(), and I will not recreate the btnClickMe for postbacks. So on a page postback, by the time OnInit() and LoadPageStateFromPersistenceMedium() is executed, the control tree and ViewState tree would have different structure, the ViewState tree will have value for btnClickMe, but the control tree will not have the control btnClickMe. I thought it would be good enough to cause the exception, but soon I was proved wrong, there was no exception thrown.

To find out why, let's have a look of the actual ViewState value generated on the html page

 “/wEPDwUKMTQ2OTkzNDMyMWRkOWxNFeQcY9jzeKVCluHBdzA6WBo=”

With a little help from ViewState Decoder I got this:

<viewstate>

  <Pair>

    <Pair>

      <String>1469934321</String>

    </Pair>

  </Pair>

</viewstate>

There is no view state data for the neither of the buttons! I did expect something like <Pair /> for a control has empty state though.

So, I think here is the first thing I learned:

For a control on the Control tree, there may not be a corresponding item on the ViewState tree (if there is no state for this control need to be saved). If there is nothing found on ViewState tree for a control, the control’s LoadViewState() will not be invoked.

So, let's do something to make the button "dirty" and its ViewState saved.

public partial class _Default : Page

{

    protected override void OnInit(EventArgs e)

    {

        base.OnInit(e);

        if (!IsPostBack)

        {

            Button btnClickMe = new Button();

            form1.Controls.Add(btnClickMe);

            btnClickMe.Text = "Click me";

        }

    }

}

 

The ViewState now became:

 

/wEPDwUKMTQ2OTkzNDMyMQ9kFgICAw9kFgICAw8PFgIeBFRleHQFCENsaWNrIG1lZGRkaZj77nQ7KGQERj05RRc1lk+fvNA=

 

<viewstate>

  <Pair>

    <Pair>

      <String>1469934321</String>

      <Pair>

        <ArrayList>

          <Int32>3</Int32>

          <Pair>

            <ArrayList>

              <Int32>3</Int32>

              <Pair>

                <Pair>

                  <ArrayList>

                    <IndexedString>Text</IndexedString>

                    <String>Click me</String>

                  </ArrayList>

                </Pair>

              </Pair>

            </ArrayList>

          </Pair>

        </ArrayList>

      </Pair>

    </Pair>

  </Pair>

</viewstate>

 

The format of the ViewState looks quite interesting, but let's worry about it later.For now, it does look like Text property of the btnClickMe having been saved. Great!

 

But when I ran it, still no exception was thrown.

 

So, I guess that is just the way it works:

 

For an Item on the ViewState tree, if there is no corresponding control can be found on control tree, this ViewState Item will be ignored.

 

So, how about creating a different control instead? Something like this:

 

public partial class _Default : Page

{

    protected override void OnInit(EventArgs e)

    {

        base.OnInit(e);

        if (!IsPostBack)

        {

            Button btnClickMe = new Button();

            form1.Controls.Add(btnClickMe);

            btnClickMe.Text = "Click me";

        }

        else

        {

            Label label = new Label();

            form1.Controls.Add(label);

        }

    }

}

 

Still no exception! And it is very interesting, after the the page postback, the btnClickMe was gone and a label was shown with text "Click me"! I didn’t assign any value to its Text Property. Why "Click me" was there? The ASP.NET has restored the ViewState value onto label, but the value actually doesn't belong to it!

 

So, here is another interesting thing:

 

ASP.NET doesn’t really know which control a ViewState item belongs to. It only matches a item on the ViewState tree and a control on Control tree by the index. 

 

If we have a look of the format of the saved ViewState, it contains nothing but just the indices of the control and the value-keys, so there is no way for ASP.NET can figure out which control exactly it belongs to. Anyway, I think this make perfect sense, we do want the _VIEWSTATE fields as small as possible, don't we?

 

The above sample has demonstrated a ViewState value for a Button's Text property was restored to a Label's Text Property on page postback. Now it comes to some interesting questions: what will happen if

 

1.    The second control doesn't have the property with same name?

2.    The second control has the property with different data type?

3.     2 controls are very different, say, a button and a GridView?

 

Let's find out!

 

public partial class _Default : Page

{

    protected override void OnInit(EventArgs e)

    {

        base.OnInit(e);

        if (!IsPostBack)

        {

            Button btnClickMe = new Button();

            form1.Controls.Add(btnClickMe);

            btnClickMe.Text = "Click me";

            btnClickMe.CommandName = "XXX";

        }

        else

        {

            Label label = new Label();

            form1.Controls.Add(label);

        }

    }

}

 

This time I have assigned a value to button's CommandName property, but Label doesn't have this property. If you run this code, still no exception will occur. Is it "XXX" for CommandName just simply ignored? Let's have a look of the saved ViewState after postback:

 

/wEPDwUKMTQ2OTkzNDMyMQ9kFgICAw9kFgICAw8PFgQeBFRleHQFCENsaWNrIG1lHgtDb21tYW5kTmFtZQUDWFhY

ZGRk7q5i15YA6gDUPW8m/IVLqGXnb+4=

 

<viewstate>

  <Pair>

    <Pair>

      <String>1469934321</String>

      <Pair>

        <ArrayList>

          <Int32>3</Int32>

          <Pair>

            <ArrayList>

              <Int32>3</Int32>

              <Pair>

                <Pair>

                  <ArrayList>

                    <IndexedString>Text</IndexedString>

                    <String>Click me</String>

                    <IndexedString>CommandName</IndexedString>

                    <String>XXX</String>

                  </ArrayList>

                </Pair>

              </Pair>

            </ArrayList>

          </Pair>

        </ArrayList>

      </Pair>

    </Pair>

  </Pair>

</viewstate>

 

Note this is the saved ViewState after a post back, the values are for the label. So even a label doesn't have CommandName property, the value was still written to Label's ViewState bag, and then saved. So if you dynamically change a control at runtime, the new control may silently "inherit" some rubbish ViewState from control was previously sitting at the position, and carry it all the time, pass it from server to client, and client back to server.

 

To test the second question out, there is a bit more code I had to write, as I couldn't find a property which on two different controls with different data type, so I have defined my own ones.

 

public class MyButton : Button

{

    public string MyProperty

    {

        get { return ViewState["MyProperty"] == null ? String.Empty : ViewState["MyProperty"] as String; }

        set { ViewState["MyProperty"] = value; }

    }

}

 

public class MyLabel: Label

{

    public Color MyProperty

    {

        get { return ViewState["MyProperty"] == null ? Color.Black : (Color)ViewState["MyProperty"]; }

        set { ViewState["MyProperty"] = value; }

    }

}

 

public partial class _Default : System.Web.UI.Page

{

    protected override void OnInit(EventArgs e)

    {

        base.OnInit(e);

        if (!IsPostBack)

        {

            MyButton btnClickMe = new MyButton();

            form1.Controls.Add(btnClickMe);

            btnClickMe.MyProperty = "XXX";

        }

        else

        {

            MyLabel label = new MyLabel ();

            label.ID = "label";

            form1.Controls.Add(label);

        }

    }

 

    protected override void OnLoad(EventArgs e)

    {

        base.OnLoad(e);

        if (IsPostBack)

        {

            MyLabel label = form1.FindControl("label") as MyLabel;

            label.Text = label.MyProperty.ToString();

        }

    }

}

 

As you can see both MyButton and MyLabel have Property called MyProperty, though MyButton.MyProperty is string type, but MyTextBox.MyProperty is Color type.

 

From previous test, we have learned that the LoadViewState() will write the ViewState values into controls' ViewState bag directly without being bothered to go through the controls' property. So, I would expect "XXX" will be written into MyLabel’s ViewState bag successfully even though MyLabel.MyProperty really expects a Color value, but we are going to have problem if we try to access the value in MyLabel.MyProperty.

 

My guess was right this time, if you run the code, an InvlaidCastException will be thrown by (Color)ViewState["MyProperty"] when the Property is accessed in OnLoad().

 

OK, the last one now, what will happen if two controls are very different? Ok, maybe we don't need something complicated as GridView, let's just try a DropDownList:

 

public partial class _Default : Page

{

    protected override void OnInit(EventArgs e)

    {

        base.OnInit(e);

        if (!IsPostBack)

        {

            Button btnClickMe = new Button();

            form1.Controls.Add(btnClickMe);

            btnClickMe.Text = "Click me";

        }

        else

        {

            DropDownList ddl = new DropDownList();

            form1.Controls.Add(ddl);

        }

    }

}

 

When I ran the page, after clicking Postback button, I got a page returned with this error message:

Failed to load viewstate.  The control tree into which viewstate is being loaded must match the control tree that was used to save viewstate during the previous request.  For example, when adding controls dynamically, the controls added during a post-back must match the type and position of the controls added during the initial request.

Aha, finally get it!

 

To find out why, I made some little changes, first I defined MyDropDownList:

 

public class MyDropDownList : DropDownList

{

    protected override void LoadViewState(object savedState)

    {

        base.LoadViewState(savedState);

    }

}

 

There is nothing in MyDropDownList, it just overrides the LoadViewState(), so I can place a break point there.

 

And then I changed page to use MyDropDownList:

 

public partial class _Default : Page

{

    protected override void OnInit(EventArgs e)

    {

        base.OnInit(e);

        if (!IsPostBack)

        {

            Button btnClickMe = new Button();

            form1.Controls.Add(btnClickMe);

            btnClickMe.Text = "Click me";

        }

        else

        {

            MyDropDownList ddl = new MyDropDownList();

            form1.Controls.Add(ddl);

        }

    }

}

 

Let’s see what is going to happen, put a break point at base.LoadViewState(), run it, click the Postback button, MyDropDownList created, the its LoadViewState() invoked, program hanged at base.LoadViewState(), good, just worked as expected! Hold on, this looks like a problem: LoadViewState(object savedState) seems to be expecting a Triplet object as a parameter, but what is actually passed in here is a Pair!

 

It does make sense, doesn't it? Don't forget the Pair object is the saved ViewState left behind from the btnClickMe, and on the postback, ASP.NET doesn’t know which control it belongs to, what the ViewState tree can tell is  "it belongs to the 3rd control on the form1" On the postback, the 3rd control on form1 now became a DropDownList, but ASP.NET is silly enough to try to restore it with the Pair object. For a DropDownList, only a Triplet object can be used to restore it, so, of course, when LoadViewState() is trying to do something like "Triplet triplet1 = (Triplet)savedState;", an exception will occur.

 

After having inspected some ASP.NET framework code using Lutz Roeder's .NET Reflector, expecially SaveViewState() and LoadViewState() method, I finally got a better picture of the what happened. A Control actually has full responsibility of saving/loading its ViewState. In ASP.NET, most of controls inherit their parent’s behavior defined in Control, WebControl or ListControl, but a control have complete control over it, and in theory, a control can have any data structure for holding its saved ViewState, as long as it is serializable and both SaveViewState() and LoadViewState() understand it. Normally, the ViewState of a WebControl will be saved as a Pair object, if Pair is not enough, a Triplet object may be used, like what ListControl does(ListControl needs a another object to hold the states for its child items). When ASP.NET tries to restore a control's ViewState with a velue which is saved for another control, if the two controls have different save ViewState object type, the Exception above will be thrown.

 

Conclusion:

When ASP.NET tries to restore ViewState values to a page and its controls, a ViewState tree will be created by deserializing the _VIEWSTATE value on html page. The ViewState tree contains only control indices and key-value pairs. ASP.NET finds the control for a ViewState item by the index*, and directly writes the value into control's ViewState bag. If you dynamically create/remove controls at runtime, it will be very likely to fool ASP.NET to restore ViewState values to a wrong control and causing a problem. Depending on what control is dynamically created/removed, following problems may occur:

 

1 Runtime exception when restoring ViewState

2 Runtime exception when accessing a property of a control

3 A control's property may have an unexpected value

4 A control may carry rubbish ViewState value and increase the size of _VIEWSTATE field on html page

 

Problems above may be difficult to notice and debug, especially 3 and 4 

*One can override this behavior using ViewStateModeByIdAttribute.

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

Tuesday, February 20, 2007 #

 

Had this question when I was reading “Effective C#: 50 Specific Ways to Improve Your C#”.

In the item 18: "Implement the Standard Dispose Pattern", the book recommends to implements IDisposable.Dispose() to do following tasks:

1.    Freeing all unmanaged resources.

2.    Freeing all managed resource (this includes unhooking events).

3.   

My question is on point 2, why do we have to unhook events?

After having a look of how System.Delegate is implemented, I found the reason is actually quite simple.

To answer the question, first let's have a look this program:

public class Publisher

{

    public event EventHandler SomethingHappen;

}

 

public class Subscriber

{

    public void DoSomething(object sender, EventArgs e)

    {

    }

}

 

public class Test

{

    public static void Main(string[] args)

    {

        Publisher publisher = new Publisher();

        Subscriber subscriber = new Subscriber();

        publisher.SomethingHappen += subscriber.DoSomething;

    }

}

 

The thing we need to take a good look is the last line of Main() method. In the Main(), there are three objects are created. Apart from a publisher, a subscriber created by the first and second line, the third line "publisher.SomethingHappen += subscriber.DoSomething" creates and an object as well.  The type of the object created is EventHandler which is derived from System.MulticastDelegate which, in turn, is derived from System.Delegate.

In System.Delegate, it maintains four private fields:

internal object _target;

internal IntPtr _methodPtr;

internal IntPtr _methodPtrAux;

internal MethodBase _methodBase;

 

Two fields are relevent here: _methodPtr and _target. In our program, the EventHandler object created will have its _target field points to subscriber object, and _methodPtr points to the memory address of DoSomething() method. A delegate must have _target field because to invoke an instance method, the first parameter is passed to the method has to be method's "this" pointer. So when a delegate object wraps an instance method, the delegate must maintain the "this" pointer, in another word, to invoke an instance method, a delegate must know the instance. If a delegate object wraps a static method, then _target will be set to null.

 

The answer to the question is quite clear now: as long as the publisher object is alive, subscriber object will be always referenced by the delegate object, it will not be able to get garbage collected even we explicitly set subscriber = null. So if we don't unhook event, it is likely to introduce a resource leak.

 

As a proof of concept, let's run this little program:

public class Publisher

{

    public event EventHandler SomethingHappen;

}

 

public class Subscriber

{

    private int[] array = new int[1000000];

    public void DoSomething(object sender, EventArgs e)

    {

    }

}

 

public class Test

{

    public static void Main(string[] args)

    {

        Publisher publisher = new Publisher();

        for (int i = 0; i < 10; i++)

        {

            Subscriber subscriber = new Subscriber();

            publisher.SomethingHappen += subscriber.DoSomething;

            //publisher.SomethingHappen -= subscriber.DoSomething;        

subscriber = null;

        }

        Console.WriteLine("Total memory allocated: " + GC.GetTotalMemory(true));

        Console.ReadKey();

    }

}

The first time I run it with the line for unhooking event commented off, the memory usage is: 40802720. Second time with the line turned on, the memory usage became only: 800948

 

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

Monday, February 19, 2007 #

 

In my last post ViewState and Dynamic Control, I mentioned that ViewStateModeByIdAttribute can be used to change the default behavior of how ASP.NET finds the controls when ViewState data restored. Now, let's have a look how it can be done.

 

For now, let's forget about ViewStateModeByIdAttribute for a second, and just have a simple page as following:

 

Default.aspx

<body>

    <form id="form1" runat="server">

        <asp:Panel ID="pnlMain" runat="Server">

        </asp:Panel>

    </form>

</body>

 

Default.aspx.cs

public partial class _Default : Page

{

    protected override void OnLoad(EventArgs e)

    {

        base.OnLoad(e);

        if (!IsPostBack)

        {

            Button button = new Button();

            button.ID = "btnClickMe";

            pnlMain.Controls.Add(button);

            button.Text = "Click me!";

        }

        else

        {

            Label label = new Label();

            label.ID = "lblMessage";

            pnlMain.Controls.Add(label);

        }

    }

}

 

Default.aspx is an extremely simple page with only one Panel on its form, in its code behind file, a new button is dynamically created and added onto the panel. On page post back, instead of recreating the button, we create a label and add it onto the panel. So, the position of the label on the control tree will be the same as the button's for the first request, and this will result in an incorrect ViewState value to be restored to label. As the result, the label will be displaying "Click me!" after a postback, though "Click me!" actually belonged to the button. (my post ViewState and Dynamic Control has more on this)

 

If we look the saved ViewState data:

 

<viewstate>

  <Pair>

    <Pair>

      <String>28670841</String>

      <Pair>

        <ArrayList>

          <Int32>3</Int32>

          <Pair>

            <ArrayList>

              <Int32>1</Int32>

              <Pair>

                <ArrayList>

                  <Int32>1</Int32>

                  <Pair>

                    <Pair>

                      <ArrayList>

                        <IndexedString>Text</IndexedString>

                        <String>Click me!</String>

                      </ArrayList>

                    </Pair>

                  </Pair>

                </ArrayList>

              </Pair>

            </ArrayList>

          </Pair>

        </ArrayList>

      </Pair>

    </Pair>

  </Pair>

</viewstate>

 

Note the part highlighted in red, it simply says: for whatever the child control with index 1 on pnlMian, the value/key pair "Click me!"/Text will be stored into its StateBag. So, on the postback, the label takes the position of index 1, and get restored with "Click me!" to its Text property.

 

Now, let's try ViewStateModeByIdAttribute. As it can be applied only on class declarations, we will not be able to use it on any existing control. We have to define a new control.

 

So, let's define a new panel with ViewStateModeById tag:

 

LoadByIdPanel.cs

[ViewStateModeById]

public class LoadByIdPanel : Panel

{

}

 

Now replace normal Panel with LoadByIdPanel in Default.aspx:

 

Default.aspx

<body>

    <form id="form1" runat="server">

        <aspx:LoadByIdPanel ID="pnlMain" runat="Server">

        </aspx:LoadByIdPanel>

    </form>

</body>

 

If we run the page now, the label will not display "Click me!". The save ViewState became:

 

<viewstate>

  <Pair>

    <Pair>

      <String>783430533</String>

      <Pair>

        <ArrayList>

          <Int32>3</Int32>

          <Pair>

            <ArrayList>

              <Int32>1</Int32>

              <Pair>

                <ArrayList>

                  <String>btnClickMe</String>

                  <Pair>

                    <Pair>

                      <ArrayList>

                        <IndexedString>Text</IndexedString>

                        <String>Click me!</String>

                      </ArrayList>

                    </Pair>

                  </Pair>

                </ArrayList>

              </Pair>

            </ArrayList>

          </Pair>

        </ArrayList>

      </Pair>

    </Pair>

  </Pair>

</viewstate>

 

Note the index now became "btnClickMe", instead of an integer value, and ASP.NET tries to find the child control with id "btnClickMe" but no control will be found on a postback, the ViewState data then will be ignored.

 

The last thing we need to be aware, ViewStateModeByIdAttribute only apply to a control's direct children. For example, if you only apply it to a page, only the form will be loaded by Id (if the form is its only child), all the controls inside the form will still be loaded by index.

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati