Tuesday, 31 March 2009

ASP.NET MVC - First Impressions

Another item on my Tech ToDo is MVC Frameworks. I have been meaning to get in to MVC frameworks for ASP.NET pretty much since I first heard of them so it has been great to finally get a chance to sit down and have a tinker.

What is MVC?

MVC stands for Model View Controllerit’s a software design pattern that aims to separate the concerns of:

The Presentation of the Data (The View)

PlaneBannerHappyFace How the data needs to be viewed should not impact any other code. Code should take the data and then build its own representation based purely on that. For example, if we had an awesome Philly steak and cheese sandwich, we could present it in a number of ways - we could have a photo, we could have a video of someone chowing down on it, or we could just put how it makes us feel on plane banner.

What changes about the actual sandwich? Nothing. Presentation changes should not require changes in the data.

The Data Itself (The Model)

PhillySteakNCheeseThe model is basically the heart of the data. This is where we represent our problem in code. It includes all of the validation, storage and general guts of the application. Think of the model as the steak and cheese in an awesome sandwich. If you were to take it away from the awesome sandwich, it would just become two mundane slices of bread. Without the bread, the steak and cheese is nothing, without the steak and cheese the bread is nothing. Without the model, the code serves no purpose. The model is an awesome sandwich with awesome filling :)

The One Who Makes It Happen (The Controller)

familyguy-burgerking So we have established that we have an awesome sandwich and several ways to present it. But how do we actually get to the point where we have a view of an actual sandwich?

Enter the controller. Think of the controller as the guy/girl you say “one awesome Philly steak and cheese sub please”, give them your cash. They then run off, take what you have said and make it happen. Without the controller, no sandwich gets made and you never get to see it.

Why Use an MVC Framework?

There are several reasons for using an MVC framework over traditional ASP.NET WebForms development:

  • They promote separation of concernsEach element of the MVC triad should not rely on the implementation of another. While there is a well-designed interface between the appropriate elements, how the interface is actually implemented should have no effect.
  • They increase testability.  Ask any WebForms developer if they test the code-behind for their pages. I guarantee most of them will say “no”. The WebForms model is not test-friendly at all (due to the crippling HttpContext class). Taking ALL of the model away from the view and placing in its own place enables you to poke and prod it to your hearts content.
  • Ability to create user-friendly, cleaner URL’s.  MVC frameworks have complete support for URL rewriting which means you can create URL’s like “myweb.com/profiles/rob” rather than “myweb.com/profile.aspx?id=1383067829”.
  • Anything else you feel should be here? Comment and let me know!

Requirements to Get Going

I am currently running Windows Vista Home Premium which comes with IIS7 (which is WAYYY better than IIS6!), but that is not required, you will need however:

That’s about it :) I do highly recommend the VWD Express Edition, it’s really rich (especially for a free editor) and TBH, there is not a great deal you cannot do in the Express version over the Pro version.

I then started working my way through the MVC Contact Manager sample application (click here and scroll to the bottom – MS please add anchors to headers! Even if you do not link to them!).

My First Thoughts

It’s NOT WebForms!

“Well Duh”

Sure, but I have been doing WebForms development for a couple of years now, so I have gotten pretty used to the pain points of it.. While I have tried to control bad habits (e.g. putting too much business stuff in the page code-behind) – it’s easy to be naughty right? MVC totally turns it all on it’s head, come in to it with an open mind and do not expect to be able to quickly port WebForms code.

Don’t Be Afraid of the Code-In-The-Markup Thing

When I started creating my Views, I got nervous about the amount of code I was placing in the ASPX. In the WebForms & VS2005 world, it was easy to do this and then get errors popping up at runtime. Based on that, I liked to avoid it where possible. You will find yourself putting a lot more code in the ASPX since, well, where else can it go? There is no code-behind :P This said though, Visual Studio 2008 is a hell of a lot smarter than 2005 and I found it picks up most boo-boo’s at compile time.

There’s Helpers Everywhere!

One thing that surprised me with MVC is the amount of static helper classes and extensions methods there are. TBH they are probably needed (especially due to the above point) but this is all stuff adding to the learning curve. Be prepared to learn a whole load of new names!

Get Used to Convention over Configuration

While I admit I have not had a chance to dig deeper into how the MVC elements are all glued together by the runtime, it is immediately obviously after creating your first triad that there is some “convention” being assumed under the hood. For example, here is a typical method in a controller:

   1: public ActionResult Edit(int id)
   2: {
   3:     // Get the Contact with the given ID.
   4:     var contact = 
   5:         (from c in _entities.ContactSet
   6:            where c.ID == id
   7:            select c).FirstOrDefault();
   8:     return View(contact);
   9: }

See the return View(contact) statement? Notice I am not actually telling it what view to return? That’s because MVC automatically runs off and searches the Views\{Controller}\{Action} folder. This is all due to the notion of “convention over configuration”. Rather than expect developers to chunk out lots of code to say where to go, establish a standard and go there instead.

Validation Logic in the Controller

Again, since I am still real fresh to ASP.NET MVC, I am not sure if there is another/better way to do this. During the tutorial it gets you to add some validation logic to the “Edit” action for a contact. Here is the code:

   1: [AcceptVerbs(HttpVerbs.Post)]
   2: public ActionResult Create([Bind(Exclude = "Id")] Contact contactToCreate)
   3: {
   4:     // Validate the Data Passed.
   5:     if (contactToCreate.FirstName.Trim().Length == 0)
   6:         ModelState.AddModelError("FirstName", "First name is required.");
   7:     if (contactToCreate.LastName.Trim().Length == 0)
   8:         ModelState.AddModelError("LastName", "Last name is required.");
   9:  /* snip... */

As you can see, where are performing some validation against the data passed in by the user and then reporting any errors to the ModelState. The ModelState is then available to the view to work with (in a real de-coupled manner, it’s really a dictionary). There are also helper methods in the view like Html.ValidationSummary to display errors reported in the ModelState using a HTML unordered list. Now, I know this is all really useful, but I am not sure how I feel about having the validation of the Model in the Controller.. I would expect the validity of the Model to be verified by the model itself, or surely you are creating some duplication of effort? Would love to hear others thoughts on this? (I am totally willing to accept it is just me being a pain in the ass and I should just accept and love the usefulness of it all!)

In Summation

After a few evenings of tinkering with ASP.NET I can’t help but feel like I am only just looking at the surface, let alone touching it. It looks to be a very powerful and already rich platform (compared to WebForms) which is impressive since it is still very much in it’s infancy.

While it will take some work making my brain work more web-like (i.e. without a PostBack/Event Model) I can feel already it is a much cleaner, smarter way to work. Above all, I am enjoying it. The pattern makes so much sense, allowing me to focus on the task at hand (e.g. coding the model is all about the model).

I’ve yet to really start working with it (e.g. sites from scratch, unaided and test-first) but I don’t think it will be long before I am doing that! Then I look forward to posting hopefully more useful and hands-on posts!

What are your thoughts?

5 comments:

  1. Hi Rob. I think we're in the same place in our skills development on this topic.
    You might want to have a look a the the NerdsDinner chapter which is a free pdf document of chapter one the upcoming ASP.NET MVC 1.0 book by wrox.
    It takes you through an entire application written using MVC including unit tests. Best of luck with it.

    Martin

    ReplyDelete
  2. Another great read Rob.

    I think the validation logic is in the Controller to keep things simple for the tutorial. It allows you to very easily see how things hook in.

    The best practice would be to have the validation in the Model. Like trying to the code behind lean in webforms, it is important to have skinny controllers.

    ReplyDelete
  3. Nice piece Rob. I'd also recommend the Nerd's Dinner walkthrough (must get around to it myself!). And you're right about validation which would typically take place in the model. You need to maintain some sort of error state in your model which the controller can use to populate the ModelState. Mike

    ReplyDelete
  4. @Martin Evans
    Thanks for the comment and heads up on the NerdsDinner excerpt (I actually already have it, just not sat down to read through it). I have heard good things about it. I've also gone ahead and ordered the book from Amazon.

    @Andrew Rimmer
    Thanks for the feedback, as you know it is my intention to make this blog more useful than "noisy". Hopefully people will read what they see here, and if they learn just one thing, I will be happy! I'm glad we agree on the idea that controllers should really just be a conduit of input (as opposed to doing much with it). I look forward to running down the rabbit hole with this one :)

    @Mike Ormond
    Thanks to you also for making me feel better about my thoughts on validation taking place in the Controller! If you know of any good samples where ModelState is populated based on error state information provided by the model please let me know. I would be keen to see if there are any "best practices" around this. E.g. something like myModel.UpdateModelState(ModelState) (Where ModelState is a reference to the ModelState the Controller has).

    ReplyDelete
  5. S'funny, I seem to have come full-circle with MVC frameworks.

    In 2002 I was working on a JSP project using the Apache Struts framework, and I hated it, couldn't get my head round things at all.

    I was really chuffed when 2003 rolled round, and I moved over to ASP.NET webforms which was initially much easier to get to grips with.

    But after six years of webforms, I'm finding it to be a leaky abstraction, and somewhat of a hinderance to the OOPy, domain-driven approach that I now prefer taking with my solutions.

    So, I'm glad there's a Microsoft MVC framework now available for me to embrace.. even if it does mean I have to re-learn a lot of the basics of state management, HTML, etc.

    ReplyDelete