編輯:這部分將不工作或難以實現
你寧願使用一個動作過濾器可以讓你在執行之前操作Result
。
特別是你需要一個結果過濾器。實施IResultFilter.onResultExecuting方法,並在那裏更改結果。特別是當您實施此方法時:
void OnResultExecuting(ResultExecutingContext filterContext)
您可以訪問ResultExecutingContext.Result Property。此屬性將包含您的視圖。如果您將其投射到System.Web.Mvc.ViewResultBase,您將可以訪問ViewName
,您將可以對其進行更改。
如果您從未實施過濾器,則此爲good hands-on-lab on the subject。在這種情況下,它實現了另一種過濾器,但它是一樣的。
作爲對OP評論的回答,ViewName
丟失和View
仍然爲空是非常正常的。 ViewName
只有在視圖返回名稱的情況下才會爲空,如下所示:return View("Index");
。而且,ViewName
只是,而不是觀點的全部路徑。所以這不是一個解決方案。因此,爲了讓這個解決方案能夠正常工作,您必須處理路線數據,控制器上下文等以查找視圖。 (關於這一點下文)。
EDIT:溶液,註冊自定義視圖引擎
當MVC必須呈現它得到從路徑數據中的信息,則控制器上下文中,視圖名稱的圖(如上面所解釋的那樣可以是空的)以及適用的慣例。
特別是,在MVC中有一個註冊視圖引擎的集合,它需要找到調用方法的視圖。視圖引擎將返回一個ViewEngineResult
,該視圖具有找到的視圖(如果找到了視圖),或返回的視圖已被非法查找的路徑列表。
因此,要修改模板路徑,您可以重寫此功能:讓原始類查找視圖,如果找到,請修改路徑。
的辦展需要採取論文步驟:
- 繼承您正在使用的視圖引擎(我sampel代碼繼承了Razor視圖引擎)
- 註冊您的VIE引擎,所以,它的查詢原來的視圖引擎之前(在我的示例代碼中,我只需清除註冊引擎列表,並註冊礦原始列表包括剃鬚刀和Web表單視圖引擎。)
這是繼承的視圖引擎代碼:
public class CustomRazorViewEngine : FixedRazorViewEngine
{
public override ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName, bool useCache)
{
ViewEngineResult result
= base.FindView(controllerContext, viewName, masterName, useCache);
if (result.View != null)
{
// Modify here !!
}
return result;
}
public override ViewEngineResult FindPartialView(ControllerContext controllerContext, string partialViewName, bool useCache)
{
ViewEngineResult result
= base.FindPartialView(controllerContext, partialViewName, useCache);
if (result.View != null)
{
// Modify here !!
}
return result;
}
static readonly PropertyInfo ViewPathProp
= typeof(RazorView).GetProperty("ViewPath");
public void SetViewPath(RazorView view, string path)
{
ViewPathProp.SetValue(view, path);
}
}
注1:在您閱讀// Modify here !!
可以修改result.View
的路徑屬性。投它到RazorView
:(result.View as RazorView).ViewPath
。由於ViewPath
設置程序受保護,因此需要使用反射設置它:您可以使用SetViewPath
方法。
注意2:正如你所看到的,我不是繼承RazorViewEngine
而是FixedRazorViewEngine
。如果你在MSDN中喜歡這個類,你將不會得到結果,但是如果你查看註冊視圖引擎列表的原始內容,你會發現這個類。我認爲這取決於項目中已安裝的軟件包,我認爲它解決了MVC4中的錯誤。如果你不Microsoft.Web.Mvc
命名空間FINF它,繼承原RazorViewEngined
注3:視圖被發現後,該視圖引擎執行它,使用ViewEngineResult
,所以,如果你改變它,這將是與新的視覺路徑執行
最後,您需要更改註冊引擎的列表,在global.asax
應用程序啓動的事件,就像這樣:
protected void Application_Start()
{
// Original content:
AreaRegistration.RegisterAllAreas();
WebApiConfig.Register(GlobalConfiguration.Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
// Added content:
ViewEngines.Engines.Clear();
ViewEngines.Engines.Add(new CustomRazorViewEngine());
}
注:竟被它如果您在App_Start
文件夾中創建了ViewEngineConfig
類,並且調用此類的靜態方法,就像使用其他所有配置完成一樣。
我喜歡這種方法的外觀,但是當我嘗試它時,ViewResultBase.View和ViewResultBase.ViewName屬性總是分別爲空和「」。有什麼建議麼? – Neilski
哎呀!你是對的。只有當你返回一個帶有提供的視圖的視圖時,'ViewName'纔可用,就像'return View(「index」)'。如果不是,註冊視圖引擎之一負責查找視圖。 MVC在每個'IViewEngine'中調用'FindView'直到找到視圖。所以,我們必須找到另一個解決這個問題的方法。也許註冊自定義視圖引擎將是解決方案。讓我試試 – JotaBe
謝謝JotaBe竭盡所能,花時間詳細回答我的問題 - 非常感謝。 – Neilski