Brendan Enrick

Daily Software Development

Using a DropDownList without ViewState

One of the most ViewState heavy controls is the DropDownList. It stores in ViewState the Text and Value for every ListItem in the DropDownList. This means large Lists can get really nasty when ViewState comes into play. They also include all of these entries a second time because they're all in the html. Being in the html will only slow the page down as it is sent to the user, but the ViewState is downloaded by the user and also must be uploaded back up to the web server. This is a horrible user experience if the page has a large amount of ViewState. Since upload speeds are usually worse than download, the user will probably not like the amount of time the postbacks on the site take. In the following example I am going to show how much ViewState can be saved by simply reloading the data into the DropDownList each time the page is requested.

This is how much ViewState my hundred item DropDownList contains at the beginning of this example.

<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwULLTEwNjkzMDQ2Nz
MPZBYCAgMPZBYEAgEPEA8WAh4LXyFEYXRhQm91bmRnZBAVZAlFbGVtZW50IDAJRWxlbWVudCAxCUVsZW1lbnQg
MglFbGVtZW50IDMJRWxlbWVudCA0CUVsZW1lbnQgNQlFbGVtZW50IDYJRWxlbWVudCA3CUVsZW1lbnQgOAlFbG
VtZW50IDkKRWxlbWVudCAxMApFbGVtZW50IDExCkVsZW1lbnQgMTIKRWxlbWVudCAxMwpFbGVtZW50IDE0CkVs
ZW1lbnQgMTUKRWxlbWVudCAxNgpFbGVtZW50IDE3CkVsZW1lbnQgMTgKRWxlbWVudCAxOQpFbGVtZW50IDIwCk
VsZW1lbnQgMjEKRWxlbWVudCAyMgpFbGVtZW50IDIzCkVsZW1lbnQgMjQKRWxlbWVudCAyNQpFbGVtZW50IDI2
CkVsZW1lbnQgMjcKRWxlbWVudCAyOApFbGVtZW50IDI5CkVsZW1lbnQgMzAKRWxlbWVudCAzMQpFbGVtZW50ID
MyCkVsZW1lbnQgMzMKRWxlbWVudCAzNApFbGVtZW50IDM1CkVsZW1lbnQgMzYKRWxlbWVudCAzNwpFbGVtZW50
IDM4CkVsZW1lbnQgMzkKRWxlbWVudCA0MApFbGVtZW50IDQxCkVsZW1lbnQgNDIKRWxlbWVudCA0MwpFbGVtZW
50IDQ0CkVsZW1lbnQgNDUKRWxlbWVudCA0NgpFbGVtZW50IDQ3CkVsZW1lbnQgNDgKRWxlbWVudCA0OQpFbGVt
ZW50IDUwCkVsZW1lbnQgNTEKRWxlbWVudCA1MgpFbGVtZW50IDUzCkVsZW1lbnQgNTQKRWxlbWVudCA1NQpFbG
VtZW50IDU2CkVsZW1lbnQgNTcKRWxlbWVudCA1OApFbGVtZW50IDU5CkVsZW1lbnQgNjAKRWxlbWVudCA2MQpF
bGVtZW50IDYyCkVsZW1lbnQgNjMKRWxlbWVudCA2NApFbGVtZW50IDY1CkVsZW1lbnQgNjYKRWxlbWVudCA2Nw
pFbGVtZW50IDY4CkVsZW1lbnQgNjkKRWxlbWVudCA3MApFbGVtZW50IDcxCkVsZW1lbnQgNzIKRWxlbWVudCA3
MwpFbGVtZW50IDc0CkVsZW1lbnQgNzUKRWxlbWVudCA3NgpFbGVtZW50IDc3CkVsZW1lbnQgNzgKRWxlbWVudC
A3OQpFbGVtZW50IDgwCkVsZW1lbnQgODEKRWxlbWVudCA4MgpFbGVtZW50IDgzCkVsZW1lbnQgODQKRWxlbWVu
dCA4NQpFbGVtZW50IDg2CkVsZW1lbnQgODcKRWxlbWVudCA4OApFbGVtZW50IDg5CkVsZW1lbnQgOTAKRWxlbW
VudCA5MQpFbGVtZW50IDkyCkVsZW1lbnQgOTMKRWxlbWVudCA5NApFbGVtZW50IDk1CkVsZW1lbnQgOTYKRWxl
bWVudCA5NwpFbGVtZW50IDk4CkVsZW1lbnQgOTkVZAlFbGVtZW50IDAJRWxlbWVudCAxCUVsZW1lbnQgMglFbG
VtZW50IDMJRWxlbWVudCA0CUVsZW1lbnQgNQlFbGVtZW50IDYJRWxlbWVudCA3CUVsZW1lbnQgOAlFbGVtZW50
IDkKRWxlbWVudCAxMApFbGVtZW50IDExCkVsZW1lbnQgMTIKRWxlbWVudCAxMwpFbGVtZW50IDE0CkVsZW1lbn
QgMTUKRWxlbWVudCAxNgpFbGVtZW50IDE3CkVsZW1lbnQgMTgKRWxlbWVudCAxOQpFbGVtZW50IDIwCkVsZW1l
bnQgMjEKRWxlbWVudCAyMgpFbGVtZW50IDIzCkVsZW1lbnQgMjQKRWxlbWVudCAyNQpFbGVtZW50IDI2CkVsZW
1lbnQgMjcKRWxlbWVudCAyOApFbGVtZW50IDI5CkVsZW1lbnQgMzAKRWxlbWVudCAzMQpFbGVtZW50IDMyCkVs
ZW1lbnQgMzMKRWxlbWVudCAzNApFbGVtZW50IDM1CkVsZW1lbnQgMzYKRWxlbWVudCAzNwpFbGVtZW50IDM4Ck
VsZW1lbnQgMzkKRWxlbWVudCA0MApFbGVtZW50IDQxCkVsZW1lbnQgNDIKRWxlbWVudCA0MwpFbGVtZW50IDQ0
CkVsZW1lbnQgNDUKRWxlbWVudCA0NgpFbGVtZW50IDQ3CkVsZW1lbnQgNDgKRWxlbWVudCA0OQpFbGVtZW50ID
UwCkVsZW1lbnQgNTEKRWxlbWVudCA1MgpFbGVtZW50IDUzCkVsZW1lbnQgNTQKRWxlbWVudCA1NQpFbGVtZW50
IDU2CkVsZW1lbnQgNTcKRWxlbWVudCA1OApFbGVtZW50IDU5CkVsZW1lbnQgNjAKRWxlbWVudCA2MQpFbGVtZW
50IDYyCkVsZW1lbnQgNjMKRWxlbWVudCA2NApFbGVtZW50IDY1CkVsZW1lbnQgNjYKRWxlbWVudCA2NwpFbGVt
ZW50IDY4CkVsZW1lbnQgNjkKRWxlbWVudCA3MApFbGVtZW50IDcxCkVsZW1lbnQgNzIKRWxlbWVudCA3MwpFbG
VtZW50IDc0CkVsZW1lbnQgNzUKRWxlbWVudCA3NgpFbGVtZW50IDc3CkVsZW1lbnQgNzgKRWxlbWVudCA3OQpF
bGVtZW50IDgwCkVsZW1lbnQgODEKRWxlbWVudCA4MgpFbGVtZW50IDgzCkVsZW1lbnQgODQKRWxlbWVudCA4NQ
pFbGVtZW50IDg2CkVsZW1lbnQgODcKRWxlbWVudCA4OApFbGVtZW50IDg5CkVsZW1lbnQgOTAKRWxlbWVudCA5
MQpFbGVtZW50IDkyCkVsZW1lbnQgOTMKRWxlbWVudCA5NApFbGVtZW50IDk1CkVsZW1lbnQgOTYKRWxlbWVudC
A5NwpFbGVtZW50IDk4CkVsZW1lbnQgOTkUKwNkZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dn
Z2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2
RkAgUPDxYCHgRUZXh0BQlFbGVtZW50IDBkZGQCc/YoLQgXzJamhzzCRizwdOQs9w==" />

And at the end of it, this is all that remains.

<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwULLTEwNjkzMDQ2NzM
PZBYCAgMPZBYCAgUPDxYCHgRUZXh0BQpFbGVtZW50IDIzZGRky26p9Cn4TiZyx2yoBv7mRgWW+gQ=" />

It is a frightening thought, but there are plenty of sites with far more ViewState than this. I am talking some people have talked to me about pages that are multiple megabytes in size.

In the following example I use a simple page with 1 DropDownList, 1 Button, and 1 Label.

Here is the starting Default.aspx page.

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>Untitled Page</title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:DropDownList ID="DropDownList1" runat="server" EnableViewState="true" />
        <asp:Button ID="Button1" runat="server" Text="Postback" />
        <asp:Label ID="Label1" runat="server" />
    </div>
    </form>
</body>
</html>

Here is the starting Default.aspx.cs code-behind file.

using System;
using System.Web.UI.WebControls;

public partial class _Default : System.Web.UI.Page 
{
    protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            // Create my data source (this would normally be data access or something similar)
            System.Collections.Generic.List<ListItem> myData = new System.Collections.Generic.List<ListItem>();
            for (int i = 0; i < 100; i++)
            {
                myData.Add(new ListItem("Element " + i.ToString(), i.ToString()));
            }
            DropDownList1.DataSource = myData;
            DropDownList1.DataBind();
        }
        else
        {
            Label1.Text = DropDownList1.SelectedValue;
        }
    }
}

Now we can make a little change here. We need to disable ViewState. The other change that we need to make is that we now have to populate the data on every request. We also need to make sure that we populate the DropDownList before Initialization of the Page occurs. This means we should override OnInit and place out code before base.OnInit. The reason we do this is so that we have data loaded in the DropDownList before the selected value of controls are set for us. Otherwise we would have to handle this on our own.

This is the new Default.aspx

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>Untitled Page</title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:DropDownList ID="DropDownList1" runat="server" EnableViewState="false" />
        <asp:Button ID="Button1" runat="server" Text="Postback" />
        <asp:Label ID="Label1" runat="server" />
    </div>
    </form>
</body>
</html>

This is the new Default.aspx.cs

using System;
using System.Web.UI.WebControls;

public partial class _Default : System.Web.UI.Page 
{
    protected override void OnInit(EventArgs e)
    {
        // Create my data source (this would normally be data access or something similar)
        System.Collections.Generic.List<ListItem> myData = new System.Collections.Generic.List<ListItem>();
        for (int i = 0; i < 100; i++)
        {
            myData.Add(new ListItem("Element " + i.ToString(), i.ToString()));
        }
        DropDownList1.DataSource = myData;
        DropDownList1.DataBind();
        base.OnInit(e);
    }

    protected void Page_Load(object sender, EventArgs e)
    {
        if (IsPostBack)
        {
            Label1.Text = DropDownList1.SelectedValue;
        }
    }
}

Enjoy not having TONS of extra ViewState. Remember that ViewState is extremely useful, but can cause problems if you ignore its existence completely. It can lead to huge pages that are quite slow.

Long Code Lines in Articles and Tutorials

While publishing articles for ASP Alliance I often take the time to fix long code lines I find in the articles. These bother me greatly, because they make web pages and thus the article ugly and difficult to read. I hate having to scroll horizontally to read a long line of code. It is annoying and takes more time. I don't get why people don't trim their code. I keep my code neatly trimmed when I'm writing articles, and also whenever it is code I am writing in general. I never want code lines to be too long. I have no problem scrolling vertically, but there should be some set limits on how long lines should ever be especially when the lines will be posted on the Internet.

Some of the ugliest sites I've ever seen are the ones where text has gotten too wide and has taken over the layout of a page. Widths have been stretched and the page extends beyond its intended positioning. I admit this has happened plenty of times on sites with which I am associated and I am ashamed. It would be nice if I could convince the rest of the development community of the importance of having code be easy to read. How can I possibly intend to help other people understand something through an article or tutorial when my code is difficult to read. I'm not helping their understanding at all by having them struggle to read the code let alone understand it.

I think overall the software development community could use a facelift. My site included. Sadly my skills in the area of design are quite lacking. Formatting text in a readable manner is about the extent of my skills, but I believe that is likely the most important task to complete.

Get rid of lines like this one.

MyCompany.Controls.DropDownList commentselectionddl = SomeTemplatedControlOnThePage.FindControl("commentselectionddl") as MyCompany.Controls.DropDownList;

Replace them with lines like this one.

MyCompany.Controls.DropDownList commentselectionddl = 
    SomeTemplatedControlOnThePage.FindControl("commentselectionddl") as MyCompany.Controls.DropDownList;

For the benefit of everyone involved in this wonderful community of developers, format your code. Make it more readable. Don't let lines trail off into the distance. Keep them short and concise. Use simple examples, and never make code more complicated just to show how smart you are. I've seen plenty of code where authors attempt to complicate their own code seemingly to make themselves appear smarter. Remember, when you write code you should not be writing for yourself. Write the code for someone else to learn. Write to help other people and make the community as a whole a better place. Sure it benefits you when you teach others, but remember that at the end of the day other people will be reading what you write.

Passing ViewData to User Controls in ASP.NET MVC Preview 4

Yesterday I was upgrading an ASP.NET MVC site from Preview 2 to Preview 4. For the most part this is an easy process. Some assemblies needed to be updated and some information updated in the web.config file. Route declaration changed, but the same information is still required, so updating that was pretty easy. The released documentation and examples clearly show these changes. I also had to make the change to my controller actions so that they return ActionResults instead of being void methods. Again, this is a fairly simple task.

There was an adjustment to user controls which caused some problems though. Yasir and I were working on this task together so we could both learn about the preview 4 changes in MVC. We scoured articles looking for this information, and we tried many different changes to the user control.

Our problem was that we could not get access to the ViewData. ViewData in the user control was always null. It was quite annoying. Eventually in desperation after reading articles and release notes and not finding what we were looking for, we started reading the source code for MVC. We took a look at this file, which is the one containing the extension method we were calling in the .aspx files. System.Web.Mvc.UserControlExtensions This file contains the extension method RenderUserControl, which our code used.

The .aspx code we were using

<%
   =Html.RenderUserControl("~/Views/Shared/MyUserControl.ascx", ViewData, new { DisplayTitle = "Hello World!" }) 
%>

RenderUserControl calls this method called DoRendering

private static string DoRendering(ViewUserControl instance, ViewContext context, object controlData, object propertySettings) {
            ViewPage dummyPage = new ViewPage();
            dummyPage.ViewContext = context;
            dummyPage.Controls.Add(instance);
            dummyPage.InitHelpers();

            //set the properties

            SetUserControlProperties(instance, propertySettings);

            if (controlData != null) {
                instance.ViewData.Model = controlData;
            }
            else {
                instance.ViewData = context.ViewData;
            }

            //Render it

            string result = HtmlExtensionUtility.RenderPage(dummyPage);

            return result;
        }

In my haste to find a solution, I didn't read the code very carefully. All I noticed was exactly how to solve our problem. I discovered that the controlData parameter we were passing to this method was being assigned into instance.ViewData.Model. I didn't even read the next couple of lines which gave away the real answer. We went and added in the .Model to our code so that it could access the ViewData. The ViewData we were passing was going into a property of the ViewData called Model, so we just used it. We went to our user control and we changed the code there. This felt really bad to us, but we went along with it.

Today I realized our error. I was thinking about the code we had looked at this morning, and I realized our mistake. I was wondering, "Why was it checking if control data was null? If it was null shouldn't ViewData.Model be null? That's our ViewData right?" That is when I realized what must have been after that.

We were not supposed to be using Model. We had some standard ViewData. No strongly-typed ViewData was being used. We were using an the standard ViewDataDictionary object and passing it to the user control. A ViewUserControl object (which is the class we were inheriting from) supports generics. It was at that time when I realized exactly what everything was being used for. The Model property and the controlData parameter are there for strongly typed ViewData. You can use boxing and unboxing or generics to pass strongly-typed data to your ViewControl. The parameter and the generic Model were added so that the ViewData property of the ViewUserControl would not be interfered with.

This solution the MVC guys use allows custom ViewData to be used without having to muck the ViewData property of the user controls. Since they added this extra piece it could be the generic one. So now I have gone and changed my code. I no longer pass the ViewData as was done in the past. It is now simply grabbed from the context of the page. I pass a null value instead of passing in any controlData to the RenderUserControl method. It wires everything up for me now.

<%=Html.RenderUserControl("~/Views/Shared/MyUserControl.ascx", null, new { DisplayTitle = "Hello World!" })%>

As a reminder to everyone. Open source code means that you can go look at the code. If you are not sure how something works, just go read the code. It is freely available on CodePlex. You can look at how everything is working and get a much better understanding of the inner workings of the technology.

Difference Between Value Types and Reference Types in C#

I recently wrote an article for C# beginners in which I explain the differences between value types and reference types in C#. It was published on ASP Alliance today. If you're new to C# or are even a little fuzzy on these concepts, I recommend you check it out. Please offer some feedback good or bad. I really do read and appreciate feedback I receive. I try to improve what I write based on what others tell me.

I've seen so many people run aground with errors stemming from misunderstandings about and just forgetting the importance of value and reference types.

Good day and happy programming!

Handling Password Recovery

I recently answered a blog post about how to handle password recovery in ASP.NET. My first thoughts when I read this questions are along the lines of, "Ah! Don't recover passwords!"

With any authentication system it is important to remember this one thing passwords should always be hashed. I don't care who you are or what system you're using, you should never ever have passwords stored in your system which are not at least encrypted in some format. In ASP.NET you want to use hashing. Being able to "recover" a password implies that the password is in a form that you could make it user-readable.

This is bad since it means that if someone managed to obtain your password data they could potentially obtain people's passwords. Considering that lots of users will use the same password in multiple places, that could be very bad.

What you need to do instead of recovering a password is to reset a user's password. They can then log in using the new password and change it to the one they want. This allows you to keep their password secure and to still allow them to recover from the issue. It just makes it a little bit more complicated for the user, but having the extra security is by far worth it. Most users will agree with you on this.

As a user I am quite upset when a site is able to "recover" my password. I am annoyed by the password policies of quite a few sites on the Internet. I've had sites limit the length of my passwords, limit the types of characters I may use, and many other sometimes asinine things.

Just always use password resets. It just makes things a little bit safer for your users. They'll be thanking you for it even if they don't actually express it to you.

Here you can read about ASP.NET Password Recovery. I just recommend you use hashed passwords and only allow password reset and not password retrieval.

Web Application Projects are better than Web Sites

Recently I was explaining the difference between the web application project and the web site to the budding developers I've been working with. I suffered greatly while using web sites instead of web application projects. I remember having a great deal of pain while my assemblies dueled each other. Scott Guthrie posted about the dueling assembly problem.

Dueling Assembly Reference Problem

The problem I refer to as a “dueling reference” occurs when you setup multiple file-based references to assemblies from a VS 2005 Web Site Project that are each updated dynamically (using .refresh files), and which in turn have dependencies on different versions of a common shared assembly library.

This one reason was more than enough in my opinion to switch to web application. It took some sites which could take upwards of five to ten minutes to compile and made them take ten seconds. I can't ask for much better improvement there.

Another great benefit of using Web Application Projects instead of using the Web Site is that there is a project file managing what is and is not included. On a few of the projects I've worked on in the past we have had some trouble with source control and web sites. It is much easier if you can just define what is and is not included in the web site. With the classic web sites, it was a loose system. The site was defined as a folder in the file system. With the web application project your site is defined using a project file which dictates which files will and will not be included.

On really annoying part of web sites are the refresh files used for adding assemblies into the bin folder. There are files which say where the assembly can be obtained. If you're working with source control you need to have these files in source control. The problem is that you need to not have the actual binaries in that location in source control or the refresh files will not work correctly. This creates some huge headaches because Visual Studio wants to check in these files (assemblies) being included by the refresh files. Ouch.

The feel of web applications is more consistent with everything else in Visual Studio. This consistency is nice, since there now is "Open Web Site" and "Open Project". It is quite annoying to have two different things to work with. If they were both just project that would make it so much simpler.

Far too many people are still using the sites, so I doubt that Microsoft will remove them from future versions of Visual Studio anytime soon. It doesn't really hurt me to have them, but I pretty much exclusively use Web Application Projects over Web Sites. I even do this for small little one shot sites. I've just grown to like them so much that I cannot turn back.

If I have to deal with refresh files again, I'll just go crazy.

Generic Recursive Find Control Extension

Earlier today I posted about a Recursive Find Control Extension Method. Since then, I was informed by Steve Smith that I should check out the generic find control method which Aaron Robson has on his blog. He has some pretty nice methods there, so I just adapted them to be extension methods now. As extension methods the code looks like this.

/// <summary>
/// Similar to Control.FindControl, but recurses through child controls.
/// </summary>
public static T FindControl<T>(this Control startingControl, string id) where T : Control
{
    T found = startingControl.FindControl(id) as T;
 
    if (found == null)
    {
        found = FindChildControl<T>(startingControl, id);
    }
 
    return found;
}
 
/// <summary>     
/// Similar to Control.FindControl, but recurses through child controls.
/// Assumes that startingControl is NOT the control you are searching for.
/// </summary>
public static T FindChildControl<T>(this Control startingControl, string id) where T : Control
{
    T found = null;
 
    foreach (Control activeControl in startingControl.Controls)
    {
        found = activeControl as T;
 
        if (found == null || (string.Compare(id, found.ID, true) != 0))
        {
            found = FindChildControl<T>(activeControl, id);
        }
 
        if (found != null)
        {
            break;
        }
    }
 
    return found;
}

And this new extension method is called very similarly to how we called the previous code. It is called using the following code.

Label theOtherLabel = LoginView1.FindControl<Label>("OtherControlToFind");
if (theOtherLabel != null)
{
    theOtherLabel.Text = "Found this one also!";
}

It is able to find the Label inside of the the following LoginView.

<asp:LoginView ID="LoginView1" runat="server">
    <LoggedInTemplate>
        <asp:Panel ID="Panel1" runat="server">
            <asp:Panel ID="Panel2" runat="server">
                <asp:Panel ID="Panel3" runat="server">
                    <asp:Panel ID="Panel4" runat="server">
                        <asp:Panel ID="Panel5" runat="server">
                            <asp:Label ID="ControlToFind" runat="server" Style="color: Red" />
                            <asp:Label ID="OtherControlToFind" runat="server" Style="color: Blue" />
                            <asp:Label ID="AlwaysShow" runat="server" Text="This shows no matter what." />
                        </asp:Panel>
                    </asp:Panel>
                </asp:Panel>
            </asp:Panel>
        </asp:Panel>
    </LoggedInTemplate>
</asp:LoginView>

I've also updated my FindControl method so that is just an overload of the previous method. Since my extension method takes the same parameters and returns the same type as the existing find control method I needed to rename it FindControlR. I've now updated it so it takes an extra parameter, but doesn't have a different name. I've added a boolean "recurse" parameter. If this is set to false it just calls the standard FindControl method and if it is set to true it will recursively call itself finding the desired control.

This is the final product followed by how one would call it.

/// <summary>
/// Searches recursively in this control to find a control with the name specified.
/// </summary>
/// <param name="root">The Control in which to begin searching.</param>
/// <param name="id">The ID of the control to be found.</param>
/// <returns>The control if it is found or null if it is not.</returns>
public static Control FindControl(this Control root, string id, bool recurse)
{
    if (!recurse)
    {
        return root.FindControl(id);
    }
    System.Web.UI.Control controlFound; 
    if (root != null) 
    { 
        controlFound = root.FindControl(id);
        if (controlFound != null)
        {
            return controlFound;
        }
        foreach (Control c in root.Controls) 
        {
            controlFound = c.FindControl(id, true);
            if (controlFound != null)
            {
                return controlFound;
            }
        } 
    } 
    return null;
}
Label theLabel = LoginView1.FindControl("ControlToFind", true) as Label;
if (theLabel != null)
{
    theLabel.Text = "Found it!";
}

I hope everyone else sees the great value in extension methods.

See More Recent Projects in Visual Studio

I usually only open between 5 and 10 Visual Studio projects on a regular basis, so I love the recent projects section of the Visual Studio Start Page. The problem is that when I add projects to my solutions they get added into the recent projects window and it makes it so I now have to go get my solution open from the file system. This irritates me quite a bit.

So for anyone who wants to increase the Recent Projects section of the Visual Studio Start Page from this.

RecentProjectsSmall

To this!

RecentProjectsLarge

Just open up the Tools menu item at the top select options and follow the instructions on this nice screen shot.

RecentlyUsedItemListMenu

And enjoy not digging into the file system to get to that solution file.

Tests Not Executed In Test Results

Earlier today, as I was working with the Protégé I've been referring to previously, we were debugging some code, and we ran into a little bug. Our tests results would not execute. We tried restarting Visual Studio and a lot of other stuff and it didn't fix it. We eventually just restarted the machine, and that fixed the problem. We figured that even though it wasn't the most graceful solution, it is one we knew would work.

This is the error message we were receiving. None of our tests were executing and it wasn't very clear about why. We did figure out that it had to do with the code coverage we had previously been running.

TestResultsNotExecuted

These guys managed to recreate the same error a little later, and they found a solution. Here is the solution to this problem.

What is going on is that we enabled code coverage and then we decided to start debugging.

So we started debugging and clicked "OK" through the message about how it was going to disable code coverage because you can't have it enabled while debugging.

Then we hit a break point and decided to stop debugging. All is seemingly still working correctly.

We attempt to run the tests again. This is where the %#$^ hits the fan. Suddenly we get that error message listed above and we have no idea why. It just doesn't want to let us execute the tests no matter what we tried.

Those budding young developers, as I said, found the error again and that time decided to pursue it further and discovered the root of the problem as well as how to fix it.

There is a process called VSPerfMon which is running in the background and is preventing the tests from being executed. It is the program which is running in the background to keep track of code coverage, and if you stopped the execution in the middle of a test it doesn't close correctly. If you kill that process you will once again be able to run your tests. To kill it you can get into the task manager select it from the processes list and end the process.

Have fun testing your code with tests that actually run.

Visual Studio Keyboard Shortcuts Disabled in Code Snippets

Since Visual Studio 2008 came out I've been extremely impressed with the software. One shortcut which I believe probably exists in CodeRush and Resharper is the ability to find the using directive needed at any given time. in VS2008 you can press ctrl + . and a little menu will appear which will add using directives for you. This makes writing code so much easier, because I don't have to go to the top of my file to add using statements. I type the name of what I need, press ctrl + . and keep going. I also love using the shortcut snippets in Visual Studio.

These snippets allow me to quickly and easily write properties, for loops, etc. I pretty much use these snippets whenever I have one for the task. They only require you fill in the necessary fields. The problem is that when you are filling in the information for one of these snippets it disables keyboard shortcuts. I can no longer have it automatically add my using directive to the top of the file. It will not bring up the menu.

In order to get this functionality to work again I have to complete the code snippet I am working on and go back to what needed the namespace added to it. I am then able to use the shortcut to add in my using directive.

These are a few examples of snippets I use in Visual Studio. I've been using var a lot lately for my foreach loops since I don't have to worry about this issue with it, but I prefer to avoid var.

foreach (var item in collection)
{

}

for (int i = 0; i < length; i++)
{

}

using (resource)
{

}

Yes, I used a using statement in this example so I could write about using a using shortcut to generate a using statement which needs a using directive.

Perhaps Microsoft will fix this and allow the keyboard shortcuts to still work while using these snippets. Maybe some of the third party tools already get around this. Resharper? CodeRush? Anyone else?