编辑:这部分将不工作或难以实现
你宁愿使用一个动作过滤器可以让你在执行之前操作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