2012-02-03 93 views
1

我正在使用ASP.Net MVC 3框架,并将依赖注入集成到应用程序中。我正在尝试创建一个自定义控制器工厂。我目前遇到的最大问题是我的IControllerFactory的实现.CreateController获取传递的请求,例如css,javascript和其他内容文件,这些内容文件随后导致它作为“Scripts/html5.js”的类型抛出异常不存在。代码是继承给我的,所以请保存你对这个偶然状态的批评。下面是执行:DefaultControllerFactory如何处理内容请求

public virtual IController CreateController(RequestContext requestContext, string controllerName) 
    { 
     if (requestContext == null) 
     { 
      throw new ArgumentNullException("requestContext"); 
     } 

     if (String.IsNullOrEmpty(controllerName)) 
     { 
      throw new ArgumentException("Value cannot be null or empty", "controllerName"); 
     } 

     this.RequestContext = requestContext; 
     try 
     { 
      return container.Resolve<IController>(controllerName.ToLower()); 
     } 
     catch (Exception ex) 
     { 
      Trace.TraceError(ex.Message); 
      return innerFactory.CreateController(requestContext, controllerName); 
     } 
    } 
+0

ASP .NET MVC控制器不处理对静态文件的请求。这应该通过路由完成,它将它交给IIS。我会先看看那里。 – Yuck 2012-02-03 18:49:22

+2

请求**不存在**的静态项**传递给MVC控制器工厂。默认工厂忽略它们,但是当你覆盖它时,你也必须忽略它们。 – 2012-07-20 00:08:00

+0

您的页面链接到缺少的资源不是实际的问题吗?这会一直发生,因为漫游器和垃圾邮件发送者会尝试访问您网站上的各种文件。我认为在这种情况下的答案是不记录错误?下面的解决方案,虽然更清洁并不能解决这个问题,但我们期望您已将缺少的控制器的行为更改为404,但这可能是正确的,但可能与原始代码一样容易。\ – 2012-07-20 00:11:34

回答

1

我能够从继承来解决这个DefaultControllerFactory而不是实现完整的IControllerFactory:

public class MyControllerFactory : DefaultControllerFactory 

然后,我只需要重写GetControllerInstance方法挂钩并从我统一容器返回任何实例:

protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType) 
    { 
     IController controller = null; 
     if (controllerType == null) 
     { 
      throw new HttpException(404, String.Format("The controller for path '{0}' could not be found or it does not implement IController.", requestContext.HttpContext.Request.Path)); 
     } 

     if (!typeof(IController).IsAssignableFrom(controllerType)) 
     { 
      throw new ArgumentException(String.Format("Type requested is not a controller: {0}", controllerType.Name), "controllerType"); 
     } 

     try 
     { 
      if (this.container.IsRegistered(controllerType)) 
      { 
       controller = this.container.Resolve(controllerType) as IController; 
      } 
      else 
      { 
       controller = base.GetControllerInstance(requestContext, controllerType); 
      } 
     } 
     catch (Exception ex) 
     { 
      throw new InvalidOperationException(String.Format("Error resolving controller {0}", controllerType.Name, ex)); 
     } 

     return controller; 
    } 
+0

这对我来说似乎是一个更清洁的解决方案,因为如您所说,您不必重新实施整个工厂。但是,当我刚刚尝试过时,它不能解决问题,因为缺少静态项目的请求仍然到达,除非控制器类型现在为空,所以您将为每个缺少的静态项目获取日志消息。 – 2012-07-20 00:05:49

+0

通过使用GetControllerInstance而不是CreateController,您将失去Unity映射中名称字段的值,而必须使用该类型。例如我的映射是''并且在我的控制器工厂CreateController中,我可以使用'return _container.Resolve (controllerName);'解析控制器。这似乎更符合控制器命名约定。 – 2012-07-20 00:06:42

0

有几件事情,你可以试一下:

routes.IgnoreRoute("{file}.css"); //plus others if you have specifics 

或更好,但只是尝试

routes.RouteExistingFiles = false; 
+0

感谢你的建议,我一直在寻找一种侵入性较小的解决方案。 – doogle 2012-02-06 15:32:46

+0

也许我错过了这个观点,但是不那么有创意,那么告诉mvc不要通过内置机制路由静态内容?你希望在路由层进行处理,而不是任何获取任何控制器工厂代码的静态文件。 – 2012-02-06 15:48:14