Los Techies : Blogs about software and anything tech!

Going Controller-less in MVC: The Way Fowler Meant It To Be


This is sort of a stream-of-consciousness post. Several folks have been asking me what I mean by ‘Controllerless actions’ and what I’m thinking about doing in FubuMVC.  The conversation has already started publically on twitter, so I thought I’d try to capture a brain-dump of my thoughts in a blog post so the conversation can continue.  This post likely won’t be up to my normally high (read: barely legible) standards. Please forgive.

Before we go further, read this:

http://www.martinfowler.com/eaaCatalog/frontController.html

And then view this:

public class ProductController : Controller
{
    private IProductRepository _repository;

    public ProductController()
    {
        /// That is the only point you need to replace
        /// if the data source changes.
         _repository = new EntityProductRepository();
    }

    public ProductController(IProductRepository repository)
    {
        this._repository = repository;
    }

    public ActionResult Index()
    {
        return View(_repository.GetAll());
    }

    public ActionResult Create()
    {
        return View();
    }

    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult Create([Bind(Exclude = "Id")] Product productToCreate)
    {
        if (_repository.Create(productToCreate))
            return RedirectToAction(“Index”);

        return View();
    }

    public ActionResult Edit(int id)
    {
        return View(_repository.Get(id));
    }

    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult Edit(Product productToEdit)
    {
        if (_repository.Update(productToEdit))
            return RedirectToAction(“Index”);

        return View();
    }

    public ActionResult Delete(int id)
    {
        return View(_repository.Get(id));
    }

    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult Delete(Product productToDelete)
    {
        if (_repository.Delete(productToDelete.ID))
            return RedirectToAction(“Index”);

        return View();
    }
}

I’m pretty sure this ProductController is not exactly what Martin Fowler had in mind.  Yet, it’s probably an actually cleaner example of what most controllers that are currently being written “in the wild” for ASP.NET MVC and MonoRail (the two most popular MVC frameworks for .NET) look like.

ProductController is a somewhat monolithic controller in that it has many actions.  It’s structured this way for several different reasons, a few of which I’ll list here:

  • The limitations of the framework upon which it’s built.  ASP.NET MVC, MonoRail, FubuMVC, and others are structured around controllers and actions (yes, even the venerable, estimable Ruby on Rails [peace be upon it] has this mindset to one extent or another).
  • The limitations of our imaginations: That’s how we’ve always done MVC!
  • The habit of doing Model2 style MVC (from which the Heavy Controller/Action paradigm comes)

Reading Fowler’s ideas on Front Controller, and looking at these Model2-esque controllers and actions, I scratched my head and said, ‘Huh. That isn’t right!’

Model 2

Model2-style MVC is concerned primarily with whole request handling and/or whole page rendering.  This was OK in the days of non-AJAX whole page post-backs (uphill, both ways, in the snow, with bare feet).  But in the modern day of heavily templated, composite UIs (think ASP.NET WebForms MasterPages, Spark Layouts, Partials, etc), and with heavy AJAX use for browser-initiated partial updates, the whole-page rendering concept doesn’t really hold up.

We usually end up contorting and bending the framework to do things that don’t really hold up that well under the Model2 way of thinking.

Front Controller

In the Front Controller pattern, the only “Controller” present is the dumb front controller that has two methods on it: Get() and Post() and you could probably just boil those down to HandleRequest().  If this sounds oddly reminiscent of IHttpHandler, you’re thinking correctly.  An IHttpHandler is, in one manner of speaking, a Front Controller.  Properly implemented, the Front Controller would load a series of commands for that particular URL/request context and then execute them either via round robin or via chain-of-responsibility (in serial).

In ASP.NET MVC, MonoRail, FubuMVC, and several other MVC frameworks for .NET, the Controller Action is essentially one BIG command that handles almost all aspects of the request.  Action Filters and FubuMVC’s Behaviors serve as a way of achieving the more compositional benefits of Commands, but they both have some limitations.

If you’ve been doing any serious MVC work with any of the popular frameworks recently, you will have certainly felt the pain of controller actions getting too large, or having too many concerns.  You may also have noticed that your views require data that’s otherwise totally unrelated to the current request (i.e. the user’s current login status for a request to retrieve a list of all products in the persistence store).  So you might use Action Filters or FubuMVC Behaviors to compose all the data the view will eventually need.  Action Filters, being attributes on the Action and thus explicitly declared, present a strong challenge to proper compositional assembly of the data needed by the view for that request. FubuMVC behaviors certainly handle this better, but the configuration can get a little messy and verbose wiring them up explicitly or even conventionally to your actions. So they are not without their drawbacks also.

This all leads inexorably to the questions: Why even have a controller at all?  Aren’t actions really just things-to-do in their own right? And aren’t Actions only a part of the responsibility of fulfilling the request (the rest being satisfied by Action Filters/Behaviors)?

What if we promoted that idea of action filters/behaviors, and the stuff-to-do-for-this-request to equal footing – each simply being a command that gets executed for a particular request?

There’s one little tiny problem in that, when in your Master Page, for example, you may need one tiny nugget of information that’s completely unrelated to the current request, but otherwise needs to be satisfied.  Rendering the view, then, becomes yet another command that can actually trigger more commands to be executed.

Explicitly Configured combined with View-Driven Command Resolution and Execution

After several talks with folks like Mark Nijhof, Jeremy Miller, Jimmy Bogard, and others, it soon became clear that we needed to rethink how we were approaching our MVC-based designs and to try to get more in touch with our “Inner Fowler” so to speak (but not too much).

I have observed that there are, in any MVC request, explicit things that need to happen (NHibernate Session-per-Request, load the current IPrincipal for ASP.NET Authorization, load the current user’s culture and timezone information, etc).  There are also things that MAY need to happen based on whether the View needs some particular type of information.  The view generally shouldn’t be making decisions other than to simply declare that it needs a partial rendered (or a MasterPage, etc).  Theoretically with WebForms or Spark views, we could, at config-time, figure out just exactly what information the view and its various partials are going to require. This way you could resolve everything at config-time and avoid any nasty runtime problems with missing information and such. I’m somewhat down on this theory and I’m anticipating this won’t work out like I hope and that there will always be runtime gotchas here.

At any rate, if we have to live with runtime surprises while we flush out this idea, that’s OK for right now.  But I really feel that the general idea (that is, demand-based command execution) is going on the right track.

Explicitly Configured Command Resolution and Execution

This one is easy: Just configure it!  We’ll have a fluent API or some sort of conventional way (or both) of automatically determining which commands need to be executed for a given request/URL.  FubuMVC currently has this with behaviors so this is achievable today, but I think we can do better and I intend to.

View-Driven Command Resolution and Execution

This one is a little tricky since the View will be requesting this at render time, on-the-fly and may result in YSOD’s if something it depends upon isn’t available. 

I’m thinking that the View would have access to the IoC Container (or Common Service Locator as the case may be) and will request something like IFubuCommand<TModel> where TModel is the particular type of model that partial requires. So you might see something like this:

<%= this.RenderPartialFor<LoginStatusModel>().Using<LoginStatusPartial>() %>

The RenderPartialForExpression would then access the IoC container and retrieve an implementation of IFubuCommand<LoginStatusModel> and then pass that to the LoginStatusPartial (which may turn around and request other IFubuCommand<XYZ>’s.

Command Registration

Commands would be registered at config-time via the normal IoC container configuration.  Using StructureMap, for example, you would simply scan all or certain assemblies for any class implementing ICommand<TModel> and load them automatically into the container as handlers.

Diagnostics

This is also somewhat complicated since the views may request different things at runtime (they may request an IFubuCommand<MODEL> where MODEL may not be known until runtime in which case things may go awry.

You could probe the Container for all IFubuCommand<TModels>’s and then simply observe Views as they execute and deliver a report after-the-fact to show what was used, by whom, and how much.  While this won’t necessarily be exhaustive, it would likely help a developer who’s troubleshooting a particular issue (or perhaps a transient, occasional error).

URL Resolution

This is perhaps the biggest change. Since there are no controllers or actions, the URL becomes the only distinguishing characteristic between two “actions” (or chains of commands) to be performed server-side.  That means the URL (or URL stub like /blah/baz/{Id}) becomes a first-class citizen – probably even its own class/type. 

One thought I’ve been kicking around about this is that you would have a class per URL Stub which has c’tor parameters or properties representing the various options of the URL.  For example, consider this “URL object” or “Action object”:

public class EditProduct
{
  // /products/edit
  public EditProduct()
  {
  }
  
  // /products/edit/9
  public EditProduct(int id)
  {
    Id = id;
  }
  
  public Id{ get; set;}
}

And to render a hyperlink to this action, for example, you might: <%= this.LinkTo<EditProduct>(Model.ProductId) %>

or even:  <%= new EditProduct(Model.ProductId) %>

Which is a lot cleaner than: <%= this.HyperLinkTo<ProductController>((p,i)=>p.EditProduct(i)) %>

Wrapping Up

So this is my brain dump and currently the rough plan I’m using to spike out some of these things in FubuMVC.  Some of it is working out, other things I’m still skeptical.

I’d love to hear what you’re thinking with your MVC-based designs.  How are YOU handling the composition problems?

Kick It on DotNetKicks.com
Posted Jun 18 2009, 03:06 AM by chadmyers
Filed under: , ,

Comments

Steve Burman wrote re: Going Controller-less in MVC: The Way Fowler Meant It To Be
on 06-18-2009 7:56 PM

All of your points about the current MVC frameworks certainly resonate with me.

Where you suggest a syntax like

<%= this.RenderPartialFor<LoginStatusModel>().Using<LoginStatusPartial>() %>

I am currently doing similar with Steve Sanderson's IPartialRequest implementation. Working well so far and I think something of that flavour is the best solution to the dependent view model issue.

I am looking forward to any developments in this space in FubuMVC.

bogardj wrote re: Going Controller-less in MVC: The Way Fowler Meant It To Be
on 06-18-2009 9:03 PM

I think it _really_ depends on what you want to do in your view.  If it's a composite UI, then filters are the way to go.  Other wise, RenderAction (from the MVC futures assembly) is great for orthogonal information in the views.  I really don't want to muck up my view model just for the header information bar (Welcome Jimmy, [logout]).

So, your IFubuCommand is ASP.NET MVC's version of RenderAction.

But filters just to show common data?  Blech, it bleeds concerns into my controller structure.

Anyway, orthogonal concerns get even worse in regular MVC when you want to do things like attribute validation, then business-rule validation, all of which is still orthogonal to doing the work of the command.  We get around it with a "ProcessXyz" method on our base controller class, which then delegates to the real command processor.  TEMPLATE METHOD PATTERN GONE HORRIBLY AWRY

Hernan Garcia wrote re: Going Controller-less in MVC: The Way Fowler Meant It To Be
on 06-18-2009 9:40 PM

I already started going on a similar path.

Allthough on top of ASP.NET MVC. A very, very, very rought idea at http://pronghorn.codeplex.com lot's of thing will change. But in this case the views call for the partials and the partials each know what they need. They all have access to the Container that is injected in the controller (or front controller althought is not unique).

Brian Donahue wrote re: Going Controller-less in MVC: The Way Fowler Meant It To Be
on 06-18-2009 10:44 PM

I've been really interested in Actions/Commands as first class citizens in the MVC/MVA model for a while (see post last Feb: http://is.gd/15OX2), and am really glad to hear you, Jimmy, Jeremy, et al talking about it.  I think this would make an awesome VAN talk for sharing ideas.  I played around with a web stack where the request would first be handled by a request action, following the thunderdome principal, and then based on the request (e.g. "accepts" header, or whatever) and the model returned, the framework would execute the appropriate response action.  Anyway, very interested to see what you come up with and/or discuss with you all sometime.

Reflective Perspective - Chris Alcock » The Morning Brew #372 wrote Reflective Perspective - Chris Alcock &raquo; The Morning Brew #372
on 06-19-2009 3:26 AM

Pingback from  Reflective Perspective - Chris Alcock  » The Morning Brew #372

Ryan Riley wrote re: Going Controller-less in MVC: The Way Fowler Meant It To Be
on 06-19-2009 3:38 AM

This sounds very similar to what Sebastian Lambla is doing with <a href="http://openrasta.com">Open Rasta</a>, except that each HTTP verb would be mapped to an individual command. Is that about right? In other words, and keeping it simple, you would create a handler for a specific URI and verb combination?

Andrew Davey wrote re: Going Controller-less in MVC: The Way Fowler Meant It To Be
on 06-19-2009 4:38 AM

Check out Snooze for strongly typed, first-class URL objects:

www.assembla.com/.../snooze

Andrew Davey wrote re: Going Controller-less in MVC: The Way Fowler Meant It To Be
on 06-19-2009 4:40 AM

Also checkout this screencast about composite views

screencast.com/.../1BM4yCa8x

I think you're on to something good here.

FubuMVC – Resources « just in ram wrote FubuMVC &ndash; Resources &laquo; just in ram
on 06-19-2009 8:24 AM

Pingback from  FubuMVC – Resources « just in ram

chadmyers wrote re: Going Controller-less in MVC: The Way Fowler Meant It To Be
on 06-19-2009 8:57 AM

@Ryan

You're right. Sebastian's been doing a lot of cool stuff and he's way ahead of all of us on most of this stuff, lol.  From what I understand, OpenRasta handles this problem slightly differently. I'm probably wrong, but it seems like it's a slightly different flavor of this concept.  I think there's still a little room for exploration here.

@Andrew: I'll check out that screencast. Thanks!  I looked at Snooze real quick and was turned off by the base classes. I'll dig a little deeper, but I'm convinced that the URL/Action objects should be POCO to the max extent possible.

Ryan Kelley wrote re: Going Controller-less in MVC: The Way Fowler Meant It To Be
on 06-19-2009 10:35 AM

This sure means a lot of rework! No, seriously I think if we move in this direction it will be much better for all of us in the long run.

BrianDonahue.Persist() wrote MVC - The Anti-Controller Revolution Heats Up!
on 06-19-2009 12:51 PM

MVC - The Anti-Controller Revolution Heats Up!

Andrew Davey wrote re: Going Controller-less in MVC: The Way Fowler Meant It To Be
on 06-19-2009 2:50 PM

No base class eh? Hmm sounds doable. Snooze is based on asp.net mvc, but I'm sure I can make a delegating controller action invoker...

A layer super type is nice for convenience methods however...

chadmyers wrote re: Going Controller-less in MVC: The Way Fowler Meant It To Be
on 06-19-2009 3:09 PM

@Andrew

If you need convenience methods, use extension methods. Don't *require* a base class purely for convenience.  Providing an optional one is cool, but it should not be required.

James Kovacs wrote re: Going Controller-less in MVC: The Way Fowler Meant It To Be
on 06-19-2009 3:49 PM

Just thinking out loud... If your request/response pipeline is going to centre around the action and is really about transforming an input request into an output response, wouldn't a functional language like F# be more suitable for creating this style of front-controller framework rather than an OO language?

chadmyers wrote re: Going Controller-less in MVC: The Way Fowler Meant It To Be
on 06-19-2009 4:35 PM

@James:  Is F# better at retrieving an array of ICommand<T>'s from the container than C# is?  There's really not that much to do, to be honest.

It's all in the configuration. I suppose F# or maybe even Boo or something might be better for that (since it's really all DSL mucky-muck work).

At this point, I don't see a lot of benefit mixing up languages for this and complicating things. very few folks know F#, so it'd be placing an undue burden on the users of the framework for very little, if any, benefit.

James Kovacs wrote re: Going Controller-less in MVC: The Way Fowler Meant It To Be
on 06-19-2009 7:02 PM

I wasn't thinking of retrieving an array of ICommand<T>'s. That can be done easily in many languages. I was thinking more of actually composing and writing the pipeline using F# functions. From my limited exposure to functional languages, they are very good at succinctly expressing transforms, which is essentially what we're doing. I agree that most developers - myself included - aren't sufficiently familiar with functional languages to make this a viable choice in the near-term. It was more a philosophical question of whether this style of front controller would be easier to write in a functional language than an OO one.

Jeffrey Palermo (.com) wrote The ASP.NET MVC ActionController – The controllerless action, or actionless controller
on 06-20-2009 12:14 AM

There has been quite  a bit of discussion about how controllers are really namespaces trying to get out once you use the concept on a nontrivial application.  Brian Donahue’s post on The anti-controller revolution prompted me to do this little

Jeffrey Palermo wrote re: Going Controller-less in MVC: The Way Fowler Meant It To Be
on 06-20-2009 12:20 AM
Daily Links for Saturday, June 20th, 2009 wrote Daily Links for Saturday, June 20th, 2009
on 06-20-2009 7:31 AM

Pingback from  Daily Links for Saturday, June 20th, 2009

Sebastien Lambla wrote re: Going Controller-less in MVC: The Way Fowler Meant It To Be
on 06-20-2009 8:17 AM

Hey there,

yes it's somehting that has been in OR for a while, the idea that resource types (what snooze calls strongly-typed URLs) are the things that drive URIs.

That said, as you correctly point out, by default in OR the action semantics is based on the resoure type and the http verb, and from what I understand, your proposal carries the operation semantic as part of the model definition (your EditProduct).

Laribee suggested the idea of using profiles in OR to let you define various programming models, and is something that i'm investigating. The latest version of OR includes a new way of defining / discovering / executing operations, and so this scenario, like a few others (around controllers with only one methods and public properties for resolution by binders and codecs) should be very easy to support.

If there's demand for it, it'd be easy to make such a profile to run fubu on top of OR instead of asp.net, and get the best of both worlds :)

Seb

My Ever Changing Controllers « Tales from the Heap wrote My Ever Changing Controllers &laquo; Tales from the Heap
on 06-21-2009 10:11 PM

Pingback from  My Ever Changing Controllers «  Tales from the Heap

ASP.NET MVC Archived Blog Posts, Page 1 wrote ASP.NET MVC Archived Blog Posts, Page 1
on 06-22-2009 12:42 AM

Pingback from  ASP.NET MVC Archived Blog Posts, Page 1

Jeff Olson wrote re: Going Controller-less in MVC: The Way Fowler Meant It To Be
on 06-22-2009 2:34 AM

Well, everyone else is self-promoting in here, so what the heck. Here's my take on the problems discussed in this post: github.com/.../mercury

If you're interested in another (drastically) different approach to the issues of controller/action composition and how endpoints are exposed from the server to the client (which is a big chunk of what the controller/action mapping convention that is so popular in the "non-stupid" ASP.NET frameworks these days is about), you should really check out the marvelous Ruby-based Sinatra (http://www.sinatrarb.com/) framework. The excellent stuff going on in that framework is what is driving my current experiments in ASP.NET.

Try all you guys want to make MVC "prettier" and more intention-revealing in C#. The problem, though, is this: You're stuck using a crappy, general-purpose language to try and elegantly express what is really better expressed in other ways. And I don't think "But! But! Tooling!" is convincing enough of an argument, longterm, to justify this self-flagellation.

If you look at what the current state-of-the-art is with regard to web apps (rich js client, rich domain), you can pretty much see that the job of the actual web framework (grossly over-simplified: map data to/from the client/server) is 1) narrowly-scoped and 2) highly optimizable.

Years of pounding the ideas of loose-coupling, SRP, DRY, etc into our heads has given us web applications mappings that are, when you get down to it, pretty damn anemic. All the data-access, behavior, etc lives in the domain or is abstracted out into the app service layer. We've (hopefully) broken the cycle of abuse of using retarded server callbacks in rendered views in favor or much more easier testable js (javascript controllers/views, anyone?). We're using view engines that don't suck to compose tighter, less-entangled rendered views (that are becoming pretty anemic, themselves, as the js side of things gets more of a share of the the action). So what about what's left over?

What I'm saying this: The stuff we code at the web framework level (controllers, actions, behaviors, etc) is pretty damn rote, all in all. In other words: A perfect candidate for a DSL.

Enter things like Sinatra (or my own solution, which is still incubating and thus not heavily pimped, here).

You're gonna be stuck with chestnuts like overloading constructors of a class to model actions as long as you remain in the BDSM box of C# as your only way to do this kind of thing (to get the tired Matrix cliche out of the way: it's a prison for your mind).

The domain requires a rich language to be expressed fully; use C# there. The client requires a rich language to be expressed; go ahead and use js or whatever for that, as well.

But the web framework? Seriously. In statically typed .NET, the most complicated things it does is 1) deliver dependencies to 2) do query/command tasks to ultimately 3) map data to/from the client/server. period. Item 1 isn't that big of a deal in Ruby because you can monkey-patch that stuff away and bait-and-switch dependencies when testing. Oh yeah, and the web framework probably manages your security and session baggage, as well.

Anywho, I'll get off my soapbox, now. I just think that the entire discussion up until this point is predicated on the assumption that the job that web frameworks do is something that really *requires* verbose, convoluted solutions like those that're prevalent in the debate. We can do better, in my opinion.

DotNetShoutout wrote Going Controller-less in MVC: The Way Fowler Meant It To Be - Chad Myers' Blog - Los Techies
on 06-22-2009 11:40 AM

Thank you for submitting this cool story - Trackback from DotNetShoutout

Sergio Pereira wrote re: Going Controller-less in MVC: The Way Fowler Meant It To Be
on 06-22-2009 8:33 PM

@James, you may want to take a look at Bistro (bistroframework.org/index.php), which is an F# MVC framework.

Andrew Peters wrote re: Going Controller-less in MVC: The Way Fowler Meant It To Be
on 06-22-2009 10:25 PM

"The limitations of our imaginations: That’s how we’ve always done MVC!"

Not really true. In Java, this pattern has been around for donkeys years. For a good example, take a look at WebWork, which powers the Atlassian apps like Jira etc.

Adam wrote re: Going Controller-less in MVC: The Way Fowler Meant It To Be
on 06-23-2009 4:08 AM

I reallly like where this idea is headed Chad. Hope that some samples and code spikes come out so we can begin exploring it further.

Even just having Controller's as actions with a Get/Post method is really a great start.

alex pedenko wrote re: Going Controller-less in MVC: The Way Fowler Meant It To Be
on 06-24-2009 8:40 AM

That's actually one of the fundemental design principles in Bistro - (as sergio said - www.bistroframework.org). Aside from the f# piece (which isn't a requirement), the major premise there is that you bind controllers to aspects of a url, and multiple controllers service a single request, without being tightly coupled with each other. that way, your url becomes the first-class citizen you describe.

igorbrejc.net » Fresh Catch For July 9th wrote igorbrejc.net &raquo; Fresh Catch For July 9th
on 07-09-2009 9:04 AM

Pingback from  igorbrejc.net » Fresh Catch For July 9th

Summary 14.07.2009 « Bogdan Brinzarea’s blog wrote Summary 14.07.2009 &laquo; Bogdan Brinzarea&#8217;s blog
on 07-14-2009 4:08 AM

Pingback from  Summary 14.07.2009 «  Bogdan Brinzarea’s blog

More FubuMvc features « Shashank’s Blog wrote More FubuMvc features &laquo; Shashank&#8217;s Blog
on 08-03-2009 10:22 AM

Pingback from  More FubuMvc features « Shashank’s Blog

The Problem with the MVC Frameworks – Introduction | Wizards of Smart wrote The Problem with the MVC Frameworks &#8211; Introduction | Wizards of Smart
on 08-05-2009 2:04 PM

Pingback from  The Problem with the MVC Frameworks – Introduction | Wizards of Smart

VS2010学习 wrote The ASP.NET MVC ActionController – The controllerless action, or actionless controller
on 08-25-2009 5:14 AM

  There has been quite  a bit of discussion about how controllers are really namespaces trying

The ViewModel and the MasterPage « typesafe wrote The ViewModel and the MasterPage &laquo; typesafe
on 11-01-2009 2:57 PM

Pingback from  The ViewModel and the MasterPage « typesafe

Inferis’ Mind Dump » Blog Archive » links for 2009-12-03 wrote Inferis&#8217; Mind Dump &raquo; Blog Archive &raquo; links for 2009-12-03
on 12-03-2009 5:07 PM

Pingback from  Inferis’ Mind Dump  » Blog Archive   » links for 2009-12-03

Copyright Los Techies 2008, 2009. All rights reserved.
Powered by Community Server (Commercial Edition), by Telligent Systems