Search code examples
asp.net-mvc-3single-responsibility-principlecommand-pattern

Command Pattern in .NET MVC 3 (removing junk from the controller)


I am trying to implement this Command Pattern on my .NET MVC 3 application, specifically for saving edits to a Thing. I am undecided on how to proceed. Before I get to the actual question, here is the simplified code:

public class ThingController
{
    private readonly ICommandHandler<EditThingCommand> handler;

    public ThingController(ICommandHandler<EditThingCommand> handler)
    {
        this.handler = handler;
    }

    public ActionMethod EditThing(int id)
    {
        ...build EditThingViewModel and return with View...
    }

    [HttpPost]
    public ActionMethod EditThing(int id, EditThingViewModel vm)
    {
        var command = new EditThingCommand
        {
            ...not sure yet...
        };

        this.handler.Handle(command);

        ...redirect somewhere...
    }
}

My EditThingViewModel is wholly disconnected from my domain, which consists of POCO classes. It seems like my EditThingCommand should look like this:

public class EditThingCommand
{
    Thing ModifiedThing;
}

However, building ModifiedThing would then still be happening in my controller. That's the majority of the work in this case. By the time ModifiedThing is built (and the "old" timestamp applied to it for optimistic concurrency checking), all that's left is for command to call Update on my data context.

Clearly there is value in being able to easily decorate it with other commands, but I'd also like to be able to move the construction of ModifiedThing outside of my controller. (Perhaps this question is really just about that.) EditThingCommand is in my domain and doesn't have a reference to EditThingViewModel, so it can't go there. Does it make sense to have another command in my presentation layer for mapping my viewmodel to my poco entity?


Solution

  • After several months of using this pattern on other projects, it is apparent to me that the commands on this particular project were simply too general and therefore too complex, requiring too much setup. It would have been better to create, for example, an EditThingTitleCommand and a MoveThingPiecesCommand and so on, and call them from their own ActionMethods.

    In other words, when using the command pattern, don't just use the commands as replacements for typical CRUD operations. With more specificity comes more benefit.