Microsoft plans to release the new Model-View-Controller (MVC) for ASP.NET developers in the first half of this year. The MVC represents a new ASP.NET paradigm that many developers should be very excited about. To see why, we need to start with a bit of a background on the current state of ASP.NET and Web development in general.
Web Development as We Know It
In my mind, there are two types of Web development: internal intranet development and external Web development. Each development type has a very different target, audience, and set of characteristics. Having worked in both camps, I find that one thing in common among all successful sites is that they constantly need tuning, tweaking, augmentation, and modification. Sites that heavily intertwine presentation, logic, behavior, and data make it very hard for multiple people to work on them in tandem (e.g., designers and developers). These sites add an increased measure of complexity that can lead to brittle "franken-webs," which end up being nightmares to maintain or extend. Therefore, while it may be tempting for Web developers to assume that one of these flavors of Web development (typically the one they work on) requires a higher caliber of developer "chops" to ensure success, the truth is that the best Web developers aren't found on one side of the fence or the other. Instead, the best Web developers work in both camps and are distinguished by the fact that they're constantly seeking to decrease coupling between presentation, behavior, and data in order to ensure better maintainability and flexibility of their solutions.
ASP.NET as We Know It
Developers know that ASP.NET is mostly targeted towards intranet enterprise development. Oh sure, there are untold numbers of Web sites out there running ASP.NET, and oodles of them can cite ASP.NET as a contributor to their success. But ASP.NET's primary focus has been on creating applications over the Web, not necessarily sites. Evidence of this can be seen in the fact that ASP.NET "pages" aren't pages at all, they're forms in which you drag and drop controls, and wire up repeaters and data grids to display information. But, invariably, the controls you interact with in ASP.NET are for editing and modifying data so that developers can quickly and easily create applications that work over HTTP.
At least, that's how ASP.NET operates on the surface. Deeper down, there are amazing resources that serve Web and application sites equally well, such as HTTPModules, HTTPHandlers, the ASP.NET Cache, along with a host of other useful and well-thought-out goodies – things that I rely upon constantly as a Web developer. But sometimes ASP.NET can be a pain when it comes to building Web sites. Especially when you need pixel-level control over layout and design, or when you are striving for standards compliance across a wide variety of browsers. More importantly though, it can be a pain when you're trying to achieve decreased coupling in your Web sites in order to make them more robust and manageable. And ironically, that difficulty can be traced to two of ASP.NET's biggest strengths: its reliance upon Controls, and its heavy leaning on object-oriented programming (OOP).
The Problem with Controls
For those of us that survived the classic ASP days, ASP.NET's controls are fantastic – and my treatment of them here is not intended to condemn or reject them, merely to point out that they do cause some problems when it comes to coupling. Specifically when it comes to needing fine-grain control of your markup, some ASP.NET controls are a bit quirky in terms of the markup they render. Some Controls inject extra carriage returns, and most inject inline CSS styling based upon some of the settings that you've specified in the designer. Even worse, some of the more complex controls, like the Calendar and earlier versions of the DataGrid, inject inline styles that can't be removed with the designer. Compensating for these issues can be problematic when you're targeting browsers created without attention to standards or that have buggy implementations. But, more importantly, ASP.NET controls typically rely heavily on inline styles, which adds additional coupling, making ASP.NET developers responsible for managing presentation details for some design elements when they're managed by ASP.NET controls.
In like manner, ASP.NET's use of naming containers bungles the IDs of your controls and emitted markup and provides oodles of problems for Web developers. You can see these problems in environments where web developers want to decouple markup from presentation and behavior. In other words, because ASP.NET needs to insure the uniqueness of your control IDs (in order to seamlessly handle state serialization and dehydration on the back end), it renames your controls on the client side, or in the final emitted markup. So, for example, if you have an ASP.NET Panel control designed to hold links with an DIV of navLinks on your page, that DIV typically gets rendered with an ID of something like ctl00_cpySide_navLinks if it's in a Master Page, or in some other parent control. ASP.NET is able to handle that seamlessly on the back-end, so most people don't see this as a problem – at least from a development standpoint. But it does add a high amount of coupling if you want to style your pages completely with external CSS. Yeah, you could just append CssClass attributes to your ASP.NET markup in order to create CSS styling handles in your HTML markup, but that engenders that worst-practice approach lovingly (and mockingly) referred to as "class-it is" in CSS circles, and still requires additional coupling and effort on the part of both ASP.NET developers and presentation coders and designers. The same thing goes for trying to add behaviors to your HTML markup through unobtrusive coding practices. The garbled IDs output by ASP.NET make it much harder to add uncoupled behaviors. Yes, you could figure out some way to keep track of containers to programmatically reproduce those funky ID names, or you could even just bind to them directly in your external behavior files. But if an ASP.NET developer changes control hierarchies or arrangements, then your behaviors are busted – which is a perfect example of poor coupling (where components need to know how accompanying components operate instead of just interacting though a simple interface, such as a navLinks ID shared in the markup).
Control Adapters represent an ingenious approach to solving some of these problems, by giving developers complete control over the emitted markup. But while there are a lot of how-to's and introductory tutorial articles that cover the benefits of Control Adapters, be prepared to quickly find yourself very alone and in very uncharted waters if you decide to use them – especially if you need your modified controls to continue to work with the ASP.NET webforms paradigm. Simple controls that only output data are ideal candidates for Control Adapters, but if you also need your controls to provide the ability to post data back to the server, good luck wiring that up.
The Problem with OOP
Again, for those of us who survived classic ASP with VBScript, it seems almost blasphemous that I could mention that there would be any problem with the OOP approach utilized by ASP.NET. And, for the most part, I'd practically brand myself a heretic for even bringing this up. Other than for a nagging feeling I get any time I play around with the DataBinding Syntax provided by ASP.NET for C# and VB.NET. Take the following example, of an ASP.NET Repeater control, bound to some sort of collection of user objects:
<asp:Repeater ID="myRepeater" runat="server"> <ItemTemplate><p><strong>Name: </strong> <%# DataBinder.Eval(Container.DataItem, "UserName") %></p></ItemTemplate> </asp:Repeater>
The DataBinder.Eval(Container.DataItem, "userName") syntax sure looks OOP, and it is (sort of). But it's also highly based on convention. (Go ahead, wire up a similar example on your own, and then go into the code-behind for the page in question, type "myRepeater." and look in IntelliSense for a DataBinder object belonging to the Repeater; then check the Page object – you won't find a ‘DataBinder' member.) Personally, I've always disliked this syntax though I was never able to pinpoint why (other than its verbosity) until I saw some examples of ASP.NET's ‘dynamic languages. For example, that same sample above would be rendered thusly in IronPython:
<asp:Repeater ID="myPythonRepeater" runat="server"> <ItemTemplate><p><strong>Name: </strong> <%# UserName %></p></ItemTemplate> </asp:Repeater>
That's quite a bit cleaner and easier, right? As Scott Hanselman likes to put it, that's just the effect of "syntactical sugar" thrown into the mix to enable developers to type less. Under the covers, data-binding is still going on and you'll obviously need to wire up a data source. But this is a much easier way to handle data-binding, even if it doesn't look pure from an OOP standpoint.
It's also an approach that has ENORMOUS appeal to someone like me who spends a lot of time working on Web sites where I really just want to quickly pound out a page with super-clean control over my markup, and don't necessarily need a full bevy of ASP.NET Controls. And that's where the ASP.NET MVC comes in.
Enter the MVC
To my mind, the ASP.NET MVC was designed specifically for demanding developers like me .We want to have our cake and eat it too. In other words, I want access to all the intrinsic power that I've grown to love in ASP.NET (Request, Response, Server, Cache, and things like FormsAuth, WebServices, Master Pages, as well as HttpModules and HttpHandlers to name just a few). But I also NEED full control over my markup in order to address some of my own business needs, as well as to help ensure decreased coupling in my own solutions and applications or sites. Even more importantly, I need a quick and easy way to ensure that my carefully crafted markup can EASILY interact with my application logic when I post my pages back to the server. And that's exactly where the ASP.NET MVC shines – because it's specifically designed to separate data, logic, and presentation. As such, it provides full control over markup, provides absurdly simple and powerful data binding (that can be done in classic templating style, or through the use of data-binding controls), and makes it so easy to map POST data back into my application (from my markup) that my logic can be very cleanly decoupled from presentation and behavior on the client-side. Better yet, this same degree of decoupling can be leveraged equally well to support Test Drive Development (TDD) with little effort.
Now, if it sounds like I'm excited about the ASP.NET MVC, let me tell you: I am. But that's because it meets some huge needs that I've felt have gone unmet for quite a while with ASP.NET. Needs that wouldn't have caused me to abandon ASP.NET, but that have caused a large number of problems. Most of the sites I work on require pixel perfect styling and lots of decoupled styling and behavior.
I've been using the ASP.NET MVC on one of my own sites over the past week or so, and while it does come with a bit of a learning curve, I'm already seeing ways in which having this functionality earlier (remember, it doesn't replace ANYTHING you know or love about ASP.NET, it's just a NEW way of leveraging ASP.NET) would have saved me tons of time and effort.
In subsequent articles I'll look at providing a better overview of the ASP.NET MVC, and lay out some concrete examples of how it works, where you can get additional insights about working with it, and how to start sizing it up for your own needs. Until then, feel free to share your own perceptions about coupling best practices, current ASP.NET limitations, or your own experiences and thoughts about the ASP.NET MVC in the WindowsDevPro forums.