我正在编写一个VirtualPathProvider来动态加载我的MVC视图,这些视图位于不同的目录中。我成功拦截了MVC之前的调用(在FileExists中),但在我的VirtualPathProvider中,我得到了原始的,预先路由的URL,如:
~/Apps/Administration/Account/LogOn
就个人而言,我知道MVC会寻找
~/Apps/Administration/Views/Account/LogOn.aspx
我应该从
中读取文件内容D:\SomeOtherNonWebRootDirectory\Apps\Administration\Views\Account\LogOn.aspx
但我宁愿不用硬编码逻辑来“添加名为Views的目录并将aspx添加到最后”。
这个逻辑存储在哪里,如何将其存入虚拟路径提供程序?
感谢。对不起,如果我不清楚的话。
答案 0 :(得分:4)
您需要创建一个继承WebFormViewEngine
的类并设置ViewLocationFormats
属性(继承自VirtualPathProviderViewEngine)。
默认值可以在MVC源代码中找到:
public WebFormViewEngine() {
MasterLocationFormats = new[] {
"~/Views/{1}/{0}.master",
"~/Views/Shared/{0}.master"
};
AreaMasterLocationFormats = new[] {
"~/Areas/{2}/Views/{1}/{0}.master",
"~/Areas/{2}/Views/Shared/{0}.master",
};
ViewLocationFormats = new[] {
"~/Views/{1}/{0}.aspx",
"~/Views/{1}/{0}.ascx",
"~/Views/Shared/{0}.aspx",
"~/Views/Shared/{0}.ascx"
};
AreaViewLocationFormats = new[] {
"~/Areas/{2}/Views/{1}/{0}.aspx",
"~/Areas/{2}/Views/{1}/{0}.ascx",
"~/Areas/{2}/Views/Shared/{0}.aspx",
"~/Areas/{2}/Views/Shared/{0}.ascx",
};
PartialViewLocationFormats = ViewLocationFormats;
AreaPartialViewLocationFormats = AreaViewLocationFormats;
}
然后,您应该清除ViewEngines.Engines
集合并将ViewEngine实例添加到其中。
答案 1 :(得分:0)
正如上面提到的SLaks,您需要创建自定义视图引擎并在FindView方法中添加视图查找逻辑。
public class CustomViewEngine : VirtualPathProviderViewEngine
{
public override ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName, bool useCache)
{
//Set view path
string viewPath = GetCurrentViewPath();
//Set master path (if need be)
string masterPath = GetCurrentMasterPath();
return base.FindView(controllerContext, viewPath, masterPath, useCache);
}
}
在Application_Start中,您可以像这样注册View Engine:
ViewEngines.Engines.Clear();
ViewEngines.Engines.Add(new CustomViewEngine());
答案 2 :(得分:0)
答案是MVC没有正确找到我的控制器。如果MVC实际上确实找到了你的控制器,那么VirtualPathProvider应该处理两个请求:
请求了真实网址的初始请求(即http://.../Account/LogOn)。
在1中的请求之后,后续的FileExists检查http://.../Views/Account/LogOn.aspx,返回false,调用FileExists。这实际上是返回aspx内容。