Logo

Maarten Balliauw {blog}

ASP.NET, ASP.NET MVC, Azure, PHP, OpenXML, VSTS, ...

About the author

Maarten Balliauw is an MVP ASP.NET and is currently employed as .NET Software Engineer at RealDolmen. His interests are mainly web applications developed in ASP.NET (C#) or PHP.
More about me More about me
Send mail E-mail me


Microsoft Most Valuable Professional - MVP - ASP.NET

Subscribe to my RSS feed Follow me on Twitter! View Maarten Balliauw's profile on LinkedIn RealDolmen - Rock-solid passion for ICT
I'm a speaker at TechDays Belgium and TechDays Finland

Search

Latest Twitter

    Follow me on Twitter...

    Disclaimer

    The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.

    © Copyright Maarten Balliauw 2010

    More ASP.NET MVC Best Practices

    In this post, I’ll share some of the best practices and guidelines which I have come across while developing ASP.NET MVC web applications. I will not cover all best practices that are available, instead add some specific things that have not been mentioned in any blog post out there.

    Existing best practices can be found on Kazi Manzur Rashid’s blog and Simone Chiaretta’s blog:

    After reading the best practices above, read the following best practices.

    kick it on DotNetKicks.com

    Use model binders where possible

    I assume you are familiar with the concept of model binders. If not, here’s a quick model binder 101: instead of having to write action methods like this (or a variant using FormCollection form[“xxxx”]):

    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult Save()
    {
        // ...

        Person newPerson = new Person();
        newPerson.Name = Request["Name"];
        newPerson.Email = Request["Email"];

        // ...
    }

    You can now write action methods like this:

    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult Save(FormCollection form)
    {
        // ...

        Person newPerson = new Person();
        if (this.TryUpdateModel(newPerson, form.ToValueProvider()))
        {
            // ...
        }

        // ...
    }

    Or even cleaner:

    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult Save(Person newPerson)
    {
        // ...
    }

    What’s the point of writing action methods using model binders?

    • Your code is cleaner and less error-prone
    • They are LOTS easier to test (just test and pass in a Person)

    Be careful when using model binders

    I know, I’ve just said you should use model binders. And now, I still say it, except with a disclaimer: use them wisely! The model binders are extremely powerful, but they can cause severe damage…

    Let’s say we have a Person class that has an Id property. Someone posts data to your ASP.NET MVC application and tries to hurt you: that someone also posts an Id form field! Using the following code, you are screwed…

    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult Save(Person newPerson)
    {
        // ...
    }

    Instead, use blacklisting or whitelisting of properties that should be bound where appropriate:

    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult Save([Bind(Prefix=””, Exclude=”Id”)] Person newPerson)
    {
        // ...
    }

    Or whitelisted (safer, but harder to maintain):

    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult Save([Bind(Prefix=””, Include=”Name,Email”)] Person newPerson)
    {
        // ...
    }

    Yes, that can be ugly code. But…

    • Not being careful may cause harm
    • Setting blacklists or whitelists can help you sleep in peace

    Never re-invent the wheel

    Never reinvent the wheel. Want to use an IoC container (like Unity or Spring)? Use the controller factories that are available in MvcContrib. Need validation? Check xVal. Need sitemaps? Check MvcSiteMap.

    Point is: reinventing the wheel will slow you down if you just need basic functionality. On top of that, it will cause you headaches when something is wrong in your own code. Note that creating your own wheel can be the better option when you need something that would otherwise be hard to achieve with existing projects. This is not a hard guideline, you’ll have to find the right balance between custom code and existing projects for every application you’ll build.

    Avoid writing decisions in your view

    Well, the title says it all.. Don’t do this in your view:

    <% if (ViewData.Model.User.IsLoggedIn()) { %>
      <p>...</p>
    <% } else { %>
      <p>...</p>
    <% } %>

    Instead, do this in your controller:

    public ActionResult Index()
    {
        // ...

        if (myModel.User.IsLoggedIn())
        {
            return View("LoggedIn");
        }
        return View("NotLoggedIn");
    }

    Ok, the first example I gave is not that bad if it only contains one paragraph… But if there are many paragraphs and huge snippets of HTML and ASP.NET syntax involved, then use the second approach. Really, it can be a PITA when having to deal with large chunks of data in an if-then-else structure.

    Another option would be to create a HtmlHelper extension method that renders partial view X when condition is true, and partial view Y when condition is false. But still, having this logic in the controller is the best approach.

    Don’t do lazy loading in your ViewData

    I’ve seen this one often, mostly by people using Linq to SQL or Linq to Entities. Sure, you can do lazy loading of a person’s orders:

    <%=Model.Orders.Count()%>

    This Count() method will go to your database if model is something that came out of a Linq to SQL data context… Instead of doing this, retrieve any value you will need on your view within the controller and create a model appropriate for this.

    public ActionResult Index()
    {
        // ...

        var p = ...;

        var myModel = new {
            Person = p,
            OrderCount = p.Orders.Count()
        };
        return View(myModel);
    }

    Note: This one is really for illustration purpose only. Point is not to pass the datacontext-bound IQueryable to your view but instead pass a List or similar.

    And the view for that:

    <%=Model.OrderCount%>

    Motivation for this is:

    • Accessing your data store in a view means you are actually breaking the MVC design pattern.
    • If you don't care about the above: when you are using a Linq to SQL datacontext, for example, and you've already closed that in your controller, your view will error if you try to access your data store.

    Put your controllers on a diet

    Controllers should be really thin: they only accept an incoming request, dispatch an action to a service- or business layer and eventually respond to the incoming request with the result from service- or business layer, nicely wrapped and translated in a simple view model object.

    In short: don’t put business logic in your controller!

    Compile your views

    Yes, you can do that. Compile your views for any release build you are trying to do. This will make sure everything compiles nicely and your users don’t see an “Error 500” when accessing a view. Of course, errors can still happen, but at least, it will not be the view’s fault anymore.

    Here’s how you compile your views:

    1. Open the project file in a text editor. For example, start Notepad and open the project file for your ASP.NET MVC application (that is, MyMvcApplication.csproj).

    2. Find the top-most <PropertyGroup> element and add a new element <MvcBuildViews>:

    <PropertyGroup>

    ...
    <MvcBuildViews>true</MvcBuildViews>

    </PropertyGroup>

    3. Scroll down to the end of the file and uncomment the <Target Name="AfterBuild"> element. Update its contents to match the following:

    <Target Name="AfterBuild" Condition="'$(MvcBuildViews)'=='true'">

    <AspNetCompiler VirtualPath="temp"
    PhysicalPath="$(ProjectDir)\..\$(ProjectName)" />
    </Target>

    4. Save the file and reload the project in Visual Studio.

    Enabling view compilation may add some extra time to the build process. It is recommended not to enable this during development as a lot of compilation is typically involved during the development process.

    More best practices

    There are some more best practices over at LosTechies.com. These are all a bit advanced and may cause performance issues on larger projects. Interesting read but do use them with care.

    kick it on DotNetKicks.com


    Categories: ASP.NET | C# | General | ICT | Internet | Quality code

    Comments

    DotNetShoutout | Reply

    Wednesday, May 06, 2009 2:08 PM

    trackback

    More ASP.NET MVC Best Practices

    Thank you for submitting this cool story - Trackback from DotNetShoutout

    blogger.forgottenskies.com | Reply

    Wednesday, May 06, 2009 2:51 PM

    pingback

    Pingback from blogger.forgottenskies.com

    Maarten Balliauw on ASP.NET MVC Best Practices at { null != Steve }

    geoffrey emery United States | Reply

    Wednesday, May 06, 2009 4:56 PM

    geoffrey emery

    Nice Post!

    John United Kingdom | Reply

    Wednesday, May 06, 2009 10:27 PM

    John

    If you're excluding the Id from the Model, how are you locating the person in the database? In the case of save that works, in the case of Update it doesn't.

    maartenba Belgium | Reply

    Thursday, May 07, 2009 8:53 AM

    maartenba

    True for updates. But you get the idea.

    For example,you don't want people ediitng your UnitsInStock or SalesPrice fields when doing a form post somewhere.

    CarlH Sweden | Reply

    Thursday, May 07, 2009 12:30 AM

    CarlH

    Great post but you didn't motivate "Don’t do lazy loading in your ViewData".

    maartenba Belgium | Reply

    Thursday, May 07, 2009 8:53 AM

    maartenba

    Will add that to the post in a second. Thanks for noticing!

    9eFish | Reply

    Thursday, May 07, 2009 4:05 AM

    trackback

    More ASP.NET MVC Best Practices

    9efish.感谢你的文章 - Trackback from 9eFish

    blog.cwa.me.uk | Reply

    Thursday, May 07, 2009 9:38 AM

    pingback

    Pingback from blog.cwa.me.uk

    Reflective Perspective - Chris Alcock  » The Morning Brew #342

    progg.ru | Reply

    Thursday, May 07, 2009 9:45 AM

    trackback

    More ASP.NET MVC Best Practices

    Thank you for submitting this cool story - Trackback from progg.ru

    bogdanbrinzarea.wordpress.com | Reply

    Thursday, May 07, 2009 1:52 PM

    pingback

    Pingback from bogdanbrinzarea.wordpress.com

    Summary «  Bogdan Brinzarea’s blog

    Melayu Boleh United States | Reply

    Friday, May 08, 2009 11:41 AM

    Melayu Boleh

    Great post but you didn't motivate "Don’t do lazy

    DotNetBurner - ASP.net MVC | Reply

    Friday, May 08, 2009 2:22 PM

    trackback

    More ASP.NET MVC Best Practices

    DotNetBurner - burning hot .net content

    Q.Lee.lulu | Reply

    Friday, May 08, 2009 6:20 PM

    trackback

    ASP.NET MVC的最佳实践与性能优化的文章

    就一些文章链接,就不多废话了。ASP.NETMVCPerformance:里面的PPT认真看一下。(没有找到视频,有找到的麻烦说一声)Howtoimprovetheperformanc...

    gOODiDEA.NET | Reply

    Sunday, May 10, 2009 5:16 AM

    trackback

    Interesting Finds: 2009 05.01 ~ 05.10

    .NET Introduction to MapReduce for .NET Developers Working With the ANTS Profiler to Optimize SharePoint

    GuyIncognito United States | Reply

    Monday, May 11, 2009 5:59 AM

    GuyIncognito

    I just purchased a PDF version of your new book from Packt Publishing.  I think I've probably covered most of the material in the other ASP.NET MVC book I just recently finished reading, but since your blog is such a great source of continuing MVC information, I felt I had to show some support!  

    Thanks and keep up the posts!


    ps.  I also like the glasses.  Smile

    maartenba Belgium | Reply

    Tuesday, May 12, 2009 3:42 PM

    maartenba

    Thanks for the support! Smile

    Eric United States | Reply

    Friday, May 29, 2009 7:20 PM

    Eric

    "Use model binders where possible" you might show using marker interfaces to also control what fields are able to be bound to.

    ScottGu's Blog | Reply

    Sunday, June 07, 2009 9:05 AM

    trackback

    June 7th Links: ASP.NET, AJAX, ASP.NET MVC, Visual Studio

    Here is the latest in my link-listing series .  Also check out my ASP.NET Tips, Tricks and Tutorials

    BusinessRx Reading List | Reply

    Sunday, June 07, 2009 9:19 AM

    trackback

    June 7th Links: ASP.NET, AJAX, ASP.NET MVC, Visual Studio

    Here is the latest in my link-listing series .  Also check out my ASP.NET Tips, Tricks and Tutorials

    kygeek.com | Reply

    Sunday, June 07, 2009 3:20 PM

    pingback

    Pingback from kygeek.com

    Daily Links for Sunday, June 7th, 2009 | LaptopHeaven's Blog

    kygeek.com | Reply

    Monday, June 08, 2009 1:33 PM

    pingback

    Pingback from kygeek.com

    Daily Links for Monday, June 8th, 2009 | LaptopHeaven's Blog

    Andrei Rinea Romania | Reply

    Monday, June 08, 2009 8:25 PM

    Andrei Rinea

    I don't get how you passed an anonymous type instance to the view in the controller and used in the view directly. I have tried and, just as I thought, it doesn't compile..

    maartenba Belgium | Reply

    Monday, June 08, 2009 8:53 PM

    maartenba

    That one is really for illustration purpose only. Point is not to pass the datacontext-bound IQueryable to your view but instead pass a List or similar.

    ASP.NET Chinese Blogs | Reply

    Tuesday, June 09, 2009 11:20 PM

    trackback

    6月7日链接篇:ASP.NET, AJAX, ASP.NET MVC, Visual Studio

    【原文地址】 June 7th Links: ASP.NET, AJAX, ASP.NET MVC, Visual Studio 【原文发表日期】 Sunday, June 07, 2009 12:05

    Paul Kohler Australia | Reply

    Thursday, June 11, 2009 12:58 AM

    Paul Kohler

    ...more good tips - good to see the promotion of proper use of the ViewData, makes the controller more testable too...

    kygeek.com | Reply

    Thursday, June 11, 2009 2:41 AM

    pingback

    Pingback from kygeek.com

    Daily Links for Sunday, June 7th, 2009

    rapid-dev.net | Reply

    Sunday, June 14, 2009 7:16 PM

    pingback

    Pingback from rapid-dev.net

    June 7th Links: ASP.NET, AJAX, ASP.NET MVC, Visual Studio | rapid-DEV.net

    Блог Скотта Гатри (перевод) | Reply

    Sunday, June 14, 2009 11:07 PM

    trackback

    Ссылки на 7-е июня: ASP.NET, AJAX, ASP.NET MVC, Visual Studio

    Вот вам последняя на данный момент публикация из моей серии списков ссылок . Также почитайтей мою страничку

    thinkingindotnet.wordpress.com | Reply

    Saturday, June 20, 2009 6:35 PM

    pingback

    Pingback from thinkingindotnet.wordpress.com

    Enlaces de Junio: ASP.NET, AJAX, ASP.NET MVC, Visual Studio « Thinking in .NET

    Jurnal de programator | Reply

    Tuesday, June 23, 2009 2:04 AM

    trackback

    ASP.NET MVC si Validarea Model Binder

    neilmartinagile.wordpress.com | Reply

    Tuesday, June 23, 2009 2:47 PM

    pingback

    Pingback from neilmartinagile.wordpress.com

    MVC ASP : Best Practises  « Convex Corners

    simon United Kingdom | Reply

    Thursday, August 20, 2009 1:11 PM

    simon

    Thanks for the guidelines, i have just started developing using mvc

    Gleb Russia | Reply

    Wednesday, November 18, 2009 8:26 AM

    Gleb

    Thanks for the post.
    May I ask a question - when you`re using white-listing or black-listing in model binding, what values will excluded properties/fields have in the view? Default value for its type? Or something else?

    uberVU - social comments | Reply

    Monday, January 04, 2010 4:25 PM

    trackback

    Social comments and analytics for this post

    This post was mentioned on Twitter by bobbher: More ASP.NET MVC Best Practices
    http://tinyurl.com/csra6c

    kygeek.com | Reply

    Friday, January 29, 2010 9:04 PM

    pingback

    Pingback from kygeek.com

    ASP.NET MVC Best Practices | LaptopHeaven's Blog

    Add comment




      Country flag

    biuquote
    • Comment
    • Preview
    Loading