Leveraging Existing ASP.NET Features in ASP.NET MVC

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.

figure8_1 
Figure 8.1 - The TextBox renders correctly

Listing 8.2 - The resulting HTML for the TextBox is less than desirable

figure8_2

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.

figure8_3

Figure 8.3 - The menu control renders, unfortunately the links require post-backs. More surgery is needed to make it function.

figure8_4

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!

figure8_5

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 Examplehttp://jquery.bassistance.de/treeview/demo/

jQuery Menu Example

http://jdsharp.us/jQuery/plugins/jdMenu/
jQuery Tabs Example

http://stilbuero.de/jquery/tabs/

 

______________________________

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.

#1 Helen avatar
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?


#2 Ben Scheirman avatar
Ben Scheirman
10.21.2008
8:15 AM

@Helen:you can get simple data binding with the built-in HtmlHelpers... this combined with the new ModelState you can start getting validation as well.I don't like server control models because they abstract HTML away from me (arguably, so do the helpers, albeit not as much).Just think of the Label server control in WebForms.It has a plethora of properties (as do others) regarding to style.It's generally a bad practice to embed style information directly in your HTML, so that leads you down the wrong path.In addition, you can't set the "style" property of the span tag (or label) without code.There's too much wool over your eyes.I'm not sure declarative controls have their place in ASP.NET MVC.


#3 Helen avatar
Helen
10.21.2008
4:32 PM

I agree with you that the controls that come with ASP.NET (and many third party ones) emit horrible markup but does that means there's no value in controls at all? You don't have to use the style objects or the viewstate or any of the features that take the power of generating the HTML away from you. You can just use them to wrap up rendering logic that you might want to reuse in other places. I guess that's exactly what you can do with a helper method. It's just a difference in syntax. Microsoft's must have had a reason to go with helper methods rather than controls. I just wish I knew what it was. Maybe it's because they wanted to distance MVC from all the overhead of controls like viewstate and runat="server" forms? Maybe it's because the helper methods are easier to unit test? Anyway, good luck with your book. Thanks for sharing a chapter of it. :)


#4 Justice~!~ avatar
Justice~!~
10.22.2008
12:07 AM

Now you've done it.I will have to make a post ABOUT THIS POSTand you know what that means!!!!YOUKNOWWHATTHATMEANS


#5 Helen avatar
Helen
10.22.2008
3:03 AM

Is there nowhere I can post about my server control sympathies without you finding out?? You're like some caped MVC protector of internet. :)


#6 Ben Scheirman avatar
Ben Scheirman
10.22.2008
8:02 AM

I will, of course, troll ANY post where server controls are held in a good light.;)Kidding aside, I'd like to hear a good argument for server controls, I just don't think they'll provide value.To me they're too opaque...the same leaky abstraction that is rank in WebForms today.


#7 Peter Seale avatar
Peter Seale
10.22.2008
1:33 PM

I'm curious about Helen's question too--I saw a similar discussion earlier somewhere about cleaning up the Login/Logout functionality that comes with the MVC template. The consensus there was to use a helper method to clean it up.But that was sort of a unique scenario; the login/logout bits were in the master page, so it's hard to argue about reuse when you use something only in the masterpage.Let's take a more real example--the Ignored/Interesting tags section on Stack Overflow. You can find your Ignored/Interesting tags in two places on the site: 1. right column on the home page, 2. on the "Preferences" tab of your profile page.In this real-world scenario, wouldn't it make sense to use a, hmm, what are those called--subcontroller?--partial view?--usercontrol? Wouldn't it make sense to use one of the above to encapsulate "Ignored/Interesting tags?"


#8 Ben Scheirman avatar
Ben Scheirman
10.22.2008
2:04 PM

@Peter - we aren't talking about not using user controls.They definitely have their place, and I'd use them often to encapsulate and clean up my views.We're talking about the difference between these:<input type="text" name="Message" /><%= Html.TextBox("Message") %><asp:TextBox id="Message" />Each has their benefits and drawbacks.I'm arguing that I don't like the abstraction away from HTML that the asp server controls employ.The helper methods also abstract it, although in a different way.I still have direct access to HTML attributes of the element without resorting to code in a code-behind.


#9 Payman avatar
Payman
12.07.2008
8:59 AM

hay,

i am a developer from IRAN,do you think that if it is possible for me to find a job there ? :D

Regards,


#10 Michael Knopf avatar
Michael Knopf
12.08.2008
9:46 AM

Ben, I've been working in Web Forms for 6+ years and am just getting deeper into ASP.NET MVC now, from what I've seen so far (includes what you have written here) basically nothing from my Web Forms experience will port to MVC and this is in fact starting over again. I'm not against this at all as software programming is an ever changing landscape and I have worked on applications that exceeded the bounds of web forms (because of high data, high transaction environments) to the point where we literally were ready to throw it all away (fortunately we started the porting of it to MVC). Overall though my thoughts as of this point in time is that we are starting over entirely as we move from Web Forms to MVC, just as we started over entirely when we moved from classic ASP to Web Forms.


#11 benscheirman avatar
benscheirman
12.08.2008
11:03 AM

@Michael,

I hear you, trust me. I have gobs of knowledge about GridView, ASP.NET server controls, page lifecycle, and it still comes back to bite me in my webforms projects. I feel that a lot of this knowledge is wasteful. With ASP.NET MVC, there is this new paradigm, yes, but it's built on top of the stuff we already know.

That said, ASP.NET MVC is a choice, and your experience with WebForms can still be put to use on WebForms projects. However, I find that ASP.NET MVC is a breath of fresh air in comparison.


#12 Michael Knopf avatar
Michael Knopf
12.09.2008
12:39 PM

Ben

I completely agree with you that MVC is in fact a breath of fresh air, I have felt the enormous pain that web forms gives you when your application reaches the limit. I have already made the commitment to move entirely to MVC (well in projects that I'm allowed to because I work for NASA and they are a little slow when it comes to allowing the latest stuff to be used on their projects, especially when they are still in BETA).

Keep up the good work, it's much appreciated.


#13 MrAnonymous avatar
MrAnonymous
1.04.2009
3:51 AM

Try to replace ReportViewer control with jQuery...

Asp.net MVC seems to me unmature. As some project managers already states - they just need get things done not another technology which excites but gives just a headache. Developers are lazy, clients are exigent and that leads to need of already ready solutions.

No need to remind me, that MVC is not a WebForms replacement and that they can co-exist. Actually, i like it. I just think it`s rarely good option for enterprise software development.


#14 benscheirman avatar
benscheirman
1.04.2009
8:23 AM

MrAnonymous - Surprisingly there are some really good charting options using just javascript, however if you want the full power of Reporting & ReportViewer, then you can easily just mix a WebForms page within your ASP.NET MVC application.

On my current project (which could be called 'enterprisey') I find many areas where ASP.NET MVC would clean it up immensely.

You're right in saying that ASP.NET MVC is a bit immature, indeed it is still in beta. But the areas where it is lacking it is far more extensible than WebForms. If you find something you don't like about WebForms, well... tough.


#15 Neil McCrossin avatar
Neil McCrossin
2.12.2009
8:49 PM

Hi Ben,

You have talked about Server Controls not working under ASP.NET MVC, but this is not what I have found in my testing. I have explained the details at forums.asp.net/.../1379275.aspx but I have not been able to get a response that actually answers the question. If you can explain further that would be great.


#16 benscheirman avatar
benscheirman
2.13.2009
11:39 AM

Hi Neil,

Thanks for your comments. Perhaps some wording does need to be changed, as like you said something do "work" for varying definitions of "work."

Firstly, to bypass the server side form tag requirement, you have to create your own base page class to override this method.

2nd, for controls that do postback, such as gridview, it does require a server-side form tag, which will add _doPostback and __viewstate to your page. You absolutely cannot have more than 1 server side form tag, so this hinders you off the bat.

Also, when handling RowEditing or PageIndexChanging events, you have to result to either custom gridview subclass or add server-side script tags to your page.

This is a gigantic about-face in the way that the MVC framework is designed to be used. Logic does not belong in the view. In fact, code other than simple helpers is completely discouraged, which is why there is no code-behind for ViewPage.

I appreciate your comments though, and I can adjust the wording for the book to better clarify what "works" and what doesn't. I'd also recommend that if you have some areas of your site that you're just not ready to give up on the webforms way of doing it, then you're free to do that in the same project. Just create an ASPX file outside of the views folder and you're free to do it with server controls, postback-model, and page lifecycle.


#17 Marco avatar
Marco
2.19.2009
12:31 PM

Thank you benscheirman!

I needed the control panel of a MVC website to be with standard ASP.NET so I could make use of Gridview and other advanced controls.

I spent quite a bit of time researching this only to find out it was a very simple solution: "you're free to do that in the same project. Just create an ASPX file outside of the views folder and you're free to do it with server controls, postback-model, and page lifecycle.". I believe this feature should be more advertised.

As far as I'm concerned this possibility gave MVC the last point to be my favourite framework. It's more powerful and clean, and when needed can use the normal page lifecycle.. perfect!

Now a question: how would you implement the fact that a folder shouldn't be processed by MVC and should contain only normal web forms?

My first implementation is the following:

public ActionResult Index()

{

Server.Transfer("~/Account/Index.aspx");

return new EmptyResult();

}

(this for each page in the folder in a controller dedicated to it).

In my first test it seems to work, but is there a better way?

Thanks!


#18 benscheirman avatar
benscheirman
2.19.2009
12:35 PM

@Marco,

You can just create a folder (outside the views folder) in your project and exclude it from routing...

routes.IgnoreRoute("WebForms/{*pathInfo}");

Then place all of your files in there and navigate to them directly.


#19 Marco avatar
Marco
2.19.2009
12:50 PM

Off-topic side note: I used the word "framework" because Microsoft define it this way: "ASP.NET MVC Framework". But I don't like the word framework used for this. The framework used is ".NET framework", and MVC is an architectural pattern or design pattern. Therefore it could have been shortened to "pattern". But I have no idea if it's just me or if anyone else would agree :)


#20 Marco avatar
Marco
2.19.2009
12:52 PM

Thanks!


#21 Neil McCrossin avatar
Neil McCrossin
3.03.2009
5:59 PM

Ben,

Thanks for your reply to my question from a few weeks ago - I am much clearer now on what the situation is. Sorry that it has taken me a while to say thanks.