StructureMap controller factory and null controller instance in MVC
Asked Answered
B

4

10

I'm still trying to figure things out with StructureMap and one of the issues i'm running into is my Controller Factory class blowing up when a null controller type is passed to it. This only happens when the application builds for the first time, after which every subsequent build works fine. Even when i shutdown Visual Studio and reopen the project (I'm not running this in IIS). It's almost like there is some sort of caching going on. This is what the controller class looks like:

public class IocControllerFactory : DefaultControllerFactory
{
    protected override IController GetControllerInstance(Type controllerType)
    {
        try
        {
            return (Controller)ObjectFactory.GetInstance(controllerType);
        }
        catch (StructureMapException)
        {
            System.Diagnostics.Debug.WriteLine(ObjectFactory.WhatDoIHave());
            throw;
        }
    }
}

What could be wrong? Do i need to have every controller registered? Thank you.

Bourges answered 29/5, 2009 at 0:44 Comment(4)
what do you mean by a null controller passed to it?Commencement
I mean a null reference of controller type being passed to the GetControllerInstance(). What i don't understand is where that null reference is coming from. I guess the MVC framework's passing a null controller instance? I initially thought it had something to do with StructureMap, but it doesn't look like the case. I guess i can put a check for a null in the method, but i'd rather figure out why it's doing what it's doing. The weirdest thing is that it happens after i open the project and build it for the first time in Visual Studio after reboot. It works every single time after that.Bourges
I am running into the EXACT same problem. Anyone have a solution to this yet?Shani
I haven't figured out what the initial problem was primarily because it was difficult to debug. I'd have to restart the machine and reopen the project to actually replicate the issue. What i ended up doing is simply checking for a null controller instance. It doesn't seem to break anything, but it would definitely help to know why the problem is occurring.Bourges
A
5

I ran into the same problem with a controller factory built around ninject.

It seems MVC will pass you null for controllertype when it can't resolve a route from the routing table or when a route specifies a none existing controller. I did two things to solve this. You might want to check your route table and add a catchall route that shows a 404 error page like described here .Net MVC Routing Catchall not working

You could also check with the routing debugger what goes wrong. http://haacked.com/archive/2008/03/13/url-routing-debugger.aspx

Actinal answered 20/6, 2009 at 13:10 Comment(1)
Another solution, when extending an existing controller factory: Check if controllerType is null, if so let the existing factory handle the request instead of handling it yourself.Tradescantia
K
8

Most browser are looking for a favicon.ico when you load a site, and there is probably some caching involved with this behavior, this might explain the odd "Only fail on the first build" thing you mentionned.

In my case this was causing the problem of the null controller type in the controller factory.

Adding a routes.IgnoreRoute("{*favicon}", new { favicon = @"(.*/)?favicon.ico(/.*)?" }); in global.asax makes the error go away, the request should fall through to the filesystem without MVC looking for a favico.ico controller in your code.

Here is a link to Gunnar Peipman post about this

I found out by overriding GetControllerType(string controllerName) in my custom controller factory class and checking what the controllerName value was for each request.

Kaufmann answered 29/10, 2009 at 19:17 Comment(0)
A
5

I ran into the same problem with a controller factory built around ninject.

It seems MVC will pass you null for controllertype when it can't resolve a route from the routing table or when a route specifies a none existing controller. I did two things to solve this. You might want to check your route table and add a catchall route that shows a 404 error page like described here .Net MVC Routing Catchall not working

You could also check with the routing debugger what goes wrong. http://haacked.com/archive/2008/03/13/url-routing-debugger.aspx

Actinal answered 20/6, 2009 at 13:10 Comment(1)
Another solution, when extending an existing controller factory: Check if controllerType is null, if so let the existing factory handle the request instead of handling it yourself.Tradescantia
R
1

I was having the similar problem. I believe it was HTTP requests for nonexistent images, CSS files, etc.

We know the MVC routing first looks to see if the requested file physically exists. If it doesn't then the URL gets tested against the configured Routes. I think the request for an image that didn't physically exist was passed to the Routing engine, and didn't match any routes, so NULL was used.

So to fix it, use FireBug or something to watch for, and fix, broken HTTP requests. During development, I used a route like this to temporarily bypass these issues (all of my resource folders start with an underscore like _Images, _Styles, etc):

routes.IgnoreRoute("_*");  // TODO: Remove before launch

Hope this helps!

Ralfston answered 17/7, 2009 at 17:7 Comment(0)
P
0

What I think you need to do is exactly the same thing that the default MVC controller factory does on the GetControllerInstance method. If you look at the Microsoft source code for DefaultControllerFactory at http://aspnetwebstack.codeplex.com/ you will see that the DefaultControllerFactory throws a 404 Exception when controllerType is null. Here is how we do it based on this information:

 public class StructureMapControllerFactory : DefaultControllerFactory
 {
      protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
      {
           if (controllerType == null)
                return base.GetControllerInstance(requestContext, controllerType);
           var controller = ObjectFactory.GetInstance(controllerType);
           return (IController)controller;
      }
 }

Basically this will ensure that, when user enters an invalid route the application handles it as a 404 error.

Pohai answered 24/10, 2012 at 12:56 Comment(2)
could you provide some more detail please? I am having the same problem and the above solution doesn't work for me (an HttpException is thrown and I am returned to the debugger). Have you overridden any other methods in your controller factory? Have you provided constructors? How have you registered it in Global.asax? Even if my custom controller factory only calls the base implementation I still get the error.Kirstiekirstin
I figured it out. I simply decorated the GetControllerInstance with the DebuggerNonUserCodeAttribute and everything works now.Kirstiekirstin

© 2022 - 2024 — McMap. All rights reserved.