Custom Controller Factory, Dependency Injection /

2020-02-18 20:39发布

问题:

I recently tried to implement dependency injection using StructureMap. I managed to follow the example all the way but I'm encountering a thrown exception every time I try to run the application. Here's some code snippets from my controller factory.

public class StructureMapControllerFactory : DefaultControllerFactory
{
    protected override IController GetControllerInstance(Type controllerType)
    {
        if (controllerType == null)
            throw new ArgumentNullException("controllerType");

        return ObjectFactory.GetInstance(controllerType) as Controller;
    }
}

My Global.asax calls a static BootStrapper class which registers all my dependencies but it looks like the StructureMapControllerFactory's GetControllerInstance is getting called twice. The first time it's called, a proper controllerType is passed in but it's always null on the second calling.

The first time GetControllerInstance is called, the type is set to HomeController which is correct. The code the fires in HomeController and it returns the View(). On the return of the View(), the Page_Load event is called on the aspx file. After stepping through that, it arrives at a line:

httpHandler.ProcessRequest(HttpContext.Current);

That's where the GetControllerInstance is called the second time.

Here's my Global.asax bits which may be relevant:

   protected void Application_Start()
    {
        RegisterRoutes(RouteTable.Routes);

        Bootstrapper.ConfigureStructureMap();

        ControllerBuilder.Current.SetControllerFactory(new StructureMapControllerFactory());
    }

I'm very keen to get dependency injection working and would be most appreciative if anyone can help me out. :)

回答1:

UPDATE The reason this is happening is that when an image is specified in a css file, and that image is missing the routing framework tries to map the url to a controller. Ignoring the routes as listed below will prevent the error from happening, but I decided not to implement it because it's a nice way of being notified that you have a missing resource.

You can see a detailed explanation along with examples of setting up dependency injection using Structure Map here.

I was having the same issue and I think I figured it out. For whatever reason whenever you try to provide your own Controller Factory you need to add a couple of additional IgnoreRoute definitions. The first thing I would do is add this line to your GetControllerInstance method:

if(controllerType == null)
    return base.GetControllerInstance(controllerType)

This will at least give you more information in the error message as to what the request is that is causing the controllerType to be null. In my particular case I had a background image in my css file set like this:

background: url(img/logo.gif);

So what happens is the routing is looking for a controller called "img" and an action that takes logo.gif or something along those lines. That's obviously not the correct behavior.

After some digging I realized I needed to add an IgnoreRoute definition to my Global.asax file that would ignore anything in the "content" directory of my site like this:

routes.IgnoreRoute("{Content}/{*pathInfo}");

I'm still not sure why you don't need to do this with the default ControllerFactory, but nonetheless it works.

You'll probably run into the same issue with favicon.ico. Particularly if you using google crhome. You'll need to add this as well:

routes.IgnoreRoute("{*favicon}", new {favicon=@"(.*/)?favicon.ico(/.*)?"})


回答2:

I am guessing you are requesting a static file, such as a javascript file, that has not been added to your project or perhaps the reference to it has a typo. You should monitor your browsers web requests and look for web requests for that do not correctly resolve to a static file when they should. You can use firebug in FF or fiddler if you are using IE to do this.