Ralph Varjabedian
Sharing .NET Code and ideas

Update for Binding ASP.NET TreeView to a DataSet or an ObjectDataSource

Hi All,

The code (the sample) that was with the post Binding ASP.NET TreeView to a DataSet or an ObjectDataSource is updated to account for columns that are of type string. Also the code now can work with DataViews and not just DataSets to enable easier binding with more sources like LINQ via the method AsDataView();

Let me know if you have any comments. Thanks.

Stop the Virus Spread on USB Flash Disks

It is becoming very annoying sharing USB Flash Disks. Most viruses for Flash Disks copy themselves on the root of your drive and set their attributes to hidden and system and modify the autorun.inf to run itself every time the USB Drive is plugged in a computer. I got an idea the other day and so far it is working great. I opened my USB Flash Disk and added an empty file to it and saved it as autorun.inf. Then I modified its security attributes (access lists) to deny access to everybody. And then I set it to read only and hidden. By doing this, when I put my USB Drive into a computer that wants to infect my drive, the virus tries to open and modify the autorun.inf but it fails. Hope this helps.

Microsoft Server 2008 Launch in Lebanon

For those who are living in Lebanon, Join us on the Wednesday 30th of April 2008 at the Palais des Congrés for the Microsoft Server 2008 Launch. You should register before you go. Hope to see you there.

LINQ in Multi-tier Applications

If you use LINQ as your database layer and you have multi layers in your design then you would know that at some point you create a set of parallel classes to LINQ entity classes that are called data transfer objects. These classes basically serve the purpose of transferring data from LINQ objects to higher levels without making the higher levels depend on LINQ generated classes, these classes are important for maintaining proper abstraction between your layers.

Transferring the data between LINQ entity objects and your data transfer objects is usually done using reflection. However using reflection is very slow so I have turned to my friend Mr. Emit.

Mr. Emit is a developer working for me at runtime and writes code for me as as needed and best of all he works for free :) His full name is System.Reflection.Emit. See how this article explains how to use System.Reflection.Emit for creating code at runtime to speed things up big time for such operations. The code in the article could be used to transfer data between any type of objects based on their Properties and not by using Reflection, but by writing code at runtime. Hope my article will speed up a lot of implementations out there.

Binding ASP.NET TreeView to a DataSet or an ObjectDataSource

The other day I wanted to bind a TreeView to a DataSet (or an ObjectDataSource that would return a DataSet) and I was disappointed to see that it does not support this. Googling this showed a lot of developers opting to fill the TreeView themselves programmatically. So I decided to create a simpler solution for this.

The key to this solution is that the TreeView can bind to any object that implements the interface IHierarchicalDataSource. So I created a simple class that takes a DataSet as its input along with two column names, I will explain them in a moment, and this class would implement the IHierarchicalDataSource interface.

So instead of writing:

TreeView1.DataSource = dataSet;

which is not supported, we write this:

TreeView1.DataSource = new HierarchicalDataSet(dataSet, "ID", "ParentID");

And that's it. And here is your sample application.

The two extra parameters that you have to pass to the constructor of HierarchicalDataSet are two column names. The first one being the primary key of the table, and the second one being the parent key which usually would be a foreign key to the primary key of the same table; this allows modeling the tree structure in a database table. Here is a simple design of such a tableTable design for a tree structure.











To ViewState or not to ViewState

ViewState is used inside your controls mostly for keeping track of variables on PostBacks. So basically if you have a variable or a property inside your WebUserControl and you want it to persist values, this is when you use the ViewState. However it is important to understand that the ViewState data is put in the page response itself as a Hidden field, what does this mean?

This means that first, you can not trust the input from your ViewState, as it comes back with the page post so it can be changed. By default the ViewState is not encrypted, however you can instruct IIS to encrypt it but it will affect performance. For example if you put in your ViewState an ID of a record to update, do not update it without asserting that it actually belongs to the logged in user, a full security discussion is beyond this post.

Second this means that your page's response size will grow as the data you save in your ViewState grows; this affects performance as it will take more time for your end user's browser to load the page and it will take more time when he wants to post back to your server. If you want to check this, when you get your page from your server, save it as an html file from your browser and check its size. There is also some extra processing in Serializing/Deserializing the ViewState. So in short, the more you save data in your ViewState, the more your suffer from performance.

So what happens when you have some large data that you have to save in your ViewState and there isn't a better solution for it. You can use a combination of your ViewState and Session to give you the same results, but with much lesser performance degradation. The trick is to save your large data inside your session with a certain generated key and just save that key inside your ViewState. For an example, suppose you have a DataSet that you want to keep track on post backs, you write some code like this.

public DataSet SavedDataSource
{
    get
    {
        if (ViewState["SavedDataSourceKey"] == null)
            return null;

        return (DataSet)Session[(string)ViewState["SavedDataSourceKey"]];
    }

    set
    {
        if (ViewState["SavedDataSourceKey"] == null && value == null)
            return;

        if (ViewState["SavedDataSourceKey"] == null)
            ViewState["SavedDataSourceKey"] = System.Guid.NewGuid().ToString();

        if (value == null)
        {
            Session.Remove((string)ViewState["SavedDataSourceKey"]);
            ViewState.Remove("SavedDataSourceKey");
        }
        else
            Session[(string)ViewState["SavedDataSourceKey"]] = value;
    }
}

By using your Session to save your large data, you are saving on the response size and also on the PostBack size, and your data is kept on your server.

A word of caution:

Please note that you are now saving your data in your Session, this means you have to be careful not to overuse this method excessively as your Session will grow on the server per user, so do not use this method frequently unless you need to use this trick when you have large data. Moreover if you know when you can dispose of your variable, do it as soon as you can by setting your property to null, this will release the session data. For example if you know you are navigating to another page and you will no longer get PostBacks on your page, then set the SavedDataSource to null to release the Session data.