Tuesday, July 29, 2008

Building TreeView Programmably in a Recursively Fashion

Below is an example of building a TreeView from a registry hierarchy. Note that RegistryKey and Registry objects are in Microsoft.Win32 namespace.

private int maxDepth = 0, depth = 0;

protected void Page_Load(object sender, EventArgs e)
{
RegistryKey schangeRoot = Registry.LocalMachine.OpenSubKey("Software\\SeaChange", false);

TreeNode rootNode = new TreeNode(schangeRoot.Name);

Traverse(schangeRoot, rootNode);

Response.Write(maxDepth.ToString() + "
" + depth.ToString());

TreeView1.Nodes.Add(rootNode);
}

private void Traverse(RegistryKey current, TreeNode currentNode)
{
Response.Write(depth.ToString() + current.Name + "
");

if (current.SubKeyCount <= 0)
{
if (depth > maxDepth)
maxDepth = depth;

return;
}

foreach (string subkeyName in current.GetSubKeyNames())
{
// Before traversing the subkey, create a new node for it
TreeNode childNode = new TreeNode(subkeyName);

// Traverse subkey
depth++;
Traverse(current.OpenSubKey(subkeyName), childNode);
depth--;

// Finish traversing the subkey, add the subkey to this node
currentNode.ChildNodes.Add(childNode);
}
}

Thursday, July 24, 2008

Cannot Access Profile Property in Webpage

In web application projects, we cannot access Profile property as what we do in web site projects. (See the differences between the two projects here: Introduction to Web Application Projects)

To work around this, use ASP.NET WebProfileGenerator, which is an add-in for Visual Studio. If we don't want to use an add-in, we could implement a custom profile provider. Use this article for a reference.

Wednesday, July 23, 2008

The Importance of Page.IsPostBack

For most of the time, we should think about adding if(!Page.IsPostBack) block in Page_Load event of our webpage. Since ViewState of all the webcontrols are enabled by default, most of the time the logic in Page_Load event is supposed to be executed only during the first time webpage is loaded. If we forget to wrap the logic inside the if block when we are supposed to do so, not only can it causes inefficiency, but leads to bugs.

Here is an example. (Refer to ASP.NET security tutorial #10 http://www.asp.net/learn/security/tutorial-10-cs.aspx, step 4)

If we don't wrap the following logic inside if(!Page.IsPostBack) block:

// Reference the SpecifyRolesStep WizardStep
WizardStep SpecifyRolesStep = RegisterUserWithRoles.FindControl("SpecifyRolesStep") as WizardStep;
// Reference the RoleList CheckBoxList
CheckBoxList RoleList = SpecifyRolesStep.FindControl("RoleList") as CheckBoxList;
// Bind the set of roles to RoleList
RoleList.DataSource = Roles.GetAllRoles();
RoleList.DataBind();

something unexpected will happen.

During the second step of the wizard, if we check any role we'd like to assign to the newly created user, it will fail to assign. After we check any CheckBox on the CheckBoxList and press the next button, the logic in Page_Load event is executed again. This will cause the RoleList to be bound again. It seems to be harmless at first, but the truth is, RoleList.DataBind() will clear any change made to the CheckBoxList. Hence, even if we've checked some CheckBox in the RoleList the second step, they all become unchecked now.

So, in this case, there is no reason not to use if(!Page.IsPostBack) block.

Perhaps saying "most of the time if(!Page.IsPostBack) block should be added in Page_Load event" is a bit absolute; but for me, I'll wrap the logic in the block every time; unless there is a reason convinces me not to do so.

Friday, July 18, 2008

Configuring passwordFormat="Encrypted" in ASP.NET

When setting passwordFortmat="Encrypted" (compared to "Hashed" by default) in web.config, I got an exception after trying to create a user.

Solution:
A tag is necessary in this case. I think it is used to encrypt password. MSDN says about machineKey:
Configures keys to use for encryption and decryption of forms authentication cookie data and view-state data, and for verification of out-of-process session state identification.
A typical tag looks like this:


The following is a generator:
http://www.aspnetresources.com/tools/keycreator.aspx

Monday, July 7, 2008

Passing Reference in C#

In the article Passing Reference-Type Parameters, we've seen that we need to use the "ref" keyword in order to swap string values. This is also true for any other reference-types such as an ArrayList.

Remember:
When you pass a reference-type parameter by value, it is possible to change the data pointed to by the reference, such as the value of a class member. However, you cannot change the value of the reference itself; ...

This reminds me the differences between a reference and a pointer: In the swap function, if we are passing parameters by pointer(like in C or C++), then any local change is also global; if we are passing parameters by reference (like in C#), then any local change is not global.