ASP.NET MVC Sample Application at

We posted a complete Contact Manager sample ASP.NET MVC Application at the website. The source code is available in both C# and VB.NET.

The application is intentionally simple. The goal was to provide members of the ASP.NET community with an application that they could use to quickly learn how to build new applications with ASP.NET MVC.

The Contact Manager application is an address book application. The application enables you to list, create, edit, and delete contacts.


I built the application over multiple iterations. With each iteration, I gradually improved the application. The goal of this multiple iteration approach was to enable you to understand the reason for each change.

Iteration #1 – Create the application. In the first iteration, we create the Contact Manager in the simplest way possible. We add support for basic database operations: Create, Read, Update, and Delete (CRUD).

Iteration #2 – Make the application look nice. In this iteration, we improve the appearance of the application by modifying the default ASP.NET MVC view master page and cascading style sheet.

Iteration #3 – Add form validation. In the third iteration, we add basic form validation. We prevent people from submitting a form without completing required form fields. We also validate email addresses and phone numbers.

Iteration #4 – Make the application loosely coupled. In this third iteration, we take advantage of several software design patterns to make it easier to maintain and modify the Contact Manager application. For example, we refactor our application to use the Repository pattern and the Dependency Injection pattern.

Iteration #5 – Create unit tests. In the fifth iteration, we make our application easier to maintain and modify by adding unit tests. We mock our data model classes and build unit tests for our controllers and validation logic.

Iteration #6 – Use test-driven development. In this sixth iteration, we add new functionality to our application by writing unit tests first and writing code against the unit tests. In this iteration, we add contact groups.

Iteration #7 – Add Ajax functionality. In the seventh iteration, we improve the responsiveness and performance of our application by adding support for Ajax.

Each iteration has an associated tutorial. You also can download the Visual Studio Solution associated with each iteration. Here is a direct link to the Contact Manager tutorials:


  1. Matthew says:

    I’ve just done the first iteration. In the views, there was code to display/edit the id field. This was not in your code. Are you running a newer version. I’m running ( I believe) RC update.

  2. JeroenH says:

    In the sample code (first iteration), the Create/Edit methods have general catch clauses, eating all exceptions. I don’t like this kind of code, especially as this is supposed to teach relatively inexperienced developers.

  3. Max Fraser says:

    I am still trying to grasp this a bit but in Iteration #4 aren’t your interfaces dependent on the Entity Framework objects like Customer?

    If I use a different ORM in the future wouldn’t my Customer objects be different and shouldn’t they then also implement say an ICustomer interface?

  4. trendbender says:

    great example, thx Stephen

  5. mh415 says:

    After Iteration 1, Listing 2, I get this error when trying to build:

    The type or namespace name ‘ContactManagerDBEntities’ could not be found (are you missing a using directive or an assembly reference?)

    Are you missing a step to add the reference?

  6. mh415 says:

    P.S. Your blog’s timezone appears to be set to UTC +12. Is that by design? Perhaps you’re blogging from Tuvalu?

  7. mh415 says:

    Re: 2 comments up. You meant Models.ContactManagerDBEntities in Listing 2, right?

  8. mh415 says:

    I’m finding more small errors. Want them listed here, or should I contact you another way? I don’t want to flood your Comments system.

  9. @mh415 — Thanks 🙂 I changed the timezone.

  10. @mh415 – Feel free to post any problems that you discover here or email me by clicking the Contact Me link at the top of the page.

  11. JoeReynolds says:

    This is excellent example, especially iteration 7.

    You could help a lot of us if you added an iteration 8 that included paging.

  12. Milan says:

    Some problems in C# version:
    – Iteration #4, Listing 1:
    public interface IContactRepository
    should be
    public interface IContactManagerRepository

    – ContactManagerService.cs and ContactController have compile time error:
    Error 1 Inconsistent accessibility: parameter type ‘ContactManager.Models.Validation.IValidationDictionary’ is less accessible than method ‘ContactManager.Models.ContactManagerService.ContactManagerService(ContactManager.Models.Validation.IValidationDictionary)’ E:My DocumentsVisual Studio 2008ProjectsContactManagerContactManagerModelsContactManagerService.cs 14 16 ContactManager

  13. Milan says:

    Also download is provided only in VB so I can’t download Iteration #4 code and continue tutorial.

  14. JB says:

    Overall, good stuff. I only downloaded the code from the iteration 7 and it compiled and worked well. However, the AJAX browser history stuff you implemented does not appear to work in IE7. Works great in Firefox 3.x but I get no back/forward button love in IE7 when using the Ajax links. Is this an issue in the MSAjax js library?

  15. JoeReynolds says:

    I’m having a problem with your example if I want to obtain only a single column from the Group list.

    Your code is like so:

    public IEnumerable ListGroups()
    return _entities.GroupSet.ToList();

    This, of course returns everything in the Group. Let’s assume th Group table has many columns and only three are needed. What would the code above look like to do that?

  16. walter says:

    It works all great if you allow to edit all fields of a contact. But if you don’t want to allow the user to change the Phone (So Phone is only displayed on the view and is not editable < %=Model.Phone %> instead of < %= Html.TextBox("Phone") %>) I get problems.

    In public ActionResult Edit(int groupId, Contact contactToEdit) contactToEdit.Phone will be null so in ValidateContact a NullReferenceException is raised.

    If you don’t validate on Phone, ApplyPropertyChanges in EditContact() throws an exception and next a NullReferenceException is raised in the view on < %=Model.Phone %> because Model=null

    So, my question is. What to do with a field that you only want to display on your view ?

  17. @Max — That’s a good point. You should strive to program against abstractions (interfaces and abstract classes) as much as possible. When using Entity Framework, it is possible to generate abstract classes instead of concrete classes. However, I don’t cover this feature in the tutorial. This would be a good idea for a tip.

  18. @Milan — Thanks for pointing out the missing downloads for iteration #4 — we are getting this fixed.

  19. @Walter — You can’t use ApplyPropertyChanges()when you have read-only properties. In this situation, you must set each property by hand:

    originalContact.FirstName = contactToEdit.FirstName;
    originalContact.LastName = contactToEdit.LastName;

  20. @JoeReynolds — Using LINQ to SQL, you can specify that you want to return only certain properties:

    var results = from g in _entities.GroupSet select new {Id=g.Id, Name=g.Name}

    In this case, even if the group table contained multiple columns, only the Id and Name columns would be returned.

  21. achu says:

    When we use a service layer for business logic then why not use a generic repository (just 1) with IQueriable instead of IEnumerators


    with new sql server database desgin any advantage EF over Linq 2 SQL ?…/…linq-to-sql.html…/…v-linq-to-sql-take-4.html

  22. DaveM says:

    The browser navigation stuff in itteration#7 does not seem to be working with IE7.

    Have you tested it with IE7 or is it something in my configuration?

  23. walter says:

    Thanks Stephen for your reply about read-only properties.

    But it’s a solution for just a part of my problem. Perhaps I should have told more about it. I want Phone only to be read-only for specific users. But an administrator may change it. Then your solution won’t work because Phone will not be saved. So should I then have to make 2 different EditContact(), one with originalContact.Phone = contactToEdit. Phone; for the administrator. And one without for other users !?

    It seems to me that that is not a nice solution. I think the problem is that if you only want to show Phone (so I use Model.Phone instead of Html.TextBox(“Phone”) in the view) you won’t get the value back in the controller-action (public ActionResult Edit(int groupId, Contact contactToEdit)). contactToEdit.Phone will be null. Is there a way to get values back from the view even if there read-only ? Then you can just use EditContact() as it was.

    Even so, without all of the above, you’re solution solves the exception in ApplyPropertyChanges in EditContact(), But still, if you enter a wrong value in Email, a NullReferenceException is raised in the view on Model.Phone because Model=null .

    One other thing about validation. If you have a datetime-property (RegistrationDate) and on the view you enter something completely wrong (say “%$##”) then contactToEdit. RegistrationDate will have an initial DateTime-value (1-1-0001 0:00:00). This can cause troubles in your own validation, so you should be aware of that.

    I want to say thanks for your articles and examples. They are great to help me a in learning MVC!

  24. Devin says:

    Thx for you application.
    I accounted some problems in practice.
    I used ajax to render the partial view,but the whole page was represented by AJAX way in ‘divList’.the second time,i clicked the link in ‘divList’,it worked well.It surprised me for a long time.I don’t know what caused the problem.PLS help me.

  25. achu says:

    great sample. thanks

  26. Zazen says:

    Steve, this last iteration of tutorials is superb. I am completely sold on your upcoming book judging by your teaching skill.

  27. JIm Solderitsch says:

    I have an mvc project that was not created with a test project in the Visual Studio solution.

    Can I add one after the fact? I think you mention in iteration #1 that it is better to create the test project at the very beginning.

    Since that is too late for me now, can I add it after the fact?

  28. mh415 says:

    I couldn’t get a Design Gallery template to work with your example, so I tried just a brand new (empty) project and the “Happy Forest” template: Running the project results in a Parser Error: “Could not load type ‘DeleteMe.Views.Shared.Site’.” I’m new to ASP.NET, so maybe there’s an obvious fix, but shouldn’t this just work out of the box especially since “Happy Forest” is a template provided by MS?

  29. @mh415 — Unfortunately, the MVC team keeps releasing new versions of ASP.NET MVC fast and furiously and there are enough changes to cause problems with the design templates that were submitted before the changes. After the final ASP.NET MVC release, I’ve scheduled a day of reviewing and updating all of the existing design templates to ensure compatibility. Thanks for your patience!

  30. @DaveM — I had to check on the issue of using AJAX History with IE 7 with the AJAX team. To get IE 7.0 compatibility you need to include a hidden IFrame in your page named __historyFrame. I’ll update the Contact Manager sample application to include this fix. Thanks for bringing the problem to my attention!

  31. mh415 says:

    I tried using your “Contact” page, but got this error:

    “Your message could not be sent, most likely due to a problem with the mail server.”

    Just a heads-up.

  32. Jay Scott says:

    Thank you for your work on these tutorials. I’m a beginner with .net and they are really helping me to get my feet wet.

    I have currently made it almost through iteration #6 and I have noticed that for iterations 4-6, I have had to download the code because of build errors in the examples from the tutorial page. This has been frustrating since I’m not experienced at debugging C#. I really wanted to edit the code as I went, but found that in a few cases it was impossible to continue without copying in the downloaded code. Now I’m in a complete mess, so I will start 7 with the downloaded code from 6 and cross my fingers.

  33. Mark says:

    I am having the same problem as in a previous post.
    The type or namespace name ‘ContactManagerDBEntities’ could not be found (are you missing a using directive or an assembly reference?)

    Is there something I am missing? I have tried to do iteration#1 twice and get the same error.

  34. Mark says:

    Figured it out.

    The type or namespace name ‘ContactManagerDBEntities’ could not be found (are you missing a using directive or an assembly reference?)

    need to either add reference at top
    using ContactManager.Models;
    or full namespace
    private ContactManagerDBEntities _entities = new ContactManager.Models.ContactManagerDBEntities();

    Hope this saves someone else some time.

  35. Gill Bates says:

    I have rolled it up and stuck it in my pooper, the whole project!! Hihi.

  36. gerry lowry says:

    @ walter:

    something like this might solve your problem and leave you requiring one form for both your administrator and for the other users.

    I’m assuming that you’ll dynamically added the readonly property to non administrators.

    I do a similar thing as follows for Html.Encode fields:

    var originalArticle = (from m in _db.NewsArticleSet where m.Id == articleToEdit.Id select m).First();

    articleToEdit.dateAdded = originalArticle.dateAdded;

    articleToEdit.dateEdited = DateTime.Now;

    In your case, if your “Phone” field is null, you would do something like:

    articleToEdit.Phone = originalArticle.Phone;
    // set Phone for non administrators

    Gerry (Lowry)

  37. Steve says:

    It seems like iteration #6 just takes a dump at “Creating the Views”.

    I made it to iteration 6 with no problems at all, and even most of the way through 6 without problem.

    For example: “We need to modify the following existing views so that they include contact groups”:

    * ViewsHomeCreate.aspx
    * ViewsHomeEdit.aspx
    * ViewsHomeIndex.aspx

    There is no Home directory at all in the downloaded code.

  38. Lori says:

    Issue with Iteration #2

    I’m following the 2nd part where the the style sheet and master are installed from the ‘vendor’. I made the changes to the other files indicated in the tutorial; however, in both my solution and the downloaded solution, my visual studio is giving this error:

    The class or CssClass value is not defined

    on these four lines of code in index.aspx:


    I don’t understand enough about this yet so I’m not sure where/if this class=”actions delete/edit” is meant to be defined but the error seems to indicate it is not defined.

    Any thoughts?

    Thanks! Lori

  39. Lori says:

    Issue with Iteration #2
    (Sorry for the second post, clearly my html code was interpreted rather than pasted)

    I’m following the 2nd part where the the style sheet and master are installed from the ‘vendor’. I made the changes to the other files indicated in the tutorial; however, in both my solution and the downloaded solution, my visual studio is giving this error:

    The class or CssClass value is not defined

    on these four lines of code in index.aspx:

    th class=”actions edit”
    th class=”actions delete”
    td class=”actions edit”
    td class=”actions delete”

    I don’t understand enough about this yet so I’m not sure where/if this class=”actions delete/edit” is meant to be defined but the error seems to indicate it is not defined.

    Any thoughts?

    Thanks! Lori

  40. Really very nice example. Iteration #7 is very important.

  41. Thanks for sharing really useful information.

  42. Really interesting one! Thanks for sharing a nice blog.

  43. seo india says:

    Thanks for publishing this example.

  44. genuine says:

    Everyone understands what categories and products are, so there is no time wasted learning the domain.

  45. vijay says:

    Great.. thank you.

  46. education says:

    Nice, that mini MVC flowchart looks tasty.

  47. seotips says:

    Thanks, for the samples.

  48. linkexchnage says:

    Excellent. I don’t wonder why Microsoft hire you.

  49. seo-tips says:

    would be most appreciated.

  50. sem-tips says:

    I’m really quite taken with the MVC approach.

  51. seo-tips says:

    Thanks for the sample.

  52. bookmarking says:

    I really enjoyed the 4 screencasts on MVC, good stuff.

  53. blog-seo says:

    Thanks very much.

  54. key-phrases says:

    Many thanks MATE.

  55. website says:

    This is excellent example.

  56. semantics says:

    Great example, thanks Stephen

  57. designe says:

    Thanks Stephen.

  58. googleseo says:

    Thank you for your work on these tutorials.

  59. adsense says:

    Great.. thanks.

  60. seo-sem-tips says:

    Thanks for your work on these tutorials.

  61. seo-benefits says:

    Thanks for sharing useful info.

  62. very nice post thanks!

  63. f3wqe I tried to mock a call to a Linq to SQL query, but I am struggling.

  64. Thanks for this article.

  65. PhD history says:

    f3wqe I tried to mock a call to a Linq to SQL query, but I am struggling. online masters degree |
    Doctorate Psychology | online associate degree

  66. Tiffany and co tiffany and co Tiffany and co tiffany jewellery tiffany jewellery tiffany & co tiffany & co Tiffany jewelry Tiffany jewelry tiffany tiffany tiffany price tiffany price tiffany london tiffany london tiffanys tiffanystiffany sale tiffany sale tiffany uk tiffany uk tiffany and co jewelry tiffany and co jewelry tiffany and co for wedding tiffany and co for wedding

  67. ED tratments says:

    HEY ED treatments are helping me a lot Now i have a happy sex life

  68. HI people the number one selection to cure the ED its viagra use it and see for youre self the power of this great medication

  69. Really interesting one! Thanks for sharing a nice blog.

  70. rick says:

    f3wqe I tried to mock a call to a Linq to SQL query,
    Essay| Essay Writing| Essay Help| Custom Essay| Buy Essay|

  71. flash chat says:

    Well done! Nice post! This really helps me to find the answers to my question. Hoping, that you will continue posting articles having lots of useful information. Thanks a lot!

  72. It’s lucky to know this, if it is really true. Companies tend not to realize when they create security holes from day-to-day operation.wr

  73. Hello
    Stephen your posts are always useful. Thanks for sharing.
    Have a nice day