User Controls or Custom Controls

Which should you use? Explore the difference between these two control types.

asp.netNOW Q&A


TECHNOLOGIES: User Controls | Custom Controls


User Controls or Custom Controls

Which should you use? Explore the difference between these two control types.


By Josef Finsel


Q: What is the exact difference between a user control and a custom control?

- KS, India


This is a good question and the short answer, if you haven't modified your VS .NET layout, is you drag user controls from the left side of the screen and custom controls from the right. Although technically this is correct, I know you want a better answer. In this column I'll build a user control and transform it into a custom control to illustrate the difference. I use C# in this article, but you can download a VB .NET solution to this question.


Start with a simple page-count control that interacts with a Web service at This simple Web service takes an AccountID, the URL, and the IP Address. Create a new project (or download this article's code files) and get a Web reference to the Web service.


Now, select Project | Add Item and choose User Control. Name the user control PageHitCounter and open it in design mode. Personally, I don't like grids, so I turn off the grid mode, drag a Literal from the toolbar, and name it ltlPageCount. Now you're ready to code (see Figure 1). You create a reference to the Web service and define a couple of strings. The most complicated part creating the URL to send to the Web service. Once you define that, you open a dataset and retrieve the data, format it, and output it to the Literal tag.


private void Page_Load(object sender, System.EventArgs e)


com.reluctantdba.pagecounter.Service1 qt = new com.reluctantdba.pagecounter.Service1();

   DataSet ds ;

   String strPageHits;

   String strURL ;

   NameValueCollection serverVars = Request.ServerVariables;

   if(serverVars.GetValues("HTTPS").ToString()  == "off")


      strURL = "HTTP://";




      strURL = "HTTPS://";


   strURL +=  serverVars.GetValues("HTTP_HOST").ToString() +  serverVars.GetValues("URL").ToString();

   ds = qt.PageHit("893407A7-0AF3-4076-801D-2AD1E5D156DA", strURL,


   DataTable tbl =  ds.Tables[0];

    if( tbl.Rows[0].ItemArray[2].ToString() == "" )

      strPageHits = tbl.Rows[0].ItemArray[0] + "<br>Since " + tbl.Rows[0].ItemArray[1];


      strPageHits ="";

   ltlPageCount.Text = strPageHits;


Figure 1. Here is the code of the user control. The most intricate part of the process is defining the URL to send to the Web service.


All you need to do to use your UserControl drag it onto a Web form from the project listing. Then you can build and browse to see the page hits. You also can reuse this user control on any of the Web pages within this Web site. Piece of cake.


What's a Custom Control?

User controls are specific to a Web page; custom controls are the ones you load into your server and toolbox. All the items in the WebForms toolbar - Textbox, DataGrid, AdRotator, and so on - are custom controls. If you are building something other folks will want to use, you'll want to build it as a custom control. This is as simple as selecting a new project of Web Control Library. Unfortunately, this is only available for VS .NET Enterprise Edition, but you can load the code and make appropriate changes to this article's code download; you simply don't have a way to start it up conveniently for new custom control projects if you don't have VS .NET Enterprise.


The first thing you'll notice about the new Custom Control (rdbaPageCounter.vb) is it has no HTML area. Instead of adding HTML objects ,you need to spit out HTML code much like when you had to parse a record set to output a table. You'll also notice the code looks a little different (see Figure 2).


  [DefaultProperty("AccountID"), ToolboxData("<{0}:rdbaPageCounter


public class rdbaPageCounter : System.Web.UI.WebControls.Label


   private string _AccountID ;

     [Bindable(false),   Category("Registration"), DefaultValue("")]

   public string AccountID


   get   {    return _AccountID;    }

   set   {    _AccountID = value;    }


Figure 2. This code shows the beginning of the custom control. You'll notice it looks slightly different from the user control shown in Figure 1.


In addition to the public class statement, you have a piece of code that defines the DefaultProperty. This is necessary because you can interact with custom controls through the properties window as you would a textbox or datagrid. The second thing to notice is I've inherited the WebControls Label type. This means my new custom control has all the Label control's content in addition to  whatever I add (in this case, the AccountID property). The next several lines of code define Get and Set for the property - but the more interesting part would be the [Bindable(False), Category("Registration"), DefaultValue("")] section. Here you can define how the property shows up, assign it a default value, and decide whether it can be data-bound. Otherwise, it's a straightforward property.


You could cut and paste the code that calls the Web service and creates the output string, but you need to make two minor modifications. You can't access ServerVariables directly anymore, so you need to use HttpContext.Current.Request.ServerVariables (although I could define a variable rather than using the full declaration each time). Also, instead of hard-coding the AccountID, you can replace it with this.AccountID.ToString (in VB .NET, use Me.AccountID.ToString) and read it from the property window. In fact, I did this with several other pieces of information from the dialog box (see Figure 3).


string strURL ;

if(HttpContext.Current.Request.ServerVariables["HTTPS"] == "off")

   strURL = "HTTP://";


   strURL = "HTTPS://";

strURL += HttpContext.Current.Request.ServerVariables["HTTP_HOST"] + HttpContext.Current.Request.ServerVariables["URL"];

ds = qt.PageHit(this.AccountID.ToString(), strURL, HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"].ToString());

DataTable tbl = ds.Tables[0];

if( tbl.Rows[0].ItemArray[2].ToString() == "")

   strPageHits = tbl.Rows[0].ItemArray[0].ToString() + "<br>Since " +




output.AddStyleAttribute(HtmlTextWriterStyle.BorderStyle, this.BorderStyle.ToString());

output.AddStyleAttribute(HtmlTextWriterStyle.BorderWidth, this.BorderWidth.ToString());



output.AddStyleAttribute(HtmlTextWriterStyle.Color, this.ForeColor.ToKnownColor().ToString());





Figure 3. In this code, you apply properties to your custom control.


The key to formatting your control at run time is to use the AddStyleAttribute method. I'm using it to add to the span tag's style property. This isn't well documented and it took some time for me to find out how to do it, but because I've covered the major examples in the previous code you can build your control. First, however, you must do two more things. You need to add the control to your toolbar, then add it to a project for testing.


To add your control to your toolbar, right-click on your toolbar and click on Customize Toolbox. Make sure you're in the .NET Framework Components tab (not the COM Components tab), then select Browse. You should be able to find your DLL and add it to the toolbar (a reference to the PageCounter service also will be added). Now you need to add an additional project. Right-click on the solution in the Project Explorer window and select Add New Project. Make sure it's a Web Application. Now you can drag your new control onto WebForm1.aspx. If you want, you could build and browse to see the page hit or you can modify the properties and save it to see the results.


Now you have a functioning custom control you can tweak and modify from the properties page. But there's something missing - it doesn't change in the IDE when you modify the properties. We'll examine this next time because the designer deserves its own article altogether. Until then, play with this control and feel free to e-mail me with improvements you'd like to see for the next column. And keep your ASP.NET questions coming to me at [email protected].


The code referenced in this article is available for download.


Josef Finsel is a software consultant for a global consulting company and specializes in .NET and SQL Server. He has published a number of VB, .NET, and SQL Server articles, and when he isn't hanging around the aspnetpro forums you can find him working on the syntax for FizzBin.NET, a programming language that works the way programmers have always suspected. He's also author of The Handbook for Reluctant Database Administrators (Apress).





Hide comments


  • Allowed HTML tags: <em> <strong> <blockquote> <br> <p>

Plain text

  • No HTML tags allowed.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Lines and paragraphs break automatically.