29

Simplify your controllers with the Command Pattern and MediatR

So you want to keep your controllers thin even as your application becomes more and more complicated.

You’re concerned that your controllers are getting bloated and you’ve heard people talk about the command pattern as one possible solution.

But you don’t know how the command pattern would fit into your app. How many commands should you have? Do you need separate commands every time you want to change a field in your database?

Focus on features

One of the nice things about the command pattern is that you can pause thinking about your implementation, and focus on your user’s interactions.

Let’s say you are creating a site where users can register and log in. If you take these actions and turn them into commands you’ll end up with;

RegisterUser
LogIn

When you focus on creating commands like these, you can stay focused on the feature in question and defer all those niggling questions about service layers, fat controllers, where to put your code etc.

That’s not to say you shouldn’t consider the architecture of your app, but if you focus on the feature first, you can prove the feature works before getting bogged down with other (more technical) concerns.

Hello MediatR

The good news is, implementing the command pattern is simple, especially if you use Jimmy Bogard’s MediatR to send commands from your ASP.NET MVC/WebAPI controllers.

With MediatR you start by creating a simple C# class to represent your command.

    public class RegisterUser : IRequest<bool>
    {
        public string EmailAddress { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
    }

The bool type parameter indicates the response type meaning in this case running this command will return a bool.

Then in your controller action you can “send” this command using MediatR.

    public class UserController : Controller
    {
        private readonly IMediator _mediator;

        public UserController(IMediator mediator)
        {
            _mediator = mediator;
        }

        [HttpPost]
        public ActionResult Register(RegisterUser registerUser)
        {
            bool registered = _mediator.Send(registerUser);
            return View();
        }
    }

Points to note:

  • Clean separation of concerns. You don’t need to pull repositories, services etc into your controller because all you need is the Mediator itself
  • Model Binding has automatically populated the command object (RegisterUser) based on the values passed in the HTTP request

This ensures your controllers stay bloat-free; focused entirely on handling requests and forwarding them on to your business logic.

So how do you actually handle this command? Simple, create a handler of course!

    public class RegisterUserHandler : IRequestHandler<RegisterUser, bool>
    {
        public bool Handle(RegisterUser message)
        {
            // save to database
            return true;
        }
    }

And that’s it. You now have a simple controller action which sends the command and a handler to handle it.

Finally if you need multiple handlers to react to the same message you should take a look at MediatR notifications.

  • Paul Wheeler

    Nice article, I *love* the command pattern using MediatR! Where I worked we built a huge application using a command per API endpoint and everyone on the team loved the architecture. Since we had an angular front-end (not MVC) we ended up using a single Web API endpoint based on JSON-RPC that dispatched the command from the web layer to the domain business layer where all the commands lived (in multiple projects). We could also execute the commands in a background queue, 100% of our business logic in the app lived in commands. I can’t say enough good things about it.

    http://www.jsonrpc.org/specification

    https://github.com/Command-R/Command-R/blob/master/CommandR.WebApi/JsonRpcController.cs

    • Really like this approach, not tried JSON-RPC yet but will definitely give it a go.

  • Scott Juranek

    One downside of this pattern we found is that when you are in a controller it is more time consuming to jump to the implementation. You can right click on the command class and find references. Or maybe there is a better way? We still use the mediator pattern but we include the handler class as a generic parameter. So it looks like this: bool registered = _mediator.Send(registerUser); Since 99% of our commands have only one handler then this allowed us to keep things skinny and not waste time finding implementation. Maybe others know of a better way to quickly jump to the handler? We have a large projects with hundreds and hundreds of commands and queries and even when using a nicely organized folder structure it was somewhat frustrating to be in a controller and not able to quickly find the implementation, which is off in another project loaded in the solution.

    • Hi Scott

      Yeah it does seem that a more decoupled architecture is (by it’s very nature) often less discoverable.

      I guess it’s a reasonable trade-off if you find the code is easier to maintain and less prone to bugs.

    • Paul Wheeler

      We actually put the handler as a nested class inside the request since for us they are required to always work as a pair. (sorry for the messed up formatting, I couldn’t figure out how to fix it in Disqus, I put a link with a Github example)
      https://github.com/Command-R/CommanderDemo/blob/a6e72ea9870478dc0db9e3e94ac6d11c83e771e2/CommanderDemo.Domain/Commands/Ping.cs

      public class Ping : IRequest {
      public string Name { get; set; }

      public class Pong {
      public string Message { get; set; }
      }

      internal class Handler : IRequestHander {
      public Pong Handle(Ping ping) {
      return new Pong { Message = $”Hello {ping.Name}” };
      }
      }
      }

      • niaher

        I do the opposite – the request and response classes are nested inside the handler class. I try not to reuse request and response classes in different handlers, because request/response and handler are usually very tightly coupled. In my opinion it’s better to duplicate the same request/response classes rather than reuse them.

        • Paul Wheeler

          Interesting approach. The reason we went with the Request/Response (which we call Commands) on the outside is that they are public classes in our assembly, while the nested Handler class is marked as internal. We actually have the ability for other teams to reference the public Request/Response Commands in our assembly as strongly-typed classes in their assemblies. We provide a JsonRpcClient that serializes the the Commands and sends to our server which executes them via JSON-RPC then returns the Response as json which is then deserialized to the strong type.
          https://github.com/Command-R/Command-R/blob/master/CommandR/JsonRpcClient.cs

          We also never reuse the Request/Response view models they each stand completely alone. All of our Entity Framework models are completely internal also and the necessary pieces are mapped to the Request/Response view models. Any necessary services are also internal, the only things publicly exposed in the business/domain assemblies are the Commands.

          • niaher

            I guess the 2 approaches are more or less the same. It’s only a matter of preference. The only real difference is that our handlers are public and can be invoked directly without IMediatr (useful for unit-testing).

          • Paul Wheeler

            Yeah, basically the same idea of structuring the commands/handlers as a cohesive unit.
            Good point about unit testing, we use the InternalsVisibleTo assembly attribute to allow unit testing of internal Handlers in the Domain project to be visible to the Domain.Tests project:

            //in Domain.dll/AssemblyInfo.cs
            [assembly: InternalsVisibleTo(“Domain.Tests”)]

  • Anthony Halliday

    It looks an interesting concept and I know this is just an intro but I would be interested in how the patter is used to populate view data, handle conditional redirects, validation and so on (in the same action). Do you create a response object for each command that has possible view data, redirect URL, response steams ect.?

    I guess this would come down to the implementation technique but is it easy to make independent to the HttpContext, e.g. you have a command invoked by 2 controllers but the result is different based on the URL (not query string) or cookies do you need to populate the request data in the controller, is the HttpContext still required and how about setting cookies.

    • Hey Anthony, thanks for your comment.

      Personally I would see the command handlers as pure business logic, so no references to HttpContext or anything which could be considered environment specific. For me it’s a good sign if your commands/handlers are easily portable to a different framework, for example you could switch from ASP.NET MVC to NancyFX and your commands/handlers could be used with no changes necessary.

      Any tweaking of the results, or setting of cookies etc. could still reside in your controller, or a service which exists at that layer in your application (but outside of the commands/handlers).

      Hope that makes sense 🙂

      • Anthony Halliday

        Hi Jon, thanks for your response. It does make sense and has got me intrigued to give it a try for my next hobby project.

  • The best thing about the pattern is that controllers are becoming mostly uneeded. For a project I was working on I used Fody weaver to examine all the commands and emit simple controllers like the one you wrote. It allowed me to operate on a better, command based level instead of spending time on writing and maintaining controllers.
    The second thing is that it’s really easy to write a mediator! It’s not a complex algorithm (effectively it’s just a dictionary of handlers) so it is easy to propagate in a team, not to mention that you can just embed your own implementation in a solution.

    • Anything which lets you focus on handling your actual business logic and not boilerplate code has to be good, right? 🙂

  • Pingback: The Morning Brew #2108 | Tech News()

  • Pingback: Dew Drop – June 8, 2016 (#2267) | Morning Dew()

  • Pingback: 3 ways to spot if your controller is doing too much - JonHilton.Net()

  • Yaroslav Veremenko

    Hi Jon. I have a quite difficult project I am working on. All logic is in controllers and I have about 20 of them structured by the area of use. If I try to use this approach I will end up with hundreds of class files. How would you suggest to structure something like that?

    • niaher

      It’s better to have 100s of small files, than 10s of huge files. To answer your question – you can separate those files by “area of use” as you suggest. I prefer to have separate projects for each domain/subdomain, e.g.

      * MyProject.Accounting
      * MyProject.UserManagement
      * MyProject.Inventory
      * MyProject.Orders

      etc

    • Completely agree with @niaher:disqus about small files vs large files.

      In many ways I’d consider the number of files to be mostly irrelevant.

      If you focus on creating handlers which directly map to the operations that your users can perform, then it is less a question about “how many class files have I got?” and more “what actions can my users perform?” and “how easily can I maintain/add features to my application?”.

      As you create more handlers (with names which accurately represent what they do), you can easily scan the list you’ve ended up with to decide what folders (or indeed projects) you need to start grouping related features/functionality.

      At the simplest level, those 20 controllers may just become 20 folders (or projects) containing multiple handlers.

      A nice benefit is that less code in each file means you have to read/understand less code to learn what any individual feature does and how it works.

      Hope that helps 😉

    • Luca Briguglia

      Hi Yaroslav,

      please have a look at my open source cms project https://github.com/weapsy/weapsy.

      I’m using a identical pattern identical to the one described in this article but without using an external library.

      It’s a large application already and you can see how easy is to add new features without modifications to the existing classes.

      Hope that helps!

  • Pingback: Simplify your controllers with the Command Pattern and MediatR - JonHilton.Net - How to Code .NET()

  • k3nn c.p.

    beginner in unity + mediatr here 😀 –> need to know exactly how to set up MediatR with Unity. can you show the wiring how to define container.Register() for the handlers in your example. I’ve tried it on my own using unity (the same with the example of “PONG” request/response from bogard’s wiki) but have run into runtime error:

    Resolution of the dependency failed, type = “MediatR.IRequestHandler`2[ReqMediatR,System.Boolean]”, name = “(none)”.
    Exception occurred while: while resolving.
    Exception is: InvalidOperationException – The current type, MediatR.IRequestHandler`2[ReqMediatR,System.Boolean], is an interface and cannot be constructed. Are you missing a type mapping?

    where: ReqMediatR is equivalent to RegisterUser class as they are both derived from IRequest. The point where it failed is in the code _mediator.send(reqMediatR) as I seem to think it cannot find the handler I defined in Unity. my unity registerTypes look like this:

    #region Mediatr
    container.RegisterType();
    container.RegisterTypes(AllClasses.FromLoadedAssemblies());
    container.RegisterTypes(AllClasses.FromAssemblies(typeof(ReqMediatR).Assembly), WithMappings.FromAllInterfaces, GetRequestName, GetLifetimeManager);
    container.RegisterInstance(t => container.Resolve(t));
    container.RegisterInstance(t => container.ResolveAll(t));
    #endregion
    ….
    #region Mediatr
    static bool IsNotificationHandler(Type type)
    {
    return type.GetInterfaces().Any(x => x.IsGenericType && (x.GetGenericTypeDefinition() == typeof(INotificationHandler) || x.GetGenericTypeDefinition() == typeof(IAsyncNotificationHandler)));
    }

    static bool IsRequestHandler(Type type)
    {
    return type.GetInterfaces().Any(x => x.IsGenericType && (x.GetGenericTypeDefinition() == typeof(IRequestHandler) || x.GetGenericTypeDefinition() == typeof(IAsyncRequestHandler)));
    }

    static LifetimeManager GetLifetimeManager(Type type)
    {
    return IsNotificationHandler(type) ? new ContainerControlledLifetimeManager() : null;
    }

    static string GetNotificationName(Type type)
    {
    return IsNotificationHandler(type) ? string.Format(“HandlerFor” + type.Name) : string.Empty;
    }
    static string GetRequestName(Type type)
    {
    return IsRequestHandler(type) ? string.Format(“HandlerFor” + type.Name) : string.Empty;
    }
    #endregion

    it is a bit long, but one more clue was that the debug line pointed to where the error was:

    container.RegisterInstance(t => container.Resolve(t));

    can you help how I can properly register my request handlers in unity? thanks for any info you may have.

    • Hey. It’s a little difficult to interpret this code in isolation, but I think the error is possibly indicating that your Unity container hasn’t been intiialised.

      My hunch is that your method to set up the IMediatR dependencies (everything inside #region Mediatr#) isn’t actually being triggered anywhere.

      See this example…

      https://gist.github.com/anonymous/179bddd951887c5b5e63a8ca5b523a2f

      Note that the BuildMediator() method is called from Applicaiton_Start, this seems to work.

      Thanks
      Jon

      • k3nn c.p.

        Hi Jon, thanks very much! your article paved the way for me to realize the potential of MediatR in my projects (much thanks also to JBogard for MediatR!). I have found the culprit (thanks to your example and for pointing it out). The MediatR wiki had this example registerType for INotificationHandler (Async, in this case)

        container.RegisterType(typeof(IAsyncNotificationHandler), typeof(GenericAsyncHandler), GetName(typeof(GenericAsyncHandler)));

        and I removed it early on because I did not use INotificationHandler and instead used IRegisterHandler. So later when I try to connect everything, with my naivety (or stupidity, hehe), the removed lines also removed the basic template for which I had to follow to use IRegisterHandler properly. I researched other projects that used MediatR and found this line

        container.Register<IRequestHandler, GetInventoryItemHandler>();

        which i did not have in my codes 🙂 and that was what I needed. Literally I had a light bulb flash in my head 😀 and when I implemented my own IRequestHandler like that…everything got connected and is working fine with this code:

        container.RegisterType<IRequestHandler, RegisterUserHandler>();

        before the line to register singleinstancefactory. I cannot stress how your example codes got my brain working while from the previous 2 days I was annoyed I couldn’t get the same examples to work. So thank you very much Jon. Cheers!

  • Pingback: How to easily extend your app using MediatR notifications - JonHilton.Net()

  • Δημήτρης Μυλωνάς

    Hi
    in the constructor of the UserController you’re passing an IMediator parameter
    public UserController(IMediator mediator)
    Where this parameter is being initialized? I’m using ASP.NET Core and I guess that in the StartUp class “something” need to be added to the services.
    Can you please explain?
    Thanks
    Dimitris

  • beton

    Love MediatR! Betting on it for big re platforming of our web apps (ecommerce domain).
    The only small downside of that approach is debugging IMO.
    You do not know @ run time with requests are linked to with handler/notification handler so you have to check up you installers up front and it is not immediate at the beginning (especially for new developers that start working with such abstract code bases xD)

    Anyway great series!