Controller != code-behind

This always drives me nuts.  I'm working on a brand spankin new project that has zero code, so a co-worker and I are working on how we want to address the MVP implementation.  So lately I'm reading up on new ideas that people have come with since the last time I did a ground-up implementation regarding MVP, service facades, business proxies, etc, and then most of my reading is on mocking MVP and looking at things like StructureMap and Spring.Net.  My co-worker is looking at MVP stuff and Web Client Software Factory and ObjectBuilder and the like.  So if anybody has any excellent resources, feel free to post them here.

Ok, so back to it, I was looking up MVP ideas and came across this page.  Half way down the page it says "Controller: Code-behind .vb/.cs files"  and goes on to say "ASP.NET doesnt have central controller function, instead the code-behind file can directly make request to the Model and can update the dataset. But lot of controller function can be implemented in code behind class events in .aspx or .ascx pages, like Page_Onload(), OnItem_Created() etcevents."

IMO: No, no, no.

Code-behind is View.  Always.  Controllers are UI agnostic and have no knowledge of System.Web at all in Asp.Net applications.  Zero.  Zilch.  Fowler last year split the MVP into Passive View and Supervising Controller.  Passive view is the more testable of the two because all behavior of the view is driven by the presenter, and is the most popular way to design MVP in Asp.Net.  Presentation Model is another popular way to design MVP and is close to Passive view except it is a more view-event-driven design, which works well, but events are harder to test.  Regardless of which way you go, there is a clear and obvious seperation of responsibilities, and I'm pretty sure if Fowler had written any of those to be specific to .Net, somewhere in the first or second paragraph of each one, he would say "code-behind is view code, never controller/presenter".

If you place controller responsibility into the code-behind, good luck with testing that.  Your lack of cohesion goes up, your tightness of coupling goes up, extensibility drops and testability drops.  Its a serious design flaw to do that, so just don't.  I could send you to probably 100 different sites that talk about this if I google it, but I'll leave you to do it.

If anybody has any ideas to the contrary regarding placing controller design into code-behind, I'd love to discuss the topic.  Like I said, I've refocused on MVP lately because of the new project and am loving all the new ideas I have been finding regarding designing MVP for mocking, so I'm all into talking about ideas right now.

Once we are done, I'm going to share what we came up with as an overall MVP architecture on here, but that's probably a few weeks away.

This entry was posted in .Net Development, OOP, Patterns and Practices, TDD. Bookmark the permalink. Follow any comments here with the RSS feed for this post.

18 Responses to Controller != code-behind

  1. Tom says:

    foobar said:
    “Of course code-behind can act as a controller. ”

    Well, that is a matter of terminology, and who you think is the owner of the word controller.
    I would say Larman is definitely a candidate, considering his best-selling book which are defining the GRASP patterns (including Controller).

    I think it is a good thing to be more explicit about what kind of controller definition you are talking about, rather than just saying Controller.
    The “GRASP Controller” is defined as “the First Object Beyond UI Layer”.

    Using this GRASP definition of a Controller (together with the definition of layers saying that each layer only depends on the next layers,
    i.e. no bidrectional dependency between layers) then you can conclude that the GRASP Controller (first object beyond UI)
    should not be in the code-behind since the code-behind is part of the view with direct access (dependency) to the GUI elements on the web page.

    At the top of this page the text says “Controllers are UI agnostic and have no knowledge of System.Web at all in Asp.Net applications.”
    That statement indicates that the authour is actually talking about the GRASP Controller.

    I would like to encourage people to be more specific about what controller they are refering to rather than just saying Controller.
    Here are four existing controllers:

    GRASP Controller
    http://davidhayden.com/blog/dave/archive/2004/11/28/648.aspx

    Front Controller
    http://msdn2.microsoft.com/en-us/library/ms978723.aspx
    http://www.corej2eepatterns.com/Patterns2ndEd/FrontController.htm

    Page Controller
    http://msdn2.microsoft.com/en-us/library/ms978764.aspx

    Application Controller
    http://www.corej2eepatterns.com/Patterns2ndEd/ApplicationController.htm

  2. rlewallen says:

    Front contoller is something I’ve toyed with implementing, using MonoRail as a framework for doing the handling, but I’m still up in the air on what the final implementation will result in. I have read that article in the past though Olivier. The message of the post was really about testablility and extensibility, which is lacking in a code-behind based controller pattern.

  3. Olivier Van Hege says:

    Maybe intereseting for you to look at what the “Patterns & Practices” team had to say about it (http://msdn2.microsoft.com/en-us/library/ms998516.aspx) some years ago.

    Their simple implementation also uses the code-behind file as the controler (without and with observer in the middle). But they explore two more evolved solutions, the Page Controller and Front Controler.

    Please let us know what you think about it…

    Kind regards,
    Olivier

  4. Dom says:

    Eric,

    Great idea holding a state indicator in the view, then using pre-render to test the view for state after all the events have fired.

    I was getting tied in knots with state management with MVP last time I tried it – between passing IDs around, holding state between postbacks, and passing in details for defaults etc.

    I’ll try what you have suggested here on my next project.

    Previously I had been raising events back from the view where the views were to be reusable, or having the views implement an interface otherwise. It sounds like you don’t have any communication pushed from the view to the presenter – rather the presenter pulls all the information it needs from the view. Great stuff.

    Will be interested to look into MonoRail also.

  5. Andy,

    I think you may have read more in my comment than I intended to say. I’m somewhat familiar with Castle and have just spent a few minutes looking at Igloo (via your blog / ayende). My current implementation of MVP very directly ties the view to the presenter (view is defined by an IView interface, Presenter knows about IView, IView knows about Presenter).

    My dependency injection tool is also very simplistic. As an example, I can write code as follows:

    DepCon.RegisterType();
    MyObject obj = (MyObject)DepCon.GetDependency
    ();

    this registers the MyObject type as the dependency to inject whenever something needs an object of the IMyInterface type.

    I can also register specific instances:

    MyObject obj = new MyObject();
    DepCon.RegisterInstanct(obj);
    MyObject obj = (MyObject)DepCon.GetDependency
    ();

    this code ensures that the one registered instance of MyObject (the ‘obj’ parameter) is the only instance that is ever returned, rather than returning a new instance every time one is requested.

    My implementation of these two different registration types is done via an IDependencyRegistration interface and an IDependencyActivation interface. I’ve also provided a direct DepCon.Register(IDependencyRegistration, IDependencyActivation) method to allow for other custom registrars and activators.

    (there are other features and interfaces for flexibility as well)

    The end result is a very simple DI tool that is highly flexible, meeting my team’s current needs.

    If anyone is interested in seeing my DI tool, please email me: derick.bailey (a.t.) mclaneat-dot-com.

  6. foobar says:

    Wow. Um. Of course code-behind can act as a controller. It’s just not very good at it, since code-behind also needs to deal with other responsibilities besides controller responsibilities.

    It’s not an ideal choice, probably the worst choice, but to say that it can NEVER be a controller is not correct.

    And as you said, using it as a controller violates encapsulation to a great degree. It also hinders testing.

  7. Eric Bergemann says:

    Jeremy,
    I definitely know what you are talking about with the event model “causing wrinkles” in ASP.NET.

    My team has been putting together a decent MVP layout in ASP.NET. I am not sure if someone else has blogged about a layout similar to this but here is a summary of how we have set up the more complex relation between the view and the presenter in ASP.NET:

    All of the elements in our view are in a View Control that implements an interface.

    Whenever the pages Page_Load event is fired the Presenter object is created and is passed the view control.

    Whenever an event in the view is raised the view control will update itself to be in a new state such that the presenter can easily figure out what to fill the view with based on the views state.

    After all of the control events have been handled then the Presenter object will be used by the page to fill the view control during the pages PreRender event.

    Because the presenter doesn’t really know anything about the view apart from the fact that it implements an interface has values and has some states we have an easily testable Presenter object.

    I guess anyway you hit it you are going to have to dance around the annoying event model in ASP.NET but I think this setup has taken out a decent amount of the frustration.

    Once you have a good layout up top of the MVP design then I think the lower level ActiveRecords and IoC stuff will come natural and could be designed to your liking.

    -Eric Bergemann
    ebbergemann@yahoo.com

  8. Derick I’d be interested in hearing those experinces and those of building a DI. It may very well be that you have created something along the lines of Castle Igloo which seems a common approach at adapting webforms to MVC. I know your using MVP so some differences but I suspect common ground. I would be interested in hearing how you are dealing with Context in your presenter, are you using DI to deal with that or mocking it using a IContext (MonoRail style) approach?

  9. Shane: I misunderstood, previously. You are correct in that it’s difficult to find good info on MVP and ASP.NET.

    All: I’m honestly confused on all of the statements about ASP.NET + MVP = hackish. Perhaps it’s because my team and I have only been working with MVP for 3 or 4 projects, now. What are the hacky implementation issues? How does the abstraction become leaky?

    In my experience, so far, the MVP setup that I write has been zero difference between Winforms, PocketPC WinForms, and WebForms. (I’ve even used MVP to create WebServices with the actual web service class being the view, which I believe does become very hacky).

    When I create a view interface and code my presenter / unit tests, I don’t care about the implementation of the view. I’m coding the app to function appropriately, despite the UI being implemented. When I do get to the actual UI view implementation in ASP.NET and I am faced with the session / state management issues that are presented, I ensure that only my specific view implementation knows about these issues. I’ve never had an WebForm session/state, event model, or other ASP.NET specific issue leak into my presenter or view interface.

    Perhaps my understanding of what everyone is calling ‘hacky’ is incorrect. Are you refering to the general ASP.NET session/state management? If so, then you should be making the statement that ASP.NET is hacky, period, not just with MVP.

    I’m hoping I can find some time soon to create a quick example and post on my blog. I’d like to get feedback from this group of commenters concerning my questions.

  10. Doug Mayer says:

    I also agree that MVP in ASP.NET certainly leaves a lot to be desired, but I don’t really feel MonoRail is a much better solution. It certainly captures the MVP part, but not being able to leverage the use of WebForm controls (most of which now render valid markup) isn’t something I’m going to be prepared to give up anytime soon. Don’t we have any choices that will give us the best of both the MVP and WebForm controls worlds??

  11. rlewallen says:

    Jeremy/Andy,

    I agree that MVP in Asp.net is a hack. That’s why I’ve been looking around at new ideas and tools to see what the new approaches to this is lately. I’ve never been happy with MVP in webforms before when implemented, so I was hoping there was something new and fresh out there to alleviate the issues. Sounds like MonoRail is something I need to dig into deeper today. I’ve done nothing more than read up on it over the last year or so.

  12. Derick: I actually said that there isn’t any information on good OO/TDD in ASP.Net. The 4 responses here contain more details then I’ve seen in all my searching on Google. I think the problem is the more of just a mass of averages problem. So many people out there (Microsoft especially) only talk about the Microsoft way of coding ASP.Net (EVERYTHING in your code behind) that any discussions that do occur about the other way of doing things (or as I like to call it.. the better way) get lost in all the noise.

    I don’t know what the solution is.. hopefully more people will take the time to discuss and record their experiences and show others little chunks of what they’ve done.

  13. jmiller says:

    I’d concur with Andy. I haven’t used MonoRail firsthand, but I can tell you that making ASP.Net try to follow the Model View Presenter pattern is hacky. MVP is based on stateful UI views, and even though WebForms tries to make a web page feel like a stateful form, the abstraction leaks badly. The eventing pipeline causes some wrinkles as well. For web development, I think MonoRail or something conceptually similar will end up being the best way to go.

    MVP/Supervising Controller/Passive View does work very well for WinForms, but you most certainly do not have to use the CAB to take advantage of that pattern. You will want an IoC/DI tool for wiring an MVP WinForms client together.

  14. I completely agree with your thoughts, Raymond. Codebehind is 100% View implementation, nothing else.

    We have based our implementation of MVP on this article: http://www.codeproject.com/useritems/ModelViewPresenter.asp – we don’t do the “IsPostback” bit in the presenter, though.

    Our standard layout include the UI project (web or winforms), an ObjectModel project (containing 3 logical layers: Entity, Bussiness Logic, Data Access), an MVP project (containing the Presenter classes and View interfaces), an MVP.UnitTests project (containing the MVP unit tests and mock objects for them), and an ObjectModel.UnitTests project (containing unit tests for the object model and the mock objects for them). We use a custom DependencyInjection tool, due to the high complexity of tools such as Spring.NET and StructureMap.

    Shane – I’d be interested in hearing your thoughts on how ASP.NET doesn’t have any good OO/TDD … My team is currently implementing MVP and TDD for various projects, including ASP.NET and PocketPC. Our architecture, design, process, and code is no different for either one of these. We use 100% OOP and are making rapid progress into TDD with MVP, Dependency Injection, etc.

  15. I’ve posted a couple of times about MVC\MVP in webforms (I’d rather we get away from mucking asp.net with the webfrom tag when in really its webforms that is bad boy and not asp.net which is a great framework that with a few tweaks ‘UNSEAL CONTEXT !’ will be even better for patterns).

    http://weblogs.asp.net/astopford/archive/tags/Patterns/default.aspx

    I second Aaron’s suggestion about Castle and using MonoRail\Windsor. To double the abstraction if you get sick of XML config in NHibernate then Castles ActiveRecord will be of interest too.

    Hacking webforms to a pattern mostly just turns it into a mess because of the couple of code behind to view, the WCSF is an adaption of the presenter pattern so it fits webforms and not the other way around and just feels hacky. However for future ref I do recommend you check out another Castle project called Igloo.

    http://weblogs.asp.net/astopford/archive/2007/01/28/castle-igloo.aspx

    The final point about webforms is that in the smalltalk sense it actually meets the MVC pattern. However in testability terms its wrong so you always look to uncouple the view and controller/presenter.

  16. Aaron Jensen says:

    About a year ago we were in your exact position. Here’s a quick rundown of our architecture decisions and changes:
    1. Spring.NET for DI, NHibernate for ORM, regular aspx/codebehind for view.

    2. Got sick of lack of testability in asp so thinned out the codebehinds and started using more testable presenters. The pages implemented a view interface, the presenters talked to that interface (fully mockable and testable)

    3. Got sick of annoying view state, badly html’d default controls, heavy obnoxious markup, etc, so switched to MonoRail for our view engine and started converting pages over to that.

    4. Got sick of xml configuration for our container so switched from Spring.NET to Castle Windsor.

    All in all, we’re now very pleased with the technologies we’ve settled on. MonoRail as a view engine is awesome, so light and easy, I love it… and we’ve done some fun things (that you can read about in our blog). Anyways, that’s a whirlwind tour of our last year. Maybe I’ll post some more detail on our blog later.

  17. I’m definitely looking forward to seeing what you come up with. There is a decided lack of information regarding bringing the OO/TDD world to the web. And with people making web apps that are more and more complex we definitely need to get some good information together.

  18. This type of thinking is something I’ve run into as well. If a .NET developer has even heard of MVC they think the current codebehind model is a perfect example of it.

    It’s even clear that Microsoft doesn’t encourage putting controller logic in the codebehind files as they don’t allow you to create Unit Tests in Team System for any methods which are part of a Page class.

Leave a Reply