ASP .NET MVC 虚拟路径提供程序
Posted
技术标签:
【中文标题】ASP .NET MVC 虚拟路径提供程序【英文标题】:ASP .NET MVC VirtualPathProvider 【发布时间】:2010-08-18 17:43:49 【问题描述】:我正在编写一个 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 添加到末尾”。
此逻辑存储在哪里,如何将其放入我的虚拟路径提供程序?
谢谢。对不起,如果我没有说清楚。
【问题讨论】:
【参考方案1】:已编辑
您需要创建一个继承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 实例添加到其中。
【讨论】:
你能说得更具体些吗?谢谢。 谢谢。以及如何从这些格式字符串中获取让我的 VirtualPathProvider 知道从哪里读取文件? 换句话说,如果我的 VirtualPathProvider 收到了对 ~/Apps/Administration/Account/LogOn 的请求,我如何使用上述信息来知道查找 D:\SomeOtherPath\Apps\Administrations\ Views\Account\LogOn.aspx? 这不应该发生。您的 VPP 是否收到任何其他请求? 我不确定你在问什么...如果我在 MVC 之前注册我的 VPP,它会收到所有请求。如果我之后注册它,MVC 会首先处理请求。另外,请注意,我要读取的源目录在实际网络应用程序的基本目录之外……特别是在一个 zip 文件中。【参考方案2】:正如上面提到的 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 中,您可以像这样注册您的视图引擎:
ViewEngines.Engines.Clear();
ViewEngines.Engines.Add(new CustomViewEngine());
【讨论】:
【参考方案3】:答案是 MVC 没有正确找到我的控制器。如果 MVC 实际上确实正确找到了您的控制器,则 VirtualPathProvider 应该处理两个请求:
带有实际请求的 URL 的初始请求(即http://.../Account/LogOn)。
在 1 中的请求之后,随后的 FileExists 检查 http://.../Views/Account/LogOn.aspx。调用 FileExists 返回 false。这实际上会重新调整 aspx 内容。
【讨论】:
在第一个之后(必须返回 false 以阻止 IIS 尝试将其作为静态文件而不是运行控制器操作) FileExists 被调用两个“~/Views/Account/LogOn.aspx " 和 "/AppName/Views/Account/LogOn.aspx" - 这两个都需要返回 true。以上是关于ASP .NET MVC 虚拟路径提供程序的主要内容,如果未能解决你的问题,请参考以下文章