MVC 5中的VirtualPathProvider

Dav*_*all 11 iis asp.net-mvc asp.net-mvc-routing asp.net-mvc-5

我似乎无法在asp.net MVC 5中使用自定义VirtualPathProvider.

FileExists方法返回true,但不调用GetFile方法.我相信这是因为IIS接管请求并且不让.NET处理它.

我已经尝试设置RAMMFAR并创建自定义处理程序,如此解决方案/sf/answers/850605101/但仍然没有运气.我收到错误404.

我的定制提供商:

public class DbPathProvider : VirtualPathProvider
{
    public DbPathProvider() : base()
    {

    }

    private static bool IsContentPath(string virtualPath)
    {
        var checkPath = VirtualPathUtility.ToAppRelative(virtualPath);
        return checkPath.StartsWith("~/CMS/", StringComparison.InvariantCultureIgnoreCase);
    }

    public override bool FileExists(string virtualPath)
    {
        return IsContentPath(virtualPath) || base.FileExists(virtualPath);
    }

    public override VirtualFile GetFile(string virtualPath)
    {
        return IsContentPath(virtualPath) ? new DbVirtualFile(virtualPath) : base.GetFile(virtualPath);
    }

    public override CacheDependency GetCacheDependency(string virtualPath, IEnumerable virtualPathDependencies, DateTime utcStart)
    {
        return null;

    }

    public override String GetFileHash(String virtualPath, IEnumerable virtualPathDependencies)
    {
        return Guid.NewGuid().ToString();
    }
}
Run Code Online (Sandbox Code Playgroud)

我的自定义虚拟文件:

public class DbVirtualFile : VirtualFile
{
    public DbVirtualFile(string path): base(path)
    {

    }

    public override System.IO.Stream Open()
    {
        string testPage = "This is a test!";
        return new System.IO.MemoryStream(System.Text.ASCIIEncoding.ASCII.GetBytes(testPage));
    }
}
Run Code Online (Sandbox Code Playgroud)

web.config处理程序我试过使用,没有成功.它目前给出错误500:

<system.webServer>
<modules runAllManagedModulesForAllRequests="true">
  <remove name="FormsAuthenticationModule" />
</modules>

<handlers>
  <add name="ApiURIs-ISAPI-Integrated-4.0"
 path="/CMS/*"
 verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS"
 type="System.Web.Handlers.TransferRequestHandler"
 preCondition="runtimeVersionv4.0" />
</handlers>
Run Code Online (Sandbox Code Playgroud)

如果我尝试导航到site.com/CMS/Home/Index,则会调用FileExists方法,但奇怪的是,virtualPath参数仅接收〜/ CMS/Home.

添加断点,似乎对于url site.com/CMS/Home/Index,FileExists方法不断被重复调用.这可能会导致无限递归,从而导致内部服务器错误.

Dav*_*all 13

它实际上与IIS无关,实际上是对事件顺序的混淆.我似乎不明白路由操作方法必须返回一个视图,VirtualPathProvider将尝试解析,而不是直接转到VirtualPathProvider.

我用一个GetPage动作创建了一个名为ContentPagesController的简单控制器:

public class ContentPagesController : Controller
    {
        [HttpGet]
        public ActionResult GetPage(string pageName)
        {
            return View(pageName);
        }
    }
Run Code Online (Sandbox Code Playgroud)

然后我设置了我的虚拟页面服务路线:

routes.MapRoute(
 name: "ContentPageRoute",
 url: "CMS/{*pageName}",
 defaults: new { controller = "ContentPages", action = "GetPage" },
 constraints: new { controller = "ContentPages", action = "GetPage" }
);
Run Code Online (Sandbox Code Playgroud)

我在注册路由之前注册我的自定义VirtualPathProvider,在globals.asax.cs中.

现在假设我的数据库中有一个页面,其中包含相对url/CMS/Home/AboutUs.pageName参数将具有值Home/AboutUs,并且返回View()调用将指示VirtualPathProvider查找文件〜/ Views/ContentPages/Home/AboutUs.cshtml的变体.

它将寻找的一些变化包括:

~/Views/ContentPages/Home/AboutUs.aspx
~/Views/ContentPages/Home/AboutUs.ascx
~/Views/ContentPages/Home/AboutUs.vbhtml
Run Code Online (Sandbox Code Playgroud)

您现在需要做的就是使用数据库查找或类似方法检查传递给GetFiles方法的virtualPath.这是一个简单的方法:

private bool IsCMSPath(string virtualPath)
        {
           return virtualPath == "/Views/ContentPages/Home/AboutUs.cshtml" || 
                virtualPath == "~/Views/ContentPages/Home/AboutUs.cshtml"; 
        }

        public override bool FileExists(string virtualPath)
        {
            return IsCMSPath(virtualPath) || base.FileExists(virtualPath);
        }

        public override VirtualFile GetFile(string virtualPath)
        {
            if (IsCMSPath(virtualPath))
            {
                return new DbVirtualFile(virtualPath);
            }

            return base.GetFile(virtualPath);
        }
Run Code Online (Sandbox Code Playgroud)

将生成自定义虚拟文件并将其返回到GetFile方法中的浏览器.

最后,可以创建自定义视图引擎,以提供发送到VirtualPathProvider的不同虚拟视图路径.

希望这可以帮助.