March 2008 - Posts

MVC: Intercepting Controller and HandleUnknownException

One of the recent videos on ASP.NET MVC covers the Hands On Labs from Mix. Scott Hanselman runs through a lab called the CustomControllerFactory, demonstrating how to build an intercepting controller.

Having followed the lab and tried the code I was left dazed and confused, and I wasn't the only one. Life would have been easier if the code from the labs were available, but I couldn't find it anywhere.

There seem to be two sources of confusion:

  • The video doesn't mention a vital addition to the Global.asax.cs file to change the controller factory
  • HandleUnknownAction ends up handling all actions

Getting the Lab Code Working 

Add a line to Application_Start (in Global.asax.cs) to set the framework to use the InterceptingControllerFactory instead of the DefaultControllerFactory:

Global.asax.cs changes

With this line set, any controllers instanciated will be InterceptionControllers. Without it, the default controller factory is used and the interception classes will be completely ignored.

Catching Unknown Actions

Once the lab code is working, you'll soon notice that HandleUnknownAction is catching every single action.

This happens because the InterceptionController never has any actions. It's a wrapper around a controller of the type specified in the URL (the controller with actions), but the InterceptionController itself doesn't have any actions, so every action will trigger the HandleUnknownAction method.

The best way to get your head round this is to download the MVC code from CodePlex, add the project to your solution and reference it directly. It's a great way to learn more about how the MVC framework does its stuff: in our example, the ProcessRequest method of the MVCHandler object creates a controller using our custom controller factory, so ProcessRequest is working with an InterceptionController.

ProcessRequest in the MVCHandler class

When the Execute method of the InterceptionController is called, it calls InvokeAction, which checks the actions defined on the controller. InterceptionController has none, so Execute calls HandleUnknownAction and our override fires. In the video Scott uses the override to check the actionName value and decide whether or not the controller should continue.

Base Class 

If you're trying to catch only unknown actions then an alternative way is to define a base controller class, inheriting from controller, which overrides HandleUnknownAction:

Now all of your controllers can inherit from this base controller:

The controller created in ProcessRequest will now be of the type specified in the URL and will have actions defined, so HandleUnknownAction will only fire when there really is an unknown action - there is no need to filter on the actionName anymore.

Msg 7391 - OLE DB provider SQLOLEDB was unable to begin a distributed transaction

This error occurred when running queries joining to a linked server, when the linked server was upgraded from Windows 2000 Windows Server 2003 SP2.

Server: Msg 7391, Level 16, State 1, Line 1
The operation could not be performed because OLE DB provider "%ls" for linked server "%ls" was unable to begin a distributed transaction.

Some common causes of the error are described on MSDN although this second article actually provided the solution we needed.

In our case the problem turned out to be that Windows Server 2003 has DTC network access disabled by default. Turning it on is pretty straightforward but stops the SQL Server service and can require the installation media.

The Microsoft SQL Server Support Blog has a post describing DTC settings in more detail, but we found that the default setup worked once network access had been enabled.

Posted 01 March 2008 11:58 AM by jonsayce | no comments
Filed under: