gpt4 book ai didi

asp.net-mvc - MVC 5 中的 VirtualPathProvider

转载 作者:行者123 更新时间:2023-12-01 23:31:22 25 4
gpt4 key购买 nike

我似乎无法让自定义 VirtualPathProvider 在 asp.net MVC 5 中工作。

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

我尝试设置 RAMMFAR 并创建自定义处理程序,如本解决方案 https://stackoverflow.com/a/12151501/801189 所示。但仍然没有运气。我收到错误 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();
}
}

我的自定义虚拟文件:

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));
}
}

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>

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

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

最佳答案

这实际上与 IIS 无关,而且实际上事件顺序困惑。我似乎不明白路由操作方法必须返回一个 View ,VirtualPathProvider 将尝试解析该 View ,而不是直接转到 VirtualPathProvider。

我使用单个 GetPage 操作创建一个名为 ContentPagesController 的简单 Controller :

public class ContentPagesController : Controller
{
[HttpGet]
public ActionResult GetPage(string pageName)
{
return View(pageName);
}
}

然后,我设置路由来提供虚拟页面:

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

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

现在假设我的数据库中有一个页面,其相对 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

您现在需要做的就是使用数据库查找或类似方法检查传递给 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);
}

自定义虚拟文件将在 GetFile 方法中创建并返回到浏览器。

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

希望这有帮助。

关于asp.net-mvc - MVC 5 中的 VirtualPathProvider,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24237123/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com