ASP.NET WebControls do more than just allow you to write reusable components. They can provide an entire approach to Web application development, allowing you to bring a new level of OOP to the UI and letting you program declaratively.
Lately I've come to notice that no other programming term has more definitions than declarative programming. In this article, I will attempt to explain it in terms of how it applies to .NET development, specifically ASP.NET through the use of WebControls. I'll do this by illustrating some real-world examples that I have used in my own projects. In the end, I hope to leave you with an understanding of what declarative programming is, how you can use it when developing ASP.NET Web applications, and how, with the help of WebControls, to use it as an approach to ASP.NET development.
This article assumes knowledge of ASP.NET and the use of the WebControls Microsoft provides. Some knowledge of custom WebControls, at least in concept, is helpful. But most importantly you should have an open mind for looking at what is most likely a different way of programming sites in ASP.NET.
The Calendar control is another great example of Web Control-based declarative programming in ASP.NET. Next time you pop one onto a WebForm, view the resulting source and you'll see the amount of HTML the code behind the control has drawn for you. All you've had to do is declare some of its properties.
OK, time to pick a fight. What is declarative programming? Well, as I stated above, I've seen many definitions of that term lately; but most of them pretty much break down into similar descriptions. It is a style of programming whereas at one level you define, in detail, how a variety of things are done, and from another level you instruct as to what needs to be done. Let me explain with a couple of examples in the context of languages I'm sure you already know.
Back to the Basics
Think about how you create a simple table in HTML: the first thing you do is define your table tags using <TABLE> and </TABLE>. A table consists of rows and columns, so of course you use <TR> and </TR> to declare each row, and then one or more <TD> and </TD> tags to define each column in each row. This is a table at its simplest form:
<TABLE> <TR> <TD>This is cell 1 in row 1</TD> <TD>This is cell 2 in row 1</TD> </TR> <TR> <TD>This is cell 1 in row 2</TD> <TD>This is cell 2 in row 2</TD> </TR> </TABLE>
I know, you know this already, but indulge me because I promise I will build on this idea. This simple code tells the rendering engine in the browser to draw a table on the page. Obviously there is some machine code at the browser level to actually draw the physical table on the page and display it properly. Now, what do you do to alter the way this table looks? Say, for example, you want thicker borders, or some extra padding and everything in the first column to be right justified. This is where the border, cellpadding, and align attributes come in. By simply adding them to your HTML tags, you've totally altered the way the table looks. You didn't need real code because you just alter attributes, or properties if you will. The rendering engine that interprets the HTML knows how to alter the appearance of the table based on what you asked for. Remember the what to do and how to do it separation I mentioned earlier?
OK, let's turn the clock back all the way to the release of ASP.NET in February of 2002 (betas not counting). Microsoft introduced the Web Control which let developers do things in what appears to be HTML-like syntax. Starting with a simple Web Control, here is how to declare a textbox :
I'm leaving out the properties here for brevity, but I think you know where I'm going with this. Since browsers can still only understand HTML, the ASP.NET parser takes this textbox declaration and turns it into the appropriate HTML; and based on various properties you can change, the browser renders the HTML slightly different. The ever-popular DataGrid control, though more complex, works the same way. It gives developers the appearance of an actual grid with all sorts of customizable features; much akin to its WinForm cousins. But as I said, the browser can still only understand HTML, so ASP.NET once again converts a simple looking declaration, <asp:datagrid> </asp:datagrid>, into what turns out to be a regular HTML table. All the properties you can set on the DataGrid, and all the programming you can provide to customize it and to fill it with data, will still only result in an HTML table, albeit a pretty complex one in the end.
This is declarative programming in ASP.NET at its simplest. I say simplest, because you, as the ASP.NET developer, have not really had to do much to get the grid (or the textbox) to display, other than drag it on a WebForm, or code the <asp:...> tags. All the code that actually draws the resulting HTML has been done for you by the folks at Microsoft?it has been programmed declaratively. In the world of Web Controls using ASP.NET, declarative programming moves some of the code off of the WebForm and into the Web Controls. Let's go back to the definition I gave before and apply it here: the Web Controls have determined how all sorts of things are to be done (rendered in this case), and the WebForm has determined what needs to be done.
If all of this sounds familiar to you, it should. This is the very basis of object-oriented programming. You design a class and expose properties, methods, and events, and it is a form of declarative programming. When you gave your objects all that cool functionality and things it can do by putting a lot of programming into them, you've relieved just that much work from any developer (yourself included) that uses your classes. Now you're seeing a classic design paradigm at work in the UI level. Heck, this has been familiar in the UI since Visual Basic 1.0 when you first dropped that textbox (remember the VBX?) on to your first form.
Are Grids All You Got?
Not by a long shot. Since the release of ASP.NET 1.0, third-parties have been providing developers with all kinds of great Web Controls to make our lives easier. Let's take a brief moment to bow our heads and thank them for all the code they've saved us... OK, back to work. In Visual Studio 2005, Microsoft has increased the number of Web Controls that come with Visual Studio to include some improved replacements of old ones as well as some very interesting new ones.
The GridView Control
What better way to start a section titled, "Are Grids All You Got?" than to talk about what? Another grid of course! The GridView in ASP.NET 2.0 is a replacement for the DataGrid (though the DataGrid is still supported) and adds some functionality built into it that in the past, needed code from the developer. As useful as the DataGrid can be, adding paging and sorting functionality only changes some visual aspects of the grid and raises some events. The WebForm developer has to provide the code for changing the sort source or the page index, then rebinding the data. The new GridView performs all this for you with the simple setting of some properties. Think about what I talked about earlier and you'll realize that the magic behind this is that the code you once had to write at the page level has now been written by Microsoft at the Web Control level, and its functionality is exposed to you by way of properties (Figure 1).
In ASP.NET 2.0, Microsoft will provide a few more controls to save developers some programming (both visually and code-wise) in areas where classically developers have had to build things manually. The DetailsView and FormsView WebControls provide other ways to display information using little or no code at all.
The DetailsView Control
The DetailsView Web Control is making its debut in Visual Studio 2005 and offers another way to look at a collection of data. As the grids show tabular data with records represented in rows and record details represented in columns, the DetailsView shows one record at a time with the fields displaying vertically and their corresponding values displaying next to them (Figure 2). The data binding intelligence built into this control is the same as that of the GridView (or the DataGrid for that matter) control; the display is what's different. As with many other WebControls you've used in the past, extensive styling is provided in this and all the other controls. I'll talk a little more about styling later because it is a key issue when it comes to providing reusability in custom Web Controls.
The FormView Control
The FormView Web Control, also new in Visual Studio 2005, displays data in a similar fashion to the DetailsView Web Control but it also offers the option of displaying data as an actual data-entry form. I mentioned earlier that Microsoft has given developers ways to do things that they had to do manually before; well, this is a perfect example. More often than not, most developers have programmed data-entry forms by building the WebForm out of labels, textboxes, buttons, and other controls they need in order to display and edit data (Figure 3). The FormView Web Control allows you to do this through declarative programming by simply binding your control to a data source. The intelligence programmed into the FormView control will build a data-entry form for you and display it along with other ancillary visual aides as well, such as paging links and headings. Other properties in this control let you reuse the control in other situations. For example, setting the DefaultMode property to ReadOnly changes your form to a view-only style where there are no textboxes, and instead data is displayed in labels. Think about how much work would be required to accomplish this in the traditional manner by building the WebForm manually.
Web Controls that provide you with the ability to program declaratively in ASP.NET do not have to perform visual rendering. Visual Studio 2005 comes with a series of DataSource Web Controls that allow developers to define data queries. Instead of using code to open database connections, create commands, and execute SQL queries returning DataSets or DataReaders, the SqlDataSource control allows you to define the database connection and query in control properties. The control can then be bound to any of the above mentioned new controls or to any custom Web Controls that you may write. This database information and the binding to other controls can be performed with no coding whatsoever?a perfect example of declarative programming. Visual Studio 2005 provides other DataSource Web Controls, including one that lets you bind to business objects.
There are several other new Web Controls in Visual Studio 2005 that are designed to save developers a lot of visual design and coding time. The Login control renders a group of labels and textboxes that make up a generic login form. The ChangePassword control does the same but with a form that gives you the visual objects and functionality you would typically use to change a user's password. Web Controls such as these, which render what appear to be entire forms or a grouping of related data-entry controls, are new to Visual Studio 2005, but the ability to create them has been around since ASP.NET 1.0.
Web Site by way of WebControls
What the heck do I mean by that? Well, let me start by stating that while this article is not a course on custom Web Control development, it's important to mention a few points about this technology. Each of the Web Controls that Microsoft and other parties provide are, at their root, classes. This means, of course, that they are programmable by any object-oriented techniques and coding style you may be accustomed to, and maybe some that you are not. Programming custom Web Controls in ASP.NET allow you to use object-oriented programming and various design patterns in a tier where you weren't really able to do so before, at least not extensively.
Classic ASP did not have what developers now refer to as WebControls. Many developers, however, used to use COM components written in VB6 to receive information via method arguments and return HTML to render in the ASP page.
Most people seem to think of custom Web Controls only in terms of component building and reusable tools that you can easily distribute to anyone for use in any Web application. While this is true, they are much more than that. My apologies to those of you who think I am stating the obvious, but believe me, I wouldn't be writing about this if I had not seen it, or seen the lack of it, to be more exact. Custom Web Controls do not have to be written with the whole world in mind, they can serve a single project (or a single corporation) if need be. This can serve three purposes: first of all, it can allow you to isolate visual components of your application and encapsulate them into controls. Right away, this eliminates code-clutter at the WebForm level, but it also encourages the second purpose, reusability. Depending on the functionality you give a Web Control (and not all of it has to be programmed in right away - some may come as-needed), you can reuse it in other places within your application even if its appearance is radically different. I'll give you some examples later. The third purpose it serves is the ability to "object-orient" your Web development. As I said before, controls are classes. They can extend or be extended by other controls, they can implement interfaces, and they can participate in whatever design patterns you deem appropriate for your task.
Microsoft has indicated that using the FormView control in Visual Studio 2005 lets you create an entire data-entry/edit form with a Web Control. Declaring properties on that control will make the FormView appear and even behave differently. You can create your own custom Web Controls that contain other controls used to build a form, or a custom grid, or any combination of anything you need. This is called a composite Web Control and is simply a control that contains a hierarchy of other controls, thus encapsulating their functionality and exposing only what is desired. When designing and developing Web applications in ASP.NET, this Web Control, or "declarative" approach to my design has served me very well and has been really well-received by those that support my apps after I am gone (the life of a consultant).
At immediate glance, developing Web applications made up primarily of custom Web Controls may seem like more work than before, but think about this. How many times have you had to build multiple nested tables, each containing multiple cells, each containing specific controls such as labels, textboxes, or buttons? A "Web Control-approach" to development lets you break your WebForm into its components, allowing you to manage the visual aspects of a complex form much easier. The level of breakdown is, of course, entirely up to you but I'm going to demonstrate techniques I have used in the past. Though at first it may appear that these techniques add complexity, I think that after you get the hang of it, they actually reduce the complexity.
This example is going to take multiple steps so bear with me. I am going to illustrate how I have used custom Web Controls to separate my Web application into manageable parts, even though not all may be subjects for reusability. Say that I want to build a site that requires a data-entry form with a few fields on it: Name, Address, City, State, Phone, and E-mail. I could build these fields right on the WebForm, or maybe I could create a UserControl that I could later drop onto the WebForm. Right away you can see that I would have to create 12 visual objects 6 labels and 6 textboxes. Some of these may be required fields so those would probably have a red asterisk to the left of the label. Say Name and E-mail were required; this would add two more labels to the form. In order to get things to line up properly I would put these controls in a table. I'd also add two more controls that are also pretty common to this scenario a heading and a submit button, which would bring my total control count to 16. No big deal; you've done this.
Let's take the first step towards making this a bit more declarative by introducing a Web Control approach. When I look at a form like this, the most common element I see is the group of controls that make up a field in the data-entry form. I am talking about the field label, the textbox, and the asterisk that indicates a required field. By creating a custom Web Control that encapsulates these three objects, I can clean up a great deal of the object clutter on the WebForm. A beneficial side-effect of creating this control is that you can reuse it just about everywhere in this site and in just about any other site you create in the future. Since this article is not a tutorial on Web Control creation, I will skip to the part where I have created this control already (indeed I have) and tell you what this "FormField" control, as I will hereafter refer to it, does. My FormField control displays a field caption and a field textbox. It allows the optional display of a required indicator based on a property setting and even allows the text and style for this indicator label to be customized. In most cases, I can see this being a simple asterisk but you may want to make it a string of some kind. The control offers separate style properties for the label and the textbox to allow for maximum visual versatility. In fact, you can even turn off the label by setting a property, and you can position the asterisk above the textbox as well as to the left of it.
By giving the FormField control all this functionality, any Webforms can use the control as they see fit by simply setting some properties. I've programmed the code that provides all this "declaratively" at the Web Control level. Now let me restate a definition from above: the FormField control defines how to do all sorts of things, and the WebForm decides what needs to be done. Let me point out one other cool feature I have added to this FormField control. A ReadOnly property on my custom Web Control not only sets the built-in ReadOnly property on the internal textbox, but it also overrides the style on the textbox with one from an additional property I provided called ViewModeStyle. This lets the Webforms that use my control set the field to a read-only state that can, at the same time, change the way the field looks, thus visually indicating its change of mode.
I said earlier that this would be the first step towards making this form conform more to the style of declarative programming by taking advantage of Web Controls. Indeed I have taken this first step and this control may prove quite useful in many other forms as well, but now I'm going to take things a little further. When I designed the site I am pulling this example from, I had already developed the custom FormField Web Control so using it was a no-brainer. However, I anticipated a couple of more facts about my application. I knew it would have several data-entry forms throughout the application that would behave and look relatively the same. Some items with similar behavior and appearance include headings, a form submission button, and the necessity to display the entire form in an edit mode or a view-only mode. I first created a custom Web Control that contained a heading for the data-entry form, a placeholder control to designate where to house the actual data-entry objects, and at the bottom of the control I placed a Submit button. Without getting into too many details, I also added several styling properties including one for the heading, the button, a field caption style, a field textbox style, and a viewmode field textbox style. This class served as my base class for several other custom Web Controls that corresponded to each of my data-entry/edit forms. In the case of the form that started this example, I created another Web Control that inherited from the base class I just told you about and then added all the FormField controls that specifically made up my Name and Address data-entry form.
Allow me to explain a couple of technical details about this control: When you create a composite Web Control, you add its child controls to a Controls collection that's part of the Web Control class you are [eventually] inheriting from. This is the case in the base class I created above. But in the derived classes that actually contain the FormField controls, I added these controls not to the Controls collection of the custom Web Control but to the Controls collection of the PlaceHolder control I created in the base class. Remember that by inheriting from this base class you adopt all of its visual functionality including a PlaceHolder; then later you will fill that PlaceHolder in the derived controls (Figure 4). This technique allows a certain level of visual inheritance at the Web UI level. Other functionality I added to the form base class includes a ViewMode property that determines if the data-entry form was to be displayed in edit mode or view mode. Setting this property will change the ReadOnly properties of all my FormField controls accordingly. Remember previously when I described the FormField control, I mentioned that I designed it so that when the ReadOnly property is set to True, a different style was applied to the contained textbox. Since I included this functionality in this Web Control already, setting that property from the "form" control(s) changes the style on all the FormField controls contained. I also want to mention sizing. One great advantage of dealing with objects in terms of separate Web Controls is that you size internal, or contained controls to the parent only; the parent being our custom Web Control. You typically size a contained control to 100% of the parent. What this means is that in the case of the FormField control, the textbox is sized to 100% of the parent minus the width of the label and the required indicator, if it is visible. This means that as you drag to resize the FormField control, the textbox will always resize accordingly. When many FormField controls are contained in your "form" Web Control, they are sized to 100% of their container, which may be an HTML table or the custom Web Control itself, or in case of the examples in this article, it is the PlaceHolder control that is contained in the base control. Figure 4 illustrates what the base form control and a derived form control would look like. Notice that the isolation of parts is very clear. The derived form control(s) need only worry about their specific controls and how they fit into their immediate container.
The final effect of all this is that you can drop a single control on a WebForm and you'll get the entire data-entry form, heading, and submit button included. You can resize this form as a single control and all contained controls will resize accordingly. This in itself is a big relief from having to size separate controls individually. By setting a simple ViewMode property, you will see the entire data-entry form change style (Figure 5) and the submit button disappear. Since my site required more data-entry/data-view forms, I created them as custom Web Controls that derived from my base class. I provided the base class and the form-specific control classes with many other properties to give it more versatility, most of which are outside the scope of this article, but I will mention that I found that sometimes I needed to reuse one of the data-entry forms in a couple of places with the difference of a couple of its fields being absent. In this case I simply added the ability to hide these fields and exposed it as a property of that control. I took care of the problem "declaratively" and the other WebForm that reused the data-entry control simply set a property to make the control appear differently.
It's important to mention that these "data entry" Web Controls were not the only thing residing on the WebForm(s), so you can image the code-clutter that I eliminated by taking this route. As far as business functionality was concerned, each of my data-entry Web Controls mapped to a business object which the control exposed as a property. The submit button that was created in the base control raised an event to the WebForm so in conjunction with the exposed business object, the appropriate database interaction can be performed. Full validation functionality may also be encapsulated within the control by implementing the IValidator interface and providing the appropriate validation code.
I used a similar technique when I needed to create custom grids. As in the case of the data-entry forms, I found that several of the grids in my application served as the entry point into the data-entry forms. This meant the grids were accompanied by other visual elements common to all of them, including a heading, an Add-New link, and a No-Items-to-List message. They also shared certain in-row links including Select, Edit, View, etc. I created these common elements as a custom Web Control similar to the data-entry form example above. Instead of a placeholder though, I actually included a DataGrid in my custom base Web Control. I added a variety of styling properties and other properties to display the Add-New link and position it in different places relative to the grid. I had about five custom grids to design and I wrote each of them as a custom Web Control that inherited from the base control. Each derived control created the grid columns it needed and provided the Databind method and it raised an event every time the grid needed rebinding to its data source. Such an event was raised in place of the sorting event and paging event the DataGrid gives you out-of-the-box. This meant I trapped the internal grid's events in my custom Web Control and just exposed my own custom event to the outside, telling the page that a rebind was necessary. In fact, I found a couple of places where I needed to reuse a couple of the grids, just not in their entirety. So I programmed the building of the columns to be dependent on property settings. This allowed the WebForms that used the custom grid controls to simply turn columns off and on by toggling properties. This, combined with the ability to hide the heading and Add-New link and all the styling I provided, allowed me to reuse these controls throughout the site and make them look completely different from one-another. For example, a home page may have a summary listing of people, while a personnel-editing page may have a grid of people with more columns on it. You can use the same Web Control in both cases, but using its custom properties, you would simply hide most of the columns on the summary version on the home page. You can bind the same business object to both controls which makes using them very simple.
Gluing Controls Together
Depending on your needs, you can have custom Web Controls in your Web application communicate with each other using events. Thanks to the way events work in .NET, you can actually declare events in one control, then declare public methods that adhere to the event signature in another control. The WebForm that contains both Web Controls can "wire" the event in one control to the method in another, thus effectively gluing the controls together so that behavior in one fires functionality in another with no other code interaction at the form level. The possibilities are endless and are limited only by your creativity.
Pattern All You Want
As you can see, I've illustrated a couple of real-world examples where I've used object-oriented techniques to achieve my UI needs. I used simple examples and showed some containment and one level of inheritance, but you can apply OOP and design patterns to the classes that make up your library of WebControls in whatever fashion you see fit.
Let me give you one quick example of where your Web Control inheritance tree can grow to more than just two levels. Say you have about five data-entry forms in your Web application similar to the one I described above. As in the above example, all the data-entry form Web Controls inherit from a common base control that provides common functionality and visual elements. What if two of these forms also shared some additional visual element and/or functionality that the other three do not? You can place these elements into another Web Control which, like the data-entry controls, inherits from the original base Web Control, but itself acts as a base Web Control for these two data-entry form controls. This allows you to build a hierarchy of visual and functional elements in a class structure where each control provides functionality to all derived controls down the line (Figure 6). If you're creating a site that creates Web Controls dynamically, you can even have factories set up to instantiate your controls or even use interfaces to call functionality from your Web Controls. I know I'm speaking pretty abstractly here, but I'm just trying to convey that any design pattern you see fit to apply to your design is possible, even in the UI, since your programs use all-too-familiar classes.
I chose to use the word toolkit for lack of a better term. Using a declarative approach, you can design a site to house most of its functionality in the Web Controls that comprise it, including all interaction with a business tier (or database if you choose to). This lets you use the custom Web Controls in any site that needs a little bit of functionality. This appears to be the case with the ASP.NET forums site located at www.asp.net. If you download the source for this project, you'll see that the designers created the site by gluing a bunch of Web Controls together. Though I can't say for sure, it's my understanding that the new Community Server forums (www.communityserver.org) is developed this way as well. The idea here is that if you're writing a site and you want to include a certain forum posting on one of your pages, you can just use one of the custom Web Controls, set some properties, and you're done. If your Web Controls offer sufficient styling properties, you can visually integrate it into the look and feel of your site with no problems at all.
Even More with Avalon
Ever hear of XAML? Well, I won't make this section an introduction to XAML, but I will tell you that it brings declarative programming even more to the forefront in Avalon (coming with Windows Longhorn). XAML is an XML-like language that lets you declare visual objects using tags and properties. You'll be able to use one code base to drive both Windows and Web applications. For example, you can use a <Textbox> tag to display a Web textbox in a browser or a Windows textbox on a WinForm. By now you should understand that the actual code that draws the appropriate object has not disappeared, it has just been taking out of our realm of responsibility. Concepts like this make me think there's some very exciting stuff coming down the pipeline.
Declarative programming using Web Controls definitely has its advantages in code isolation, reusability, and providing versatile functionality. While I believe this practice and approach to ASP.NET design creates more robust Web applications, I think you should use it as one of the tools in your arsenal as a developer; just like every tool and technique you may have acquired through the years. In every project, you need to weigh the functionality your users desire against the available time and resources; and if you're a consultant, you also have to consider the skills of the team who will take over support of your project after you're long gone. I know that the styles I have demonstrated here are supportable in the long run. I have also been fortunate to work with people that have been eager to learn and explore new and even unorthodox techniques. This may not always be the case and you may find that anything more than top-down programming is beyond the reach of some people. In any case, use judgment when you apply these or any techniques to your development. Most sites I have seen that are written in ASP.NET use a conventional page centric (non-Web Control) approach to design and development, and are written very well. My friend Scott is very quick to remind me that design and coding is a very personal art and I believe he could not be more correct. There are many right ways of achieving a goal and every style and technique you learn along the way contributes to increasing your handy, dandy, roving, programming bag of tricks.