2012-02-03 94 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