First time here? You are looking at the most recent posts. You may also want to check out older archives or the tag cloud. Please leave a comment, ask a question and consider subscribing to the latest posts via RSS. Thank you for visiting! (hide this)

Last week I held two presentations about ASP.NET MVC for the new-born DotNetRomaCeStà user group in Rome. And one of them was about what I consider to be ASP.NET MVC Best Practices. The presentation was in Italian so I decided to translate my slide in English so that everybody can read them.

Controller’s best practices

1 – Delete the AccountController

You will never use it and it’s a super-bad practice to keep demo code in your applications.

2 – Isolate Controllers from the outside World

Dependencies on the HttpContext, on data access classes, configuration, logging, clock, etc… make the application difficult (if not impossible) to test, to evolve and modify.

3 – Use an IoC Container

To make it easy to adhere to Best Practice #2, use an IoC Container to manage all that external dependencies. I use Ninject v2, but there are many around, and it’s easy to build your own if needed.

4 – Say NO to “magic strings”

Never use ViewData[“key”], but always create a ViewModel per each View, and use strongly-typed views ViewPage<ViewModel>.

Magic strings are evil because they will never tell you whether your view is failing due to a misspelling error, while using a strongly-typed model you will get a compile-time error when there is a problem. And as bonus you get Intellisense.

5 – Build your own “personal conventions”

Use ASP.NET MVC as a base for your (or your company’s) reference architecture. Enforce your own conventions having controllers and maybe views inherit from your own base classes rather then the default ones.

6 – Pay attention to the Verbs

Even without going REST (just RESTful) use the best Http Verb for each action. Adopt the PRG Pattern (Post-Redirect-Get): show data with GET, modify data with POST.

Model’s Best Practices

7 – DomainModel != ViewModel

The DomainModel represents the domain, while the ViewModel is designed around the needs of the View, and these two worlds might be (and usually are) different. Furthermore the DomainModel is data plus behaviours, is hierarchical and is made of complex types, while the ViewModel is just a DTO, flat, and made of strings. To remove the tedious and error-prone object-mapping code, you can use AutoMapper. For a nice overview of the various options I recommend you read: ASP.NET MVC View Model Patterns.

8 – Use ActionFilters for “shared” data

This is my solution for the componentization story of ASP.NET MVC, and might need a future post of its own. You don’t want your controllers to retrieve data that is shared among different views. My approach is to use the Action Filters to retrieve the data that needs to be shared across many views, and use partial view to display them.

View’s Best Practices

9 – Do NEVER user code-behind

NEVER

10 – Write HTML each time you can

I have the option that web developers have to be comfortable writing HTML (and CSS and JavaScript). So they should never use the HtmlHelpers whose only reason of living is hiding the HTML away (like Html.Submit or Html.Button). Again, this is something that might become a future post.

11 - If there is an if, write an HtmlHelper

Views must be dumb (and Controllers skinny and Models fat). If you find yourself writing an “if”, then consider writing an HtmlHelper to hide the conditional statement.

12 – Choose your view engine carefully

The default view engine is the WebFormViewEngine, but IMHO it’s NOT the best one. I prefer to use the Spark ViewEngine, since it seems to me like it’s more suited for an MVC view. What I like about it is that the HTML “dominates the flow and that code should fit seamlessly” and the foreach loops and if statements are defined with “HTML attributes”.

Download the slides and demo

Both the slides and the demo code are available for download. Or watch it here:

Which other Best Practices would you suggest?

The 12 above are what I consider basic practices that everyone building ASP.NET MVC applications should adopt. Do you think there are other must-have practices for developers building ASP.NET MVC applications? Please say it in the comment section below.

One last note: in May Sebastien Lambla had a talk about his ASP.NET MVC Best Practices for the VistaSquad user group in London. His talk was very inspiring and stuck into my mind, and it inspired both my ASP.NET MVC projects and my talk as well. So I want to give credit to Sebastien’s talk for having inspired me, and that talk. If you are interested you can download his slides from the Developers Developers Developers event in Scotland.

posted on Tuesday, October 27, 2009 11:38 PM

Comments on this entry:

# re: 12 ASP.NET MVC Best Practices

Left by Liam at 10/28/2009 3:02 AM

I'm not sure that Best Practice #1 is enough justification in itself. Why would I never use AccountController? If I do use the existing AccountController am I breaking best practices? It seems to function just fine for a simple login and registration page.

Otherwise, great list of recommendations which can be easily followed!

# re: 12 ASP.NET MVC Best Practices

Left by Hadi Hariri at 10/28/2009 7:31 AM

@Liam,

Among other things, the Account Controller breaks SRP. It is not well structured. It's tightly bound to ASP.NET Memembership.

@Simone,

Although I like Spark, I think the lack of working Intellisense is a shortcoming. I also feel people really put down the WebForm viewengine when it's not actually that bad. But yes I would switch to Spark once support is better. I had major issues with it in MVC 2.

# re: 12 ASP.NET MVC Best Practices

Left by Michel at 10/28/2009 10:55 AM

I suppose you wanted to write : "but IMHO it’s NOT the best one".
But I am very interested to read your post on HtmlHelpers. I just started in MVC and it's hard to see what it brings better (or worse) than "real" HTML.

# re: 12 ASP.NET MVC Best Practices

Left by Andrew at 10/28/2009 11:19 AM

In point 12 you have 'The default view engine is the WebFormViewEngine, but IMHO it’s the best one', whereas in your slideshow (slide 45) point 2 is 'Not the best available' - I am assuming you mean to state a preference for the Spark View Engine but one of your comments also leaves that a bit unclear.

# re: 12 ASP.NET MVC Best Practices

Left by Jag Reehal at 10/28/2009 11:47 AM

Hi Simone,

Great job.

Following on from point 11, I did a blog post on how to keep logic out of your views which shows how you can refactor if's in your views.

www.arrangeactassert.com/asp-net-mvc-view-best-...

Cheers,

Jag

# re: 12 ASP.NET MVC Best Practices

Left by Simone at 10/28/2009 12:28 PM

Good catch Michel and Andrew: it was a "NOT the best one".
Edited the post, thank you

# re: 12 ASP.NET MVC Best Practices

Left by Grizzo at 10/28/2009 3:20 PM

Can you use #8 (ActionFilters for "shared data") without violating #4 (Say no to magic strings)?

If so, can you point to a URL that gives and example?

# re: 12 ASP.NET MVC Best Practices

Left by Chris Vann at 10/28/2009 4:04 PM

Regarding the Spark View Engine comment, I have yet to use it, but it's top on my priority list. The problem with using the Web Form engine is that it makes it too easy to carry over ASP.NET Web Forms practices without even realizing it. Views containing any runat="server" tags are the debil.

# re: 12 ASP.NET MVC Best Practices

Left by David Kemp at 10/28/2009 5:00 PM

Should #10 read:

I have the opinion that...

rather than

I gave the option that...

?

# re: 12 ASP.NET MVC Best Practices

Left by Nate at 10/28/2009 6:41 PM

On #11 :
I've seen this type of comment more lately and it just doesn't make sense to me. There is display logic and there is business logic. It is OK for display logic to go in a View. The presentation layer is where display logic is supposed to go. Also, by abstracting away conditionals into HtmlHelper methods you are not removing them. That logic is still in the presentation layer, but you have added possibly unnecessary complexity.

An alternative to creating HtmlHelper methods just to remove if statements would be to conditionally fill your ViewModel with the correct value needed by the View.

Thanks for the other 11 points though.

# re: 12 ASP.NET MVC Best Practices

Left by Terry at 10/28/2009 9:28 PM

AccountController - do you have a temlpate controller or a link for reference that we could see for what you envision as a proper separation?

# re: 12 ASP.NET MVC Best Practices

Left by Liam at 10/29/2009 1:58 AM

@Hadi,

Sure. Point taken that it isn't well constructed, but it works for the purpose for which it was built. However the statement 'You will never use it.. and bad practice to keep demo code..' taken by itself doesn't justify removing it.

# re: 12 ASP.NET MVC Best Practices

Left by WebDevVote.com at 10/29/2009 10:41 AM

You are voted!
Track back from WebDevVote.com

# No parameterless constructor defined for this object.

Left by Francois Botha at 10/29/2009 2:46 PM

Thanks for a great article. I'm just diving into ASP.NET MVC now, and this is a great resource for me to get things right from the start.

I do however have a problem with the sample code, specifically #2. I get this exception "No parameterless constructor defined for this object." when browsing to /Post/ . For #3 and the rest it works fine.

I'm a total MVC newbie, so excuse my ignorance.

# re: 12 ASP.NET MVC Best Practices

Left by Simone at 10/29/2009 11:43 PM

@Hadi: If you install Spark VS Integration you'll have Intellisense

# re: 12 ASP.NET MVC Best Practices

Left by Simone at 10/30/2009 12:05 AM

Thank you everybody for your comments on my 12 best practices.
First of all, this was just a slightly annotated version of the slides. But they are still slides and were supposed to be explained by someone talking. So, they cannot be exhaustive.

@Liam, @Terry, @Hadi
#1 - AccountController:
I agree, just saying "You will never use it and it’s a super-bad practice to keep demo code in your applications" is not enough. The reasons why I said to remove it is that this controller breaks the SRP principles (does registration, editing, and manages the login). Then it's too coupled with the MS Membership Provider. Membership provider makes sense in web forms, where it is integrated with many web controls (menu, navigation, login view, etc) but in ASP.NET MVC it would only be needed to use the default Account Controller. And I think that it's easier to implement my own Authorization Filter rather then implementing my own membership provider

@Michel, @Grizzo
#8 - Composite views
I know, mine is a very opinionated "opinion" :)
And I'll try and elaborate it more in post to come. But basically you have 2 options not to use magic strings and do a composite view:
1 - use a hierarchical view model: if you are showing the same data in different pages then you probably might want to put the properties that contain that data in a base class. And have your action filter populate these properties.
2 - go on using the "magic strings", but abstract them away from both the designer of the view and the developer of the action filter.. build your own conventions and you'll be happier

@Nate, @Jag
#11 - HtmlHelpers
Jag has a very interesting post about this problem.
It's OK to have logic as long as it's not so much to transform the view in an unreadable mix of C#, HTML and JS (the so-called tag soup).
Generally I prefer to resolve most of my conditional statements in views, and put the result as additional Boolean properties in my ViewModel. And using Spark, I have no problem adding plain boolean conditions in HTML.
This might become a new followup post as well :)

# re: 12 ASP.NET MVC Best Practices

Left by Hadi Hariri at 10/30/2009 7:22 AM

@Simone,

In theory yes, in practice the intellisense actually doesn't work too well and falls short in many areas.

# re: 12 ASP.NET MVC Best Practices

Left by Carol at 12/3/2009 8:53 PM

"Views must be dumb (and Controllers skinny and Models fat). If you find yourself writing an “if”, then consider writing an HtmlHelper to hide the conditional statement."..

I have found the need for quite a number of IF statements in my Controllers. Aren't HtmlHelpers more to dumb down the View, rather than the Controller? How can I make my Controllers skinnier? Should I move more logic to my Models?

# re: 12 ASP.NET MVC Best Practices

Left by Simone at 12/21/2009 1:49 PM

@Carol:
you are right, HtmlHelpers are to "dumb down" Views, not Controllers.
Another approach is to move part of the logic to the Model as well.
For example, rather than have something like this
<% if (model.ShipDate>DateTime.Now) { %>

<% { else if (model.ShipDate

<% } %>

you might have a status property that does the check for you and returns directly the src image or, even better, sets a class on the row and then you put a background image via CSS.

# Thanks

Left by Vampal at 1/19/2010 4:32 AM

Great job

# re: 12 ASP.NET MVC Best Practices

Left by Ron at 1/20/2010 4:47 AM

I'm having problems passing values from the controller to the view. I created a boolean variable to use as a flag and want the view to render some html based on whether its true or false. Unfortunately ViewData doesn't pass boolean values.

Any ideas? I should be able to pass any datatype to a view. Its easy in other MVC frameworks.

Ideas?

thanks!

Comments have been closed on this topic.