2011-08-04 61 views
0

我目前正在開發一套MVC3 web應用程序,這些應用程序有許多共同之處,但是作爲單獨的軟件包進行部署。一個例外是爲每個安裝部署的管理應用程序。他們還共享一個數據庫和一組共同實體。MVC3控制器和視圖的可重用性

最近增加包括認證(自定義窗體身份驗證),自動菜單建築(使用控制器動作屬性)和其他一些屏幕。我遇到的問題是我必須創建重複的控制器和視圖。

最好的例子是身份驗證位。每個應用程序現在都有一個帳戶控制器和身份驗證視圖,它們是彼此的副本。隨着添加更多應用程序,您可以看到它如何迅速成爲維護噩夢。另一個例子是每個呈現菜單的應用程序中的共享視圖(通常通過Html.Action調用)。這也需要一個在每個應用程序中看起來完全一樣的控制器。

我還是設法抽象的認證和菜單建設的實施細則,被稱爲XXX.Core.Mvc共享的項目,也有共同的HtmlHelper擴展和特定的MVC Web什麼。所以現在應用程序中所有重複的視圖和控制器都充當代理。

我正在尋找如何擺脫這些所謂的普通視圖和控制器將駐留在一個共享的項目,他們可以被引用的良好格局/調用。有沒有人做過這樣的事情?你能推薦任何好的文章或例子嗎?

例如你怎麼點它返回一個視圖的ActionResult在不同的項目或共享路徑視圖控制器動作?如何將示例/帳戶/身份驗證路由到不同項目中的控制器?一種方法的部署含義是什麼?

+0

[This Post](http://blogs.msdn.com/b/webdevtools/archive/2011/01/20/how-to-get-razor-intellisense-for-model-in-a-class- library-project.aspx)看起來很有用。試圖實現現在具有可重用的自定義錯誤。 –

回答

0

我試了兩件事。在每種情況下,通用控制器和視圖都位於單獨的組件中。爲了證明概念,我實現了通用的應用程序錯誤處理所以在我的終點MVC3應用,實現的Global.asax:

protected void Application_Error() 
{ 
    ApplicationErrorHandler.Get().Handle(Server, new HttpResponseWrapper(Response), new HttpContextWrapper(Context)); 
} 

當應用程序錯誤處理程序在單獨的程序執行:

public class ApplicationErrorHandler 
{ 
    public static ApplicationErrorHandler Get() 
    { 
     return new ApplicationErrorHandler(); 
    } 

    public void Handle(HttpServerUtility server, HttpResponseBase response, HttpContextBase context) 
    { 
     var exception = server.GetLastError(); 
     var httpException = exception as HttpException; 
     response.Clear(); 
     server.ClearError(); 
     var routeData = new RouteData(); 
     routeData.Values["controller"] = "Errors"; 
     routeData.Values["action"] = "Http500"; 
     routeData.Values["exception"] = exception; 
     response.StatusCode = 500; 
     if (httpException != null) 
     { 
      response.StatusCode = httpException.GetHttpCode(); 
      switch (response.StatusCode) 
      { 
       case 403: 
        routeData.Values["action"] = "Http403"; 
        break; 
       case 404: 
        routeData.Values["action"] = "Http404"; 
        break; 
      } 
     } 
     IController errorsController = new ErrorsController(); 
     var rc = new RequestContext(context, routeData); 
     errorsController.Execute(rc); 
    } 
} 

在這同一組件控制器文件夾所在的ErrorsController和視圖\錯誤包含所需的3個視圖; Http403.cshtml,Http404.cshtml和Http405.cshtml。所以結構與您的正常Mvc3項目相同。但是,爲了獲得@model支持和intelisense工作,您還需要web.config - 常規項目中Views的文件副本,並放置在此獨立程序集中的視圖下。

當說在我們的應用程序出現應用程序錯誤(HTTP狀態500 - 內部服務器錯誤)的ErrorsController被執行,且在這種情況下使用將是Http500.cshtml的圖。路徑看着將是:

  • 〜\查看\錯誤\ Http500.cshtml
  • 〜\查看\共享\ Http500.cshtml

爲了從組裝我試着提供文件兩件事情:

方法之一:實現一個的VirtualPathProvider。我不會詳細討論,但目標是將cshtml視圖嵌入資源並使用VirtualPathProvider和VirtualFile爲其提供服務。這種方法的問題是,我發現沒有可行的方法來從視圖文件夾服務器web.config,以便讓Razor評估視圖。我可以得到它來檢索文件並對其進行流式處理,但不執行它。要說明問題是什麼,請考慮Http500.cshtml:

@model Exception 
<h3>@MvcHtmlString.Create(Model.Message.Replace(Environment.NewLine, "<br />").Replace("\t", "&nbsp;&nbsp;&nbsp;&nbsp;"))</h3> 
<p>@MvcHtmlString.Create(Model.StackTrace.Replace(Environment.NewLine, "<br />").Replace("\t", "&nbsp;&nbsp;&nbsp;&nbsp;"))</p> 
<input type="hidden" name="serverError" value="true"/> 

返回的內容是文件的內容而不是評估的異常。原因是View文件夾中的web.config需要同時使用Razor。默認情況下,視圖引擎是Web表單(.aspx)。

方法二:在IIS中創建虛擬目錄。這種方法效果更好,因爲視圖不必被編譯爲資源,不需要虛擬化。所需的只是在我的最終應用程序的Views文件夾下創建虛擬目錄錯誤,並將其指向部署常見程序集的Views \ Errors的位置。

當然,它的行爲不像一個合適的插件,因爲常見的文件需要與.dll分開部署,但我並不太在意。

但是,如果有人知道如何讓虛擬文件爲Razor工作的方式,我是所有的耳朵。那麼 - 所有的眼睛真的。