Leveraging Existing ASP.NET Features in ASP.NET MVC
Monday, October 20 2008 23 Comments
The following is an excerpt from my upcoming book, ASP.NET MVC in Action...
Many of us have invested heavily in ASP.NET. With ASP.NET MVC now available as an alternative to WebForms, is all that knowledge lost? Do we have to relearn this platform entirely from scratch? You’ll be relieved to know that many of ASP.NET’s platform features work the same way they always have. Some ASP.NET server controls even work. In this chapter we’ll cover what works in ASP.NET MVC and what does not. By the end of the chapter, you should feel comfortable leveraging your existing knowledge of ASP.NET to build robust web sites with ASP.NET MVC.
8.1 ASP.NET Server Controls
As you just discovered, some ASP.NET server controls work with ASP.NET MVC, but which ones? How can we tell if a control will work or not? To put it simply, any control that depends on ViewState or generates post-backs will not work. Some controls will render, but they require a <form runat=”server”> which you might not want to add. Adding a server-side form tag will put hidden fields on the page for ViewState and event validation. The form will also POST to the same action you’re on, which is usually unacceptable.
Note:
The code you’ll read in this section is purely exploratory. Most of it contains hacks and other workarounds that go against the intended design of an MVC web application. The intent of this section is to see how far we can bend the framework without breaking it. Your authors would not recommend using most of these methods in a production application unless absolutely necessary.
8.1.1 The TextBox
The first control we’ll examine is the <asp:TextBox />. It renders as an <input /> HTML element. It requires a <form runat=”server”> tag to function, and will be given a generated ID, again which is what we’re trying to avoid here! Since it is a form field, and the form is required to be runat=”server”, it is crippled in its function. Figure 8.1 shows it in action, while Listing 8.1 shows the resulting HTML.
Figure 8.1 - The TextBox renders correctly
Listing 8.2 - The resulting HTML for the TextBox is less than desirable
We can see here that the rendered HTML contains a lot of things that we didn't ask for. In addition, notice that the form tag has an action attribute that we didn't specify. This will prevent the form from submitting to an action that we request. Since a textbox in ASP.NET MVC is as simple as <%= Html.TextBox(“name”) %>, the TextBox server control offers no functionality - only baggage - for your ASP.NET MVC views.
8.1.2 Other Common Controls
We can see from our simple text box example that most ASP.NET WebForms input controls have little to offer. However, some of the controls have very functional rendered output. An excellent example is the <asp:Menu /> control. It doesn’t require or generate any post-backs and it doesn’t require view state. It simply renders HTML and JavaScript to allow elements to expand and hide on mouse events. Leaving aside that the <asp:Menu /> renders a nasty pile of HTML tables to display properly, it’s purely a client rendered control, and it works just fine in ASP.NET MVC. Luckily we can fix the poor markup with ASP.NET Control Adapters, which also function in ASP.NET MVC. Figure 8.3 demonstrates the menu control.
Figure 8.3 - The menu control renders, unfortunately the links require post-backs. More surgery is needed to make it function.
Figure 8.4 - The horrific markup that is rendered by the Menu control. Stay tuned for a better way.
While the <asp:Menu /> control renders properly, the links in the menu are post-back links, and don't work. We could conjure up some javascript to alter this behavior, however doing so would just add to the mess. Additionally, take a look at the rendered markup in Figure 8.4. Hard-coded styles, deeply nested tables, highly obtrusive javascript make this tiny menu render nothing short of a headache.
Note:
This type of markup is a constant reminder of why we want more control over our HTML! Later, in Chapter 14 (Recipes) we'll see how we can do much better. For now, let's continue on with our exploration of ASP.NET server controls.
Two controls that would be hard to live without would be the <asp:TreeView /> and the <asp:Calendar />. The TreeView works fairly well, however it generates post-backs that do nothing. The visual aspect works just fine, however. The calendar relies heavily on post-back for navigation, so unfortunately it does not function in ASP.NET MVC.
I’ve so far neglected the big-daddy of ASP.NET server controls. That’s right; I’m talking about the GridView. The GridView is an interesting case, because it has so many different forms. At its simplest, the GridView is just an HTML table. It’s great for displaying tabular data. If we don’t require any post-back, then it should work, right? In short it does work, however there are a view gotchas along the way.
8.1.3 The GridView
The first issue you face is there is no declarative way to bind the GridView to data coming from ViewData. For this we can poke into the code-behind class, which up until now has been mostly useless. In standard ASP.NET Form, you can add an OnLoad event handler and set the grid’s DataSource property to the data coming from ViewData. Listing 8.1 shows how you might accomplish this. Another method you could employ is to take the data binding code and put it directly in the view markup, inside <% %> code blocks. Listing 8.2 demonstrates this. Both of these methods send bad vibes up my spine, but the point is that it is possible.
Listing 8.1 - Binding a GridView from the code-behind
public partial class grid : ViewPage<Customer[]>{ protected override void OnLoad(System.EventArgs e) {base.OnLoad(e);grid1.DataSource = ViewData.Model;grid1.DataBind(); }}Listing 8.2 - Binding a GridView from the view itself
<% grid1.DataSource = ViewData.Model; grid1.DataBind();%>
You also have the option of using the DataSource controls such as ObjectDataSource, SqlDataSource, and XmlDataSource. Of course, in doing this you've completely circumvented the MVC pattern and placed all of your data access directly in the view!
Figure 8.5 - The GridView renders properly
Figure 8.5 shows our newly bound GridView in action. Unfortunately, that's all you get, because none of the advanced features of the GridView will work. No sorting, paging, editing, or selecting. Because of this, it is of limited utility, and will probably only aid you during prototyping and demos.
All is not lost, however. In ASP.NET MVC you can achieve the holy grail of an editable data grid, complete with sorting, paging, and editing. You just have to structure it in a different way. You'll see an example of this in Chapter 14 (Recipes).
8.1.4 So Where Do I Get The Good Stuff?
The examples I've shown here might give you a sour taste in your mouth about ASP.NET MVC. Before you scoff at it and decide that you don't want to live without your TreeView and Menu controls, consider this: many thousands of samples online show how you can achieve the same functionality with a little bit of Javascript and CSS. These are freely available solutions that many other platforms leverage. With ASP.NET MVC we can do the same, and with minimal friction in applying it. Often, these solutions are so simple; they make the declarative ASP.NET controls look like a sledgehammer. Here are a few references for platform-agnostic solutions to tree views, menus, and tabs using jQuery.
| jQuery Treeview Example | http://jquery.bassistance.de/treeview/demo/ |
jQuery Menu Example | http://jdsharp.us/jQuery/plugins/jdMenu/ |
| jQuery Tabs Example |
______________________________
For more early sections of ASP.NET MVC in Action, check out the pre-release PDFs available at Manning Press.
My co-authors may also be posting some excerpts, so pay attention to them: Jeffrey Palermo and Jimmy Bogard.


Helen
10.21.2008
5:43 AM
As horrible as some of the rendering is for the built in server controls, what do you think about building your own controls to hold rendering logic? I'm a MVC newbie but I've been experimenting with using helper methods vs using server controls. I think I like the syntax of the server controls better when I'm working in the aspx. I'm still trying to decide if that's because of my web forms background or whether it's actually a good idea. :)I'm also thinking about and how far I'd actually want to use it. I don't want to use a form with a runat="server" tag or viewstate but would I want to use data binding or a simple foreach loop? Do I want to embed javascript using web resources or should I just use the scripts folder? I'd be interested to hear what someone with a bit more experience thinks. Is there any big advantage of using helper methods? Is there something really wrong about using server controls in an MVC project?