MVC 中的 StructureMap 控制器工厂和空控制器实例

Posted

技术标签:

【中文标题】MVC 中的 StructureMap 控制器工厂和空控制器实例【英文标题】:StructureMap controller factory and null controller instance in MVC 【发布时间】:2010-10-29 18:20:30 【问题描述】:

我仍在尝试使用 StructureMap 解决问题,我遇到的问题之一是当将空控制器类型传递给它时,我的 Controller Factory 类爆炸了。这只发生在应用程序第一次构建时,之后每个后续构建都可以正常工作。即使我关闭 Visual Studio 并重新打开项目(我没有在 IIS 中运行它)。几乎就像是在进行某种缓存。这是控制器类的样子:

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;
        
    

可能出了什么问题?我需要注册每个控制器吗?谢谢。

【问题讨论】:

传递给它的空控制器是什么意思? 我的意思是控制器类型的空引用被传递给 GetControllerInstance()。我不明白的是那个空引用来自哪里。我猜 MVC 框架传递了一个空控制器实例?我最初以为它与 StructureMap 有关,但看起来并非如此。我想我可以在方法中检查 null,但我宁愿弄清楚为什么它正在做它正在做的事情。最奇怪的是,它发生在我打开项目并在重新启动后第一次在 Visual Studio 中构建它之后。之后它每次都有效。 我遇到了完全相同的问题。有人对此有解决方案吗? 我还没有弄清楚最初的问题主要是因为它很难调试。我必须重新启动机器并重新打开项目才能真正复制问题。我最终做的只是检查一个空控制器实例。它似乎没有破坏任何东西,但肯定有助于了解问题发生的原因。 【参考方案1】:

大多数浏览器在您加载站点时都在寻找 favicon.ico,并且此行为可能涉及一些缓存,这可能解释了您提到的奇怪的“仅在第一次构建时失败”的事情。

在我的情况下,这导致了控制器工厂中的空控制器类型问题。

在 global.asax 中添加 routes.IgnoreRoute("*favicon", new favicon = @"(.*/)?favicon.ico(/.*)?" ); 会使错误消失,请求应该落入文件系统,而 MVC 不会在您的代码中寻找 favico.ico 控制器。

这是Gunnar Peipman post about this的链接

我通过在我的自定义控制器工厂类中覆盖 GetControllerType(string controllerName) 并检查每个请求的 controllerName 值是什么来发现的。

【讨论】:

【参考方案2】:

我在使用 ninject 构建的控制器工厂时遇到了同样的问题。

当 MVC 无法解析路由表中的路由或路由指定不存在的控制器时,似乎 MVC 会将控制器类型传递给 null。我做了两件事来解决这个问题。您可能需要检查您的路由表并添加一个显示 404 错误页面的包罗万象的路由,如此处所述.Net MVC Routing Catchall not working

您还可以使用路由调试器检查出了什么问题。 http://haacked.com/archive/2008/03/13/url-routing-debugger.aspx

【讨论】:

另一种解决方案,扩展现有控制器工厂时:检查控制器类型是否为空,如果是,则让现有工厂处理请求,而不是自己处理。【参考方案3】:

我遇到了类似的问题。我相信这是对不存在的图像、CSS 文件等的 HTTP 请求。

我们知道 MVC 路由首先查看请求的文件是否物理存在。如果没有,则 URL 将针对配置的路由进行测试。我认为对物理上不存在的图像的请求已传递给路由引擎,并且不匹配任何路由,因此使用了 NULL。

所以要修复它,请使用FireBug 或其他需要注意的东西,并修复损坏的 HTTP 请求。在开发过程中,我使用了这样的路由来暂时绕过这些问题(我所有的资源文件夹都以下划线开头,例如_Images、_Styles 等):

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

希望这会有所帮助!

【讨论】:

【参考方案4】:

我认为您需要做的事情与默认 MVC 控制器工厂对 GetControllerInstance 方法所做的事情完全相同。如果您查看位于http://aspnetwebstack.codeplex.com/ 的 DefaultControllerFactory 的 Microsoft 源代码,您将看到当 controllerType 为 null 时 DefaultControllerFactory 会引发 404 异常。以下是我们根据这些信息执行此操作的方法:

 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;
      
 

基本上,这将确保当用户输入无效路由时,应用程序将其作为 404 错误处理。

【讨论】:

您能提供更多细节吗?我遇到了同样的问题,上面的解决方案对我不起作用(抛出 HttpException 并且我返回到调试器)。您是否覆盖了控制器工厂中的任何其他方法?你提供了构造函数吗?您是如何在 Global.asax 中注册的?即使我的自定义控制器工厂 only 调用基本实现,我仍然会收到错误。 我想通了。我只是用DebuggerNonUserCodeAttribute 装饰了GetControllerInstance,现在一切正常。

以上是关于MVC 中的 StructureMap 控制器工厂和空控制器实例的主要内容,如果未能解决你的问题,请参考以下文章

用于 ASP.NET MVC 的没有 DI 容器的控制器的构造函数参数

SpringMVC简介

2021-07-04 .NET高级班 88-ASP.NET MVC 控制器工厂实现Unity容器注入

ASP.NET MVC 4 控制器扩展

处理注入的 HttpClient

StructureMap - 能够在运行时替换程序集