all controllers get "newed up" for every request?

Oct 6, 2010 at 3:45 PM

Debugging an unrelated thing today, we had breakpoints set up in a controller's constructor.  When browsing the site, before even going to a page that would invoke that controller, we hit the breakpoint.  Strange indeed!

Investigating further, we went in and put breakpoints on "every controller" in the constructor.  It seems every page hit, no matter what controller would end up being used, caused all controllers to get instantiated.  Meaning, we hit the breakpoints in their constructors.

Further, it seems they get hit "multiple" times. 

So, to clarify, in a default routing scenario, we brows to the /Home/Index view, and we see the constructor of the UnrelatedControllerA being hit.  Along with calls to the constructors of UnrelatedControllerB, C, D, etc.  Sometimes, UnrelatedControllerA has its constructor called 3-4 times.   No other methods, obviously, jsut the constructor.

It seems to be Turbine related, in that we didn't have this problem before implementing Turbine.  Rolling back to an earlier version proves this.  Certainly other things have also been implemented in the meantime so could be the culprit, but knowing what they are, it seems highly likely that it is a Turbine thing.

While we investigate, it would be good to know - does anyone else experience this?  If it is Turbine, can it be fixed?

Oct 6, 2010 at 4:47 PM

Travis,

 

After seeing your post i put break points in my controllers as well.

I concur, even on the default page, unrelated controllers are hit, often multiple times for the single browser request.

alan

Oct 6, 2010 at 4:57 PM

Alan, thanks.  Can't wait to hear from Javier!

Oct 6, 2010 at 5:02 PM

I'm not Javier, but I can give a quick explanation and fix before I head to lunch:

It is true that each controller was being new'd up on every request, but that issue has been resolved.  I don't know if it has made its way into the latest downloadable build, but it has been addressed.

The quick way to fix this is to override the DefaultFilterFinder.  That's the guy that's doing it.  If you register an implementation of IFilterFinder, one that returns your own filters (or one that returns none), then the issue will go away.

 

 

Oct 6, 2010 at 5:27 PM

Hmm.. Thanks Darren.

I'm not sure how my implementation would "find" the correct filters for each action method.  I'm assuming these are the filters you are referring to?  Where for various Action Methods we have the filters for allowing POST/GET, Authorization, etc.  Does it affect filters on incoming parameters for model binding too?  We have one of those...

We are faced with "rip it out and wait for MVC3" or "fix it quickly."  It's going to be a real pain to rip it out, and it would give me less reason to be excited to see Javier speak in Las Vegas next month :)  Any idea when the latest stuff will be ready for release?

Thanks,

Travis

 

Coordinator
Oct 6, 2010 at 5:46 PM

Sorry Travis, Darren and Alan -- I was out on lunch and couldn't get back to you guys :)

As Darren has already pointed out, yes this is an issue and it has been addressed.  Actually, Darren was the one that found it and fixed it, so HUGE kudos to him. The changes are implemented here - http://github.com/lozanotek/mvcturbine/blob/master/src/Engine/MvcTurbine.Web/Controllers/DefaultFilterFinder.cs

I'm still in the process of putting the final touches on the v2.2 (been busy with contract work and conferences), so you can clone out yourself from the master branch and run the build\build_binaries.bat and the use the new binaries.

If you want to talk it over, hit me through Skype at lozanotek and I'll be more than happy to help you out.

Coordinator
Oct 6, 2010 at 5:53 PM

Here's the technical explanation and roadmap :)

Also, the reason for this bug is due to a side effect on how containers and Controllers are implemented. Since a Controller class is an IActionFilter, IExceptionFilter, etc. it makes into the list of filters that DefaultFilterFinder uses. When the runtime queries for IActionFilter, the container resolves everything that is IActionFilter even though it originally wasn't registered as so (All controllers are registered as IController by Turbine).


My goals for moving forward with v3 (to coincide with MVC3) is to remove this piece and lean on what MVC3 has built-in for filters and also provide a fluent registration for filters. This will allow me to explicitly call each filter rather than getting a list and then iterating it.

Oct 6, 2010 at 7:23 PM

thanks for the quick replies!

i'm a bit stuck.

i got the master branch and replaced the DefaultFilterFinder.cs with the link provided.

then i ran build\build_binaries.bat

then copied over the new MvcTurbine.Web.dll to my solution (VS 2008) wherever that dll existed and am still getting the stated behaviour.

i must be doing something wrong. any idea what i'm missing?

thanks!

Coordinator
Oct 6, 2010 at 7:32 PM

Did you clean everything out?  Unfortunately, the controllers will be called at least once since the list needs to be populated once.  Are you seeing the ctor being called more than once?

Oct 6, 2010 at 8:03 PM

my bad.

it was only on the initial request after startup.

subsequent requests are calling only the responsible controller.

sorry...

Coordinator
Oct 6, 2010 at 8:19 PM

No worries, Alan. You had me worried there for a minute! :)

Again, the reason for this is because container/actionfilter fun I explained earlier. I know it's not ideal but it fixes the issue for every request. Now that ASP.NET MVC is handling more of this at a lower level in v3, the code will be ported to leverage said pieces and thus this "patch" will no longer be needed.