ASP.NET MVC: Why your dislikes may be wrong

Wow, so I keep talking about how I want to write more, particularly now that I'm an "insider" working in Redmond, and yet it has been a month since my last post. But hey, I've been here two months and I just finally spent some time in downtown Seattle for the first time last weekend, so get off my case. :)

Anyway, as is typical in the professional world of software development, I've seen a great deal of debate about whether or not ASP.NET MVC is the second coming or a step backward. There are also peripheral discussions about what Microsoft sees as the future, but given the outright declaration of that guy with the red shirt and the fact that we've got new versions of Webforms and MVC on the way this year, I think it's pretty clear that you use whatever the best tool for the job is. Isn't it funny how that comes up with every religious debate about development tools?

In any case, there are a few themes to the online chatter around MVC that don't give it proper credit. I'm not suggesting that these are stupid people, but rather people who don't have the whole picture for one reason or another. This isn't an exhaustive list I'm sure, but it is noise that may prevent you from investigating the framework further, or inspire you to spread misinformation. There's a positive theme that builds up here, as you'll see.

ASP.NET MVC is too primitive.

Generally I think this statement is made in the context of MVC's lack of server controls. Some people don't like generating markup, particularly those who've enjoyed the drag-and-drop RAD nature of ASP.NET. Let's face it, when we first saw demos of ASP.NET v1 prior to its release, it looked a lot like VB6, solving problems around the stateless nature of HTTP and letting us build stuff quickly. Behold the editable DataGrid, right?

The thing is, I would observe that as time went on, people weren't using these features out in the wild, particularly with big, sprawling, public facing apps. (I'd like to see the DataTable class stricken from the .NET Framework.) Personally, I almost always used Repeater controls, or variations on them I wrote myself, so I'd have more control over how the markup was rendered. And I almost never used in-place editing either, partly because I wasn't building Excel on the Web, and partly because getting your head around the event model was sometimes a pain.

So MVC goes minimal on the UI end of things by rendering simple HTML via the HtmlHelpers, and there's a remarkably simple state bag to hold on to your goodies when your server side validation says something isn't right. That you can simply wire up objects to those helpers without all of the "MyTextBox.Text = myObject.Foo" and the reverse nonsense in event handlers is a huge time saver. Give it a try!

MVC is a step backward to ASP.OLD and spaghetti code.

This is a pretty huge perception problem. I have to admit though, the first time I saw it demo'd, I thought the same thing. I remember the horror of ASP and trying to debug it, and this looked the same. That was because I didn't truly appreciate what Model-View-Controller really meant. After reading through a Ruby On Rails tutorial and reading various articles about the MVC pattern, something clicked in my head and I investigated further. Then I drank the Kool-Aid® at various Mix conferences and I was hooked.

But back to the Italian food, the biggest thing that colors your perception is that there are a lot of really bad examples of what a view should look like. That doesn't mean that it's conceptually broken. Remember that the MVC pattern facilitates the famous separation of concerns, meaning a view should not participate in any logic except perhaps some very basic display logic (most often, looping through some enumerable set of data). If you see some example on the Internets of a view that is calculating salaries, or worse, hitting a database, politely post on that site: "MVC: ur doin it wroung."

It's a lot of work deciding how to split everything up.

Again, I think that's only true if you aren't doing it right. Admittedly, it takes some practice to decide where things go, but after awhile it becomes pretty obvious. If you're dealing with a view, ask yourself if it's doing anything more than displaying stuff. If you're dealing with a controller, ask yourself if it's doing anything more than coordinating what to show the user, and shuttling data between the views and the models. If you're dealing with models (which is a pretty nebulous umbrella term in a lot of texts), ask yourself if it's doing any decision making about what to display or how to display it.

Don't be intimidated over the many related subjects around this concern soup. Dependency injection isn't that hard to get down, and like anything it takes practice to fully grasp why you'd want to soak up its awesomeness (see: Loose coupling).

In fact, the "ah ha" moments really may not come until you've forced yourself to sit down and do an end-to-end science project. While I understand that test driven development is a huge leap that's hard to make, unit testing can make your life easier even if it's slightly after the fact. In order to unit test, you have to figure out how to decouple your bits. That subject is too enormous here to cover, so you'll have to take it on faith until you try it.

Ugh, but it takes so long to do everything "right."

Think about how much time you may spend debugging a code-behind or a custom server control. If we share any experience, it's probably around those hours we'll never get back. Now imagine that you have some tight model that just does what it does, probably interacting with a database (or rather an interface that in production happens to be a database). Imagine you have a controller that takes the request, feeds its data to the model, then sends the model's data to a view to be rendered. Each phase of that can be looked at in total isolation. The points of failure are much easier to narrow down. And because it can be looked at in isolation, each part can also be tested in isolation. The speed at which you can debug this arrangement is far greater than what you do in Webforms.

The bottom line is that MVC is just... different. I happen to be a strong advocate of it because it gets back to the basics of what HTTP truly is, without a huge mess of abstraction on top of it to hide the way it works. That's important these days, because we trust the browser to do more work than ever now. The framework also gets us thinking about (but doesn't force us) how to do things in a way that is testable, more maintainable, and ultimately, more simple.

If you don't think you like MVC, but haven't really looked into it, go check out the learning page on ASP.NET/mvc. Read the tutorials, view the video (that Hanselman guy is a trip).

29 Comments

  • I looked at a few examples and read up on it just a little and didn't think it looked like much until now - I have bought the Pro Asp.net MVC framework book and now I am hooked on MVC - I think as developers we just sometimes choose the option that works and for something new to come out it takes some of us a while to really tie into (like Dynamic Data) - I really like it but havent used it in a project. (its just different as you say)

  • That's a pretty solid book, too. Highly recommended.

  • Granted I have been out of the game for a while when it comes to coding, but where I left off and the problem I am going to face next when I jump back into coding in a few weeks is dependency injection.

    You say it is easy, but the problems I have seen in doing DI properly, is horrible examples where massive leaps of faith are taken in the readers knowledge.

    When learning new things sometimes things should be explained so a 5th grader can understand it.

    The biggest problem I see is people showing chunks of code and saying "this is our DI setup". Then moving on and a lot of people don't know what that code does or how it works.

    I point out DI specifically, but it is a problem accross the board I see in most examples of MVC. You might even say to some degree that only the most advanced developers are developing with MVC so the explanations of core things are for other advanced users because to get to the "cool" stuff they can't be bother with the "basics".

    A more specific example of my problem is with nHibernate and DI. I am told that part of setting up nhibernate has some resource costs so DI can help solve that problem. However, no one shows how to do it. That is my specific problem.

    But another problem a friend is running into is he has spaghetti code in his views and is trying to move to more strongly typed views, but can't find good how-to's on doing it because some many jumps in assumptions of knowledge are made. I would say we are about intermediate level developers closer to the beginer side than advanced side so some of these things are within our grasp they just aren't explained well enough. Its not like we just learned a for loop and are trying to use polymorphism properly.

    I explained it to my boss once. While the information is out there and right in my face my skill level is missing one puzzle piece from me grasping it, but no one out there has that puzzle piece.

    I think that might be where some of the overall problem in understanding what MVC is. You have people that are high and mighty seeing bad examples and vice versa you have people that don't know what is going on who can't find good examples.

  • That's a lot of good feedback. I agree that the approach to teaching these concepts hasn't been great, and I theorize that some of the problem is rooted in folks not having a strong enough base in object oriented programming. I admit that I often assume that OOP design patterns are common knowledge.

    DI is intended to simply keep different pieces separate, so they can be tested. In the classic controller and data repository examples, this means controllers should only know the interface for a repository. In production, the controller uses a real SQL-hitting implementation, in testing, it uses a mocked or stubbed out implementation.

    Forget all of the frameworks for a minute and think of it this way... A repository interface (call it IUserRepo), which includes a method called GetUser(). In MVC, without any change to the plumbing, a controller is created using its default constructor. Let's say the constructor loads a concrete implementation of IUserRepo, and some action method uses that object to call GetUser().

    Now let's say there's a different constructor, that takes an IUserRepo as a parameter. In your unit tests, you'd create the object that way, passing in a fake IUserRepo that you stubbed out to return specific data, or using a mocking framework (I like Moq). You can now test the controller's action method without worrying about what the dependency on the repo is.

    The DI frameworks change the controller factory for MVC, and generally what they do is expect that controllers do not have a default constructor, and match the parameters with whatever the configured concrete version of the interfaces are. In our example, it would know to create the controller and pass in that SQL-hitting IUserRepo. Does that make sense?

    You don't *need* to use the DI framework, if you don't mind writing two constructors for the controller. The question becomes, are you really testing the same thing if you create controller objects in two different ways (the controller factory in MVC calling the default, and you calling the overload with parameters). I think that's mostly an academic debate.

  • Thank you, that is a well written blog.

    I am still on the fence because right now I enjoy the speed of being able to drop a ListView on a page, connect it to a Linq data Source control and open the Wizard and...

    click->click->click

    and I have a ton of code written. Then I wire up a few events (like overriding the selecting event on the Linq Data Source control to perform a complex query not the simplistic one I used to create the UI).

    Basically, I love my controls and my Wizards :) I'm kinda waiting for MVC to either:

    A) Provide a bunch of controls
    B) Have a bunch of Wizards in Visual Studio to create code for me

    It seems MSFT is leaning toward B. For example the Wizard that comes up when you want to make a new View. Ok, put in the view and give me the option to also insert a pageable, editable Grid.

    I can be converted, but not yet.

  • While I certainly don't speak for anyone around ASP.NET, I can assure you that there's no leaning toward one or the other. ASP.NET 4, as you can see by the various blog posts around new features, is still evolving, still getting better.

    My issue with the drag-and-drop stuff is that I find it hard to customize, and in testing it doesn't seem like it scales well. That said, I suppose it's perfectly adequate line-of-business apps. The biggest thing though is that it doesn't adequately split stuff up into truly loosely coupled pieces, and that makes it hard to test.

  • Nope - I still dislike it.

    Why do some advocates of MVC, with its separation of Model and View concerns, propose the "ViewModel" concept - the _merging_ of Model and View concerns?

    Why do so many examples and demos have a Model containing a list of SelectListItems so that the View can render a drop down list? No separation there.

    Where's my RegisterClientScriptBlock function so that my controls don't keep dumping references to the same script file in the html?

    It's beyond the precious little space in my brain to get a page editing an entity, containing a list of child entities, and have this conform to MVC. I'm shoehorning - not streamlining.

    The tutorial pages are a joke. Show me a model binder demo there. Where's my _integrated_ Visual Studio help?

    Tag soup! That is So 1998.

    Reflection every *&%^@!!where.

    And so much more....

    [/Rant]

  • So because some people like to use a "view-model" (which is little more than a messaging container), the whole thing is broken? You don't need to implement that yourself.

    There absolutely is separation in the drop-down scenario you suggest. It's still possible to test the controller fully.

    Why are you using controls that reference scripts?

    Entity editing: ur doin it wroung!

    Just because you're frustrated with it doesn't make it Bad Stuff.

  • Jeff - thanks for taking the time to reply to an obvious rant.

    My frustration stems, to a large degree, by comments such as those you just made (in the nicest possible way). I've researched so many blogs and references, and I just haven't seen the light. I already know I'm doing it wrong because no-one would be pushing a pattern that's making me work so hard to achieve so little.

    Scripts - I've got partial views referencing jqGrids, so I need to reference the jqGrid and jquery ui js files. If I render a partial view twice, I get two references to the script file. Short of placing all .js file references in the master page (ugh), I don't see how to avoid this, or why it's a bad idea.

    I still don't _get_ why a Model should/could populate objects for the convenience of HTML helpers. What does a SelectListItem mean in the context of my business domain? Nothing at all. It's an html thing. Doesn't that road lead me into the temptation of handing over an instance of a databound asp:DropDownList? So it's testable - good - but it doesn't comply with the black and white description of M/V/C - where are the boundaries?

    Entity editing - Help! What's the answer? I want to edit an entity which contains a list of child entities, and do it with the best UX I can build. I can't see any examples or demos of doing this the MVC way, nor any discussion of why I shouldn't or can't do it. A classic Order/Order Item example would suffice.

    I feel like I'm the dumbass at the back of the class wondering how the smart kids got the answers.

    Thanks
    Dermot.

  • I'm sure you're not a dumbass, and there's obviously some disconnect between what's out there and what you're absorbing. Knowing that is important for the community and I'm sure anyone with an interest in the platform.

    On script references... don't be too worried about referencing them once in your master. Most of the time they're going to be cached from one page to the next anyway. Get 'em loaded and forget about them!

    A model isn't populating anything... it's just a vessel for data. I mean, when we talk about separation of concerns, we're talking about one concern worried about rendering, and another coordinating the business with what view to serve. The separation can't be pushed to the point where a view doesn't even know about data, right?

    Your controller action, based on a request, is handing off the details of the request (parameters, cookies, query strings, whatever) to some business logic, and in return taking the results of that logic and passing them to the view. That's it. If that's some kind of enumerable collection formatted as a select list, so be it. The SelectList class, despite the name, is just a fancy collection with some extra properties, and has zero knowledge about HTML. As such, you can test the results of your controller action when it returns one of these in the model.

    As for the child entities bits, I think you can take one of two approaches. The first is that your view makes AJAX calls as you go to save a "row" of data. The second approach is to do it the full post way using the dot hierarchy of field names. A controller can in fact interpret that correctly out of the form/value collection. The yellow and black "Pro ASP.NET MVC" book (or whatever the title is) has a pretty solid example of that.

    The danger in learning MVC I think is trying to apply the grandest use cases from every day life to it right away. It's the whole crawl/walk thing. The first thing I built with it was a simple blog, and that helped enormously. Now that I'm doing bigger things, it's much easier after having the more simple foundation. Good mentors help too.

  • Thanks again Jeff

    I'll take one last tilt at the select list issue, and move on, hopefully tripping over a mentor along the way :)

    Your article states "you're dealing with models /snip/, ask yourself if it's doing any decision making about what to display or how to display it." So, I know the View needs to display a means of selecting a widget from a list of widgets, and that there's a currently selected widget. Today the View shows a combobox built from a list of SelectListItem. Tomorrow, the View is changing to a jqGrid because we want to show more widget properties. That means I have to change my Model because my View has changed.

    None of my data or data access has changed. By converting my widget list to a selectlistitem list, the model has made the decision of "how to display it".

    And I claim that is not separation of concerns.

    Regards,
    Dermot.

  • I think you're really splitting hairs here. The data in a SelectList is not bound to a drop down. I mean, yes, that's typically where you use it, but it's just a container implementing IEnumerable. We custom roll containers like this all of the time to package up data for consumption by a view. For example, a photo gallery may contain a reference to an album, a collection of its photos, the number of pages it has, the current page index, etc. You're still just building an object graph that is testable against the controller, and that the view can pick and choose from in terms of data. In either case, the controller has no knowledge about how the data will be displayed any more than the view has any knowledge about how the object graph was created.

  • Dermot,

    Forgive me if I'm missing something, but you just said:

    "Today the View shows a combobox built from a list of SelectListItem. Tomorrow, the View is changing to a jqGrid because we want to show more widget properties. That means I have to change my Model because my View has changed."

    I think NO - this change should only be in the Controller code, you can leave the Model alone. The Controller code can fiddle with 'view models' as required for this example, and you only change the Model if there's a real business change there.

    HTH,

    Best,
    Jim

  • Jim

    So the Controller needs to be aware of the implementation within the View? How does converting Model (say, entity framework) data into View-compatible (say, SelectListItem) data in the controller fit with the "skinny controller" directive?

    This confusion might all go away if ViewModel was called ViewData and everyone admitted it was an implicit requirement of implementing the pattern.

    Are ViewModel classes actually an implicit design requirement of MVC? I'll take a "Yes absolutely" or a "No, and here's why" response.

    Still not _getting_ it...

  • No, the controller doesn't care what the view does. You're over-thinking it. A view has still has to be aware of what data is called in any universe, right? The "separation of concerns" is that the view doesn't choose what data it should receive or how it should be picked. It's solely concerned with displaying it. That's it.

    And no, you don't need to use ViewModel classes. You can just as easily use the collection instead. I personally don't like doing that because the strong typing and removal of "magic strings" makes it a little more compile-time friendly. And it supports Intellicrack. :)

  • Jeff

    You lost me. Is "the collection" the ViewData dictionary?

    Can I stretch your goodwill to ask for an example?

    Imagine a page editing a "Share purchase request". A user creates a request for a "SharePurchase", choosing one stock from a list, a country from a list and a currency from a list, and enters a trade date. The request can be saved and amended later.

    So, SharePurchase declares Stock, Country, Currency and Date.

    What is the "model" object that the typed View uses as ViewPage? Where do you get the saved purchase request and lists from the database? What tasks (and in what M,V or C, or VM) do you undertake to get [option] tags to render for each item in each list?

    This example illustrates the problem of aggregating lookup data needed for the edit operation, beyond the examples of "models" edited solely through text boxes.

    These seem such basic principles to be asking about after many months of trying that I'm embarassed to be doing so, and still sat at the back of the class going "huh?".

  • Yes, the ViewData dictionary, my bad.

    The model's type would likely be some kind of custom bucket, probably. But I stop you when you start asking about the database because it has nothing to do with that view at all.

    If you're simply displaying dropdowns with no care about how they're selected, then having an enumerable Country collection of some kind is fine in that view model. If you need to choose which value is selected, then you'll probably want to use a SelectList class as the Country property. It's totally appropriate for the controller action to wire that up (a SelectList can be set up with the constructor alone).

    Don't confuse the strongly typed view models with how you consume them in the action methods that handle a post. There are actually several different ways to handle that. So an Edit() method (decorated with a [AcceptVerbs(HttpVerbs.Post)] attribute) may take an id from the path, and other parameters can map to form fields. You can use model binders to also bind the request pieces to inputs in your method. You can even do old school FormCollection to read values.

    In all of these cases, the point remains that you can test these methods in the controller with no knowledge of the view, and more importantly, without the HttpContext that is so integral to virtually everything in WebForms.

  • Hi Dermot,

    In my experience so far of ASP.NET MVC, every View takes for the 'ViewPage' bit either (i) a Model object or (ii) a View Model that I've concocted in the Controller to add things like lookup lists (as per your example with countries and currencies). You also have the ViewData collection available - I use it occasionally, for example to supply a variable title for a page.

    I think the word 'Model' may be over-used here and causes confusion, but in practice you get used to defining a number of View Models in your Controller classes. They're usually done with specific View(s) in mind, but as Jeff says they don't need the View to function so you can test each part separately if/when you're doing Unit Testing.

    Jim

  • Interesting thread. Dermot sounds a lot like me when moving from ASP to ASP.NET. It made me crazy. (A control for a literal?!?! This is the web, not a fat client!) I like Jeff's recommendation to start slowly with a small application. Maybe a good book would help: Steve Sanderson's MVC book is excellent but he does use Castle Windsor without much explanation. You might skip the IOC and just use constructor injection - eliminate a black box and learn about IOC later. I like ASP.NET MVC because I very much appreciate decoupled code; it just feels right. I've seen too many winforms, webforms apps that were extremely brittle and difficult, (impossible), to maintain. With MVC I had to ramp up on my javascript, JQuery, CSS, HTML, HTTP, REST too. But I like it. Another great book on Architecture is Esposito and Saltarello's Microsoft .Net: Architecting Applications for the Enterprise.

  • OK - one month on, and I still cannot reconcile the evangelised benefits with the actuality of making it work in a clean, logical and separated set of layers.

    We've got as many 'view model' classes as we have 'model' classes, each wrapping our underlying model object, and reproducing property getters/setters. We're probably "doin' it wrong", but nothing we've found has explained a better way that works for all of our business classes and business problems. I'd be as well building my model objects line by line from asp:textbox controls - it would be the same amount of work and I'd be able to _see_ the movement of values from html to database.

    I'm left with a deflated sense of "Oh what's the use?", and a distinct impression (warning: hugely unfair comment ahead) that ASP.NET MVC is the product of a clique of elite architectural fanbois sitting in a corner office sipping cool-aid. I still want my Visual Studio integrated help file. I want best practice whitepapers and be able to go to the Microsoft web site to get them, rather than hoping Google can find a forum posting or blog post not related to alpha/beta/RC versions. I want the full Microsoft machine behind this platform.

    And I still want to yell "TAG SOUP!!".

    Hiding that hyperlink because you're not authorised to use that function? Either _another_ HtmlHelper method (and corresponding overloads), or inline button .

    Want an inline style in your Html.TextBox? Ah yes, create an anonymous C# type, inline in your html. Good grief, Charlie Brown.

    6 months in, and I dislike MVC.

  • There's nothing wrong with having "view models" or whatever. The key is that you're also participating in model binding and validation on the models. Doing that means none of the wire ups, in either direction, to controls. I can't understand how you don't see the benefit in that. And if you're not unit testing, able to really see each object in isolation, loosely coupled, then yes, you're probably doing it wrong.

    The framework isn't built out of some intellectual snobbery, it's based on a pattern that has been around since long before C#. You can F1 on MVC stuff... where's the problem. www.asp.net/mvc has a ton of information too.

    I think you're fighting it too hard, and missing too much.

  • Like any platform, there will be good implementations and bad. Ultimatley i think it comes down to guidence/direction.

    If everyone was using a MVP pattern in webforms with unit tests, MVC might not have been needed so much (besides for the obvious better control over markup)?

    Given enough time im sure we will see some horrid examples of MVC applications. eg. database or service connections sitting in controllers, untestable spagetti code in the aspx to try and create data driven dashboards etc.

    2 platforms, both with pros and cons.
    Depends on the application or website you are trying to develop.

  • Dermot O'Logical raises something ime curious to hear from those who have used mvp in lob apps...

    In asp.net mvc?
    admin super button .

    in webforms with mvp
    //view
    public IView.AdminButtonVisible{
    get{return btnAdminSuperButton.Visible}
    get{set btnAdminSuperButton.Visible=value}
    }

    //in presenter
    View.AdminButtonVisible=Thread.CurrentPrincipal.IsInRole("admin")

    //unit test
    var presenter = new MyPresenter(MyViewMock)
    //run what ever method
    Assert.AreEqual(false, MyViewMock.AdminButtonVisible)


    With an MVP pattern we can automate tests on if the button property is set correctly.

    Is there a way to acheive something similar with MVC.

    My thinking is if the view is supposed to be "dumb" there should not be any conditional logic in it.

  • MVC has a huge learning curve and MVC can be waste of time unless you working on a large high traffic website. If I am working on a high traffic website that needs to be worked on by multiple developers then I can see using MVC because MVC makes it easier for developers to work on different parts and it would be easier to test. However, for a small traffic website that doesn't require much development, I would use Webforms. Also the DataGrid is one of the greatest server controls ever. I read a few comments where developers miss having it. Well guess what, some of you are so nerdy that you just go for the latest thing without thinking. Now we are going back to the classic asp days when code was difficult to debug and all spaghettied. Also, seems all the MVC change were done as Extension methods. What was the reason behind this? Was it so that previous versions of .NET Framework wouldn't have to be touched ? ? Seems this all started when Rails came out and people wanted the MVC design pattern too in asp.net.

    Seems Microsoft.NET is going through the same process that it did with MFC. MFC started out easy enough but as Microsoft got to 6.0 it became harder and harder to keep up with all the changes.

  • Why is it a waste of time for small sites? My personal blog is an MVC app. The short URL app I build for CoasterBuzz.com is also MVC (and it has two action methods and one controller). What does size have to do with anything?

    Interesting how our perspectives are different. I find the DataGrid to be the worst control ever, and I've never used it in a deployed app.

  • Jeff,
    I did support for Microsoft in the 90's and dreaded learning all the frills the new versions of Visual Studio had. However, I absolutely love it when technology is incorporated into VS that is already industry tested and accepted. MVC is definitely an industry standard and I love the way its been incorporated into the newer versions of the framework.
    Hopefully it will inspire other .Net developers to use robust patterns and act as a communication bridge between the C# and Java worlds.

  • Seriously? If you really think that, you're doing it wrong.

  • MVC is pile of crap. It is like PHP meets .NET which means it has no future. Might as well write everything in JavaScript why not, it will be more efficient.

  • Spoken like someone who hasn't used it.

Comments have been disabled for this content.