Survey of two large MVC projects

A large-ish MVC project in which I led the architecture is hitting a milestone of 12 months in development (though released to production for some months now). It’s a similar project to the one where AutoMapper came from, but this time targeting a more focused domain, and subject of the How We Do MVC post.

Much of the patterns discussed come from a certain context, especially on optimizations I look at for accelerating delivery that don’t necessarily apply to other systems. Some comparison stats between these two projects:

Project A

  • ~6 years of continuous development at various pace
  • Over 100 deployments to customers statewide
  • 352 Controllers
  • 1079 Actions
  • 3 actions/controller

Project B

  • 12 months of continuous development at continuous pace
  • At least one deployment to a customer, a few more planned this year, then dozens the next
  • 71 Controllers
  • 534 Actions
  • 7.5 actions/controller

So while B only has 20% of the controllers of A, it has half the actions. This is for a couple of reasons:

  • 6 years ago AJAX was difficult for accessibility. Not the case any more, so AJAX plays a much bigger role
  • Task-based UIs mean a lot more contextual actions take place on one screen, depending a large number of factors

All these “put XYZ” on a diet talks, preferring slices over layers, and in general wanting new features to only add classes and files and not modify them is because of the scope of projects I generally deal with. I have to come up with tools and techniques to address design challenges of this scope, so tools like AutoMapper, the mediator pattern, feature folders, HTML conventions, slices over layers, no convoluted project structure and so on are critical to allow this sort of project to continue at a pace without slowing down under its own weight.

In this project, we had no repositories. No layered project structure. No abstractions over dependencies. No vegetable-based architectures. The last 12 months had roughly 250 working days, which averages out to a new controller every 3.5 days and a little over 2 new controller actions every single day. That sort of pace can only come from a laser focus on highly cohesive code, where each new feature only added requisite classes for feature where pieces differed, and allowing conventions to fill in mundane details that we intended to be consistent site-wide.

I’ve already covered our designs in our controllers, next, I’ll pick up the conventional HTML post that allowed us to create a highly streamlined process for building out our views (and how we extended this concept to client-side templates).

About Jimmy Bogard

I'm a technical architect with Headspring in Austin, TX. I focus on DDD, distributed systems, and any other acronym-centric design/architecture/methodology. I created AutoMapper and am a co-author of the ASP.NET MVC in Action books.
This entry was posted in ASPNETMVC. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • gilligan_MH

    yes! Keep them coming. I am in charge of an mvc web app (not site) for Warehousing that is just about to hit production so I am looking for spots where I can streamline design.

  • What does “Slices over Layers” mean exactly?

    • gilligan_MH

      You divide your project and namespaces by Feature Name or Feature Grouping instead of by technical components. So you would have Features/Account/AccountController and Features/Account/AccountEntity instead of Controllers/AccountController and Models/AccountEntity

      • Thanks for the info gilligan. So this different way of thinking, where does it lead? I can “feel’ the difference a bit in my mind but overall it seems to be the same organization of an app just different naming convention…

        • jbogard

          So instead of classes spanning across features, they’re targeted towards a single slice. Single action, Foo. Foo view, FooValidator, FooHandler, FooViewModel, Foo.js. All concerns, organized together, built around concepts. But no common type spanning them, instead you have them as instances of a concept (handling a query, the view, supporting javascript, etc).

          • Smart ;) . I like it, thanks for the knowledge.

          • Phil H

            Just out of interest, how is that organised with regards to projects / assemblies?

          • jbogard

            Initially one project since we had one application. Eventually we had three projects, one for core domain and two subdomain UIs. Basically our deployment needs defined our organization approach.

          • Do you allow developers working on a slice to “do their own thing” in terms of patterns, practices, library choices, etc…? For example, if one developer working on a slice wants to do their thing in Angular, while another developer working on a different slice wants to do their thing in Knockout, do you allow that? Do you enforce coding guidelines across slices?

          • jbogard

            No. We have a consistency of approach across slices, but nothing really enforced. It turns out though that code for components inside a slice was relatively small. On the UI side, we could have done that for each view, but it was really the UI requirements driving that.

          • Apologies for asking a yes and a no question in the same post. I can’t tell if your “No” is in reference to the “do you allow developers to do their own thing” or “do you enforce guidelines” question..

          • jbogard

            Do own thing – not choose new frameworks. That gets messy. Otherwise, yeah, we just have guidelines and peer reviews to make sure nothing was missed perf-wise etc.

  • Robert Bonham

    Off the topic, but i’m curious of the size of the team working on these projects and their rolls at a high level? (architect, developer, etc)

    Thanks, and yes, keep these post coming

  • Pingback: The Morning Brew - Chris Alcock » The Morning Brew #1638()

  • seankearon

    Very interesting to see your figures – 1 controller every 3.5 days, 2 actions per day. Can you give us an idea of the team size? Could give a rough approximation of what an average action is like?

    • jbogard

      It varied a bit, I’d say we had minimum of 4 developers at all times, a bit more when we were focused on a deployment.

  • jdn

    “No vegetable-based architectures”.

    I had to think about that one for a second. LOL.

  • I think we need stating the above information and go deep in to share, thanks | htpt://

  • Bhalchandra Kadam

    Just out of curiosity, if there are no layers/repositories – how did you manage the ORM stuff. Did you use the EF for such a large projects?

    • jbogard

      For large projects? Yes (both NHibernate and EF). How did I manage it? There wasn’t much to be managed, I used dependency injection, and if a component needed a DbContext, it just used it directly. No wrappers/abstractions etc.

  • Daudi Husbands

    You started with one project? What??? Does that mean you really had UnitTesting, IntegrationTesting, UI Testing, Database, DependencyInjection, AutoMapping, Validation, Message Handling, Application Services, UI etc. all in one project?
    Do you remember CodeCampServer? I’ve been using that as a template for almost every project I picked up. It’s a royal pain but I’ve grown so used to it. I can’t even bring myself to switch from NHibernate to EF even though I love EF’s implementation of LINQ so much better that NH.

    Oh I need therapy. Lol
    Keep up the great work. Big fan

  • scichelli

    I’ve spent three years (off and on) working on that first project and four months (full-time) working on the second one. I am having a blast with the new one–I can add features so quickly. I don’t miss repositories at all. Task-based UIs (and laser-focused controller actions) make clearer code and a more intuitive user experience. While I agree with organizing by feature-based folders (instead of “Views”, “Models”), I do mutter “Jimmy something something” under my breath when R# offers me a list of 17 AddEditViewModels. (I just have to retrain my hands: Ctrl-N, Feature Name, space, AddEdit…)

  • All the contents you mentioned in post are too good and can be very useful. | |

  • brgrz

    Hey Jimmy, thanks for the insights. Do you also use T4MVC? Do you use T4MVC with support for feature folders too? If you use Feature Folders, do you also separate routing configuration per feature or do you have all the routes in one big config class? To what extent do you use Areas? Do you ever package up Areas into Nuget packages to make them more reusable (for instance, something similar that the ASP.NET Web API Help Page Nuget package is doing)? When you said you had one Core project and two different UI projects, what are those two (do you separate frontend and backend per project or per area or per feature?) Quite a few question but thanks!

    • jbogard

      Nah, I don’t use T4MVC at all. Feature folders don’t require routing config, since my controllers don’t move (really I’m just renaming “Views” to “Features”).

      Don’t do much with areas at all any more.

      One core project, two UI projects, the core had everything that needed to be shared (domain models, services, UI services, UI widgets/config).

  • Miguel


    So you have everything in one VS project?

    Where do you place your handlers, commands and queries? Also inside each feature folder? Do you have folders inside feature folders to organize files by type or you just place all files there? Would be nice to see a full folder structure of what you are using …

    What type of files do you place under feature folders?

    Thank you