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 虚拟路径提供程序的主要内容,如果未能解决你的问题,请参考以下文章

如何在 ASP.Net MVC 剃须刀助手中指定图像的虚拟路径

ASP.NET (MVC) 服务图像

asp.net网站在IIS上获取虚拟路径的问题!

asp.net mvc 共享内容目录

ASP.NET 虚拟路径映射到另一个不允许的应用程序

Asp.Net MVC - 无法开始监视文件更改