Thursday, February 18, 2010

DRY up your content using ASP.NET user controls


I was doing a little code-cleanup on an app I support this week.  I was trying to find some places where I could implement the DRY (don't repeat yourself) methodology.  It was fairly easy picking, because this app is leaning a little more toward the RYE (repeat yourself everywhere) methodology.  Anyway, I came up with a way to use ASP.NET User Controls in a project to move some of that repetitive content out of the individual pages, and into a centralized place.

This may not be anything new to anyone, but I had never thought of using a user control for content.  I created two controls, one for some contact information that was used on every page (pointing to different departments in the company), and one to encapsulate some page framework that needed to be slightly different depending on where the application was deployed (I was able to put this logic into the user control and read the location from the web.config).

The contact control renders asp labels to display content on the page, and the framework control renders standard divs.  The code had to be slightly different in the code-behind to search for the controls, but once you set up the controls this way, you wouldn't need to ever change the c# code if you wanted to add a new label or div to the .ascx file.

Anyway, like I said I just came up with this idea earlier this week, but I'm anxious to add it to the toolkit.  I'm already thinking of some more uses for this.  You could perhaps have a 'snippets.ascx' file that had all the reusable content, and enclose each piece in a div.  Then all you'd have to do is call the user control in your app with the name of the div you wanted to render.

i.e. <userControl:Snippets ID="SnippetControl" DivID="WhateverDivIwantToShow" runat="server" />

I'll add the relevant code.  Should be easy to see what I'm talking about.

------------------------------------------------------------------


front-end for user control to deterministically expose asp label controls:

<asp:Label ID="Payroll" Visible="false" runat="server">
<p>
    For questions regarding the content of your documents contact the Payroll Department at 555-5555.
</p>
</asp:Label>

<asp:Label ID="HelpDesk" Visible="false" runat="server">
<p>
    For technical questions or support please contact the Help Desk at 555-5555.
</p>
</asp:Label>


   
c# code-behind for user control:

public partial class Contact : System.Web.UI.UserControl
{
    string strLabelID = string.Empty;

    public string LabelID
    {
        get
        {
            return strLabelID;
        }
        set
        {
            strLabelID = value;
        }
    }

    protected void Page_Load(object sender, EventArgs e)
    {
        foreach (Control ctrl in Controls)
        {
            if (ctrl is Label)
            {
                if (ctrl.ID == strLabelID)
                {
                    ctrl.Visible = true;
                }
            }
        }
    }
}



usage of control:

<ucContact:Contact ID="PayrollContact" LabelID="Payroll" runat="server" />

<ucContact:Contact ID="HelpDeskContact" LabelID="HelpDesk" runat="server" />

------------------------------------------------------------------------------

Another Example:

front-end for user control to deterministically expose generic div elements:

<div id="Header" visible="false" runat="server">
    put stuff in here for the header
</div>

<div id="Footer" visible="false" runat="server">
    put stuff in here for the footer
</div>



c# code-behind for user control:

public partial class PortalFramework : System.Web.UI.UserControl
{
    private string strDivID = string.Empty;

    public string DivID
    {
        get
        {
            return strDivID;
        }
        set
        {
            strDivID = value;
        }
    }

    protected void Page_Load(object sender, EventArgs e)
    {
        foreach (Control ctrl in Controls)
        {
            if (ctrl is HtmlGenericControl)
            {
                if (ctrl.ID == strDivID)
                {
                    ctrl.Visible = true;
                }
            }
        }
    }
}



usage of control:

<ucFramework:PortalFramework ID="PortalFrameworkHeader" runat="server" DivID="Header" />

<ucFramework:PortalFramework ID="PortalFrameworkFooter" runat="server" DivID="Footer" />