为什么我的控制器在没有被调用时被实例化?

时间:2013-08-09 12:02:21

标签: asp.net-mvc

以下是我遇到的症状:

我在一个地区有一个全新的空控制器:

public class JamController : Controller
{
    public JamController()
    {
        throw new Exception("Not implemented!");
    }

如果我访问http://myprojectserver.example.com:12345/urlthatdoesnotexist,则会收到以下错误:

[CompositionException: The composition produced a single composition error. The root cause is provided below. Review the CompositionException.Errors property for more detailed information.

1) Not implemented!

Resulting in: An exception occurred while trying to create an instance of type 'MyWebProject.Areas.Users.Controllers.JamController'.

Resulting in: Cannot activate part 'MyWebProject.Areas.Users.Controllers.JamController'.
Element: MyWebProject.Areas.Users.Controllers.JamController -->  MyWebProject.Areas.Users.Controllers.JamController

Resulting in: Cannot get export 'MyWebProject.Areas.Users.Controllers.JamController (ContractName="System.Web.Mvc.IController")' from part 'MyWebProject.Areas.Users.Controllers.JamController'.
Element: MyWebProject.Areas.Users.Controllers.JamController (ContractName="System.Web.Mvc.IController")
]
   System.ComponentModel.Composition.Hosting.CompositionServices.GetExportedValueFromComposedPart(ImportEngine engine, ComposablePart part, ExportDefinition definition) +55
   System.ComponentModel.Composition.Hosting.CatalogExportProvider.GetExportedValue(CatalogPart part, ExportDefinition export, Boolean isSharedPart) +78
   System.ComponentModel.Composition.Hosting.CatalogExport.GetExportedValueCore() +47
   System.ComponentModel.Composition.Primitives.Export.get_Value() +57
   System.ComponentModel.Composition.ExportServices.GetCastedExportedValue(Export export) +40
   System.ComponentModel.Composition.<>c__DisplayClassa`1.<CreateStronglyTypedLazyOfT>b__6() +39
   System.Lazy`1.CreateValue() +416
   System.Lazy`1.LazyInitValue() +382
   System.Lazy`1.get_Value() +75
   MefContrib.Web.Mvc.<>c__DisplayClass4.<GetControllerType>b__0(Lazy`1 e) +53
   System.Linq.WhereSelectEnumerableIterator`2.MoveNext() +204
   System.Collections.Generic.List`1..ctor(IEnumerable`1 collection) +381
   System.Linq.Enumerable.ToList(IEnumerable`1 source) +58
   MefContrib.Web.Mvc.CompositionControllerFactory.GetControllerType(RequestContext requestContext, String controllerName) +412
   System.Web.Mvc.DefaultControllerFactory.System.Web.Mvc.IControllerFactory.GetControllerSessionBehavior(RequestContext requestContext, String controllerName) +61
   System.Web.Mvc.MvcRouteHandler.GetSessionStateBehavior(RequestContext requestContext) +122
   System.Web.Mvc.MvcRouteHandler.GetHttpHandler(RequestContext requestContext) +33
   System.Web.Mvc.MvcRouteHandler.System.Web.Routing.IRouteHandler.GetHttpHandler(RequestContext requestContext) +10
   System.Web.Routing.UrlRoutingModule.PostResolveRequestCache(HttpContextBase context) +9709884
   System.Web.Routing.UrlRoutingModule.OnApplicationPostResolveRequestCache(Object sender, EventArgs e) +82
   System.Web.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +136
   System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +699

我的问题是“为什么?”为什么它试图实例化这个控制器呢?我在哪里查看导致这种情况的原因。我很确定在“找不到页面”上实例化每个控制器并不是预期的行为。

我不知道该去哪儿看。有人能指出我会有所帮助吗?

更新:

原来,下面的SetControllerFactory方法导致了问题:

// Tell MVC3 to use MEF as its dependency resolver.
var dependencyResolver = new CompositionDependencyResolver(catalog);
DependencyResolver.SetResolver(dependencyResolver);

// Tell MVC3 to resolve dependencies in controllers
ControllerBuilder.Current.SetControllerFactory(
    new CompositionControllerFactory(
        new CompositionControllerActivator(dependencyResolver)));

注释掉“告诉MVC3来解决控制器中的依赖关系”部分修复了我的问题,除了我要求的控制器之外没有控件实例化。幸运的是,只有在你没有使用标准的Asp.Net控制器分辨率(我们是)时才需要这样做。

2 个答案:

答案 0 :(得分:2)

这是 MefContrib.Web.Mvc 中的错误。这个程序集实现了它自己的ControllerFactory,它继承自 DefaultControllerFactory

工厂重写 GetControllerType ,我假设尝试解析除默认应用程序或其引用之外的某些位置的控制器。 GetControllerType的实现首先调用 base.GetControllerType 以查看Defaultcontroller是否可以解析它。

如果不能 - 不存在的网址就是这种情况 - 它会向MEF询问实现IController的所有导出。这将返回 IEnumerable&lt; Lazy&lt; IController&gt;&gt; ,其中每个类在bin /文件夹中实现IController(默认情况下)。

然后在IEnumerable上运行linq查询,在每个Lazy&lt; IController&gt;的Value属性上调用 GetType()。请求懒惰&lt; T&gt;的值。强制创建实例。这就是为什么bin /中的每个控制器都是为不存在的页面构建的原因。

我认为这不是一个容易解决的问题,因为无法在不创建值的情况下从Lazy&lt; T&gt; .Value获取Type实例。但是,通过从AppStart_MefContribMVC3.cs中删除使用Asp.Net注册ControllerFactory的行 - 您已经有效地停止使用MefContrib.Web.Mvc的ControllerFactory,而只是使用了Asp.Net的DefaultControllerFactory。

答案 1 :(得分:0)

原来,下面的SetControllerFactory方法导致了问题:

// Tell MVC3 to use MEF as its dependency resolver.
var dependencyResolver = new CompositionDependencyResolver(catalog);
DependencyResolver.SetResolver(dependencyResolver);

// Tell MVC3 to resolve dependencies in controllers
ControllerBuilder.Current.SetControllerFactory(
    new CompositionControllerFactory(
        new CompositionControllerActivator(dependencyResolver)));

注释掉“告诉MVC3来解决控制器中的依赖关系”部分修复了我的问题,除了我要求的控制器之外没有控件实例化。幸运的是,只有在你没有使用标准的Asp.Net控制器分辨率(我们是)时才需要这样做。