C# ASP.NET MVC-VirtualPathProvider不与本地IIS一起工作
我正在尝试建立一个MVC网站,其中一些视图来自数据库。我已经开始使用VirtualFile和VirtualPathProviders实现所有的逻辑,并且在IISExpress上一切都很好。。。切换到本地IIS时出现问题。虚拟文件正在被找到,但什么也没发生,我得到404错误。我假设这是IIS期望该文件实际存在,但我不知道如何使它在不存在时工作 我使用以下示例进行测试: DynamicPages.csC# ASP.NET MVC-VirtualPathProvider不与本地IIS一起工作,c#,asp.net,asp.net-mvc,iis,virtualpathprovider,C#,Asp.net,Asp.net Mvc,Iis,Virtualpathprovider,我正在尝试建立一个MVC网站,其中一些视图来自数据库。我已经开始使用VirtualFile和VirtualPathProviders实现所有的逻辑,并且在IISExpress上一切都很好。。。切换到本地IIS时出现问题。虚拟文件正在被找到,但什么也没发生,我得到404错误。我假设这是IIS期望该文件实际存在,但我不知道如何使它在不存在时工作 我使用以下示例进行测试: DynamicPages.cs public class Page { public string Name { get;
public class Page
{
public string Name { get; set; }
public string UrlName { get; set; }
public string View { get; set; }
}
public class PageService
{
private List<Page> pages;
public PageService()
{
pages = new List<Page>();
pages.Add(new Page() { Name = "test2", UrlName = "test2.cshtml", View = "test2" });
pages.Add(new Page() { Name = "test3", UrlName = "test3.cshtml", View = "test3" });
}
public List<Page> GetAllPages()
{
return pages;
}
}
public class PageVirtualFile : VirtualFile
{
private string data;
public PageVirtualFile(string virtualPath, string data)
: base(virtualPath)
{
this.data = data;
}
public bool Exists { get { return true; } }
public override System.IO.Stream Open()
{
byte[] byteArray = Encoding.UTF8.GetBytes(data);
MemoryStream stream = new MemoryStream(byteArray);
return stream;
}
}
public class CmsRouteHandler : IRouteHandler
{
public class CmsVirtualPathProvider : VirtualPathProvider
{
public IEnumerable<Page> pages
{
get
{
return (new PageService()).GetAllPages();
}
}
public override bool FileExists(string virtualPath)
{
if (IsVirtualPath(virtualPath))
{
if (FindPage(virtualPath) != null)
{
PageVirtualFile file = (PageVirtualFile)GetFile(virtualPath);
return file.Exists;
}
}
return Previous.FileExists(virtualPath);
}
public override VirtualFile GetFile(string virtualPath)
{
if (IsVirtualPath(virtualPath))
{
Page oPage = FindPage(virtualPath);
if (oPage != null)
return new PageVirtualFile(virtualPath, oPage.View);
}
return Previous.GetFile(virtualPath);
}
public override System.Web.Caching.CacheDependency GetCacheDependency(string virtualPath, System.Collections.IEnumerable virtualPathDependencies, DateTime utcStart)
{
if (IsVirtualPath(virtualPath))
return null;
return Previous.GetCacheDependency(virtualPath, virtualPathDependencies, utcStart);
}
public override string GetFileHash(string virtualPath, System.Collections.IEnumerable virtualPathDependencies)
{
if (IsVirtualPath(virtualPath))
return Guid.NewGuid().ToString();
return Previous.GetFileHash(virtualPath, virtualPathDependencies);
}
private Page FindPage(string virtualPath)
{
string VirtualName = VirtualPathUtility.GetFileName(virtualPath).ToLower();
if (pages != null)
{
Page oPage = pages.SingleOrDefault(page => string.Equals(page.UrlName, VirtualName, StringComparison.InvariantCultureIgnoreCase));
return oPage;
}
else
return null;
}
private bool IsVirtualPath(string virtualPath)
{
string Path = (VirtualPathUtility.GetDirectory(virtualPath) != "~/") ? VirtualPathUtility.RemoveTrailingSlash(VirtualPathUtility.GetDirectory(virtualPath)) : VirtualPathUtility.GetDirectory(virtualPath);
if (Path.StartsWith("/Views/_Cms", StringComparison.InvariantCultureIgnoreCase) || Path.StartsWith("~/Views/_Cms", StringComparison.InvariantCultureIgnoreCase))
return true;
else
return false;
}
}
public IHttpHandler GetHttpHandler(RequestContext requestContext)
{
return new CmsHandler(requestContext);
}
class CmsHandler : MvcHandler
{
public CmsHandler(RequestContext requestContext)
: base(requestContext)
{
}
protected override IAsyncResult BeginProcessRequest(HttpContext httpContext, AsyncCallback callback, object state)
{
return base.BeginProcessRequest(httpContext, callback, state);
}
protected override IAsyncResult BeginProcessRequest(HttpContextBase httpContext, AsyncCallback callback, object state)
{
try
{
var vpp = new CmsVirtualPathProvider();
var requestContext = ((MvcHandler)httpContext.Handler).RequestContext;
string path = requestContext.HttpContext.Request.Url.AbsolutePath;
if (path != null)
{
IEnumerable<Page> pages = vpp.pages;
if (pages != null)
{
Page oPage = pages.SingleOrDefault(page => string.Equals((requestContext.HttpContext.Request.ApplicationPath + "/").Replace("//","/") + page.Name, path, StringComparison.InvariantCultureIgnoreCase)); // Select the page matching our requested path (if any)
if (oPage != null)
{
requestContext.RouteData.Values["controller"] = "_Cms";
requestContext.RouteData.Values["action"] = "Index";
}
}
}
return base.BeginProcessRequest(httpContext, callback, state);
}
catch (Exception ex)
{
throw new Exception(ex.Message);
}
}
protected override void ProcessRequest(HttpContext httpContext)
{
base.ProcessRequest(httpContext);
}
}
}
如果我使用IISExpress,以下链接将起作用:
http://localhost:<port>/test2
但是,在本地IIS上,它将更改为:
http://localhost/<websitename>/test2
这将抛出404错误
有什么办法解决吗。我在谷歌上发现了很多或多或少类似的案例,但似乎都不起作用
非常感谢 @Donal可能重复-谢谢你的评论-我在问我的问题之前看过这篇文章,尝试了答案,但都没有帮助。从IISExpress切换到本地IIS不会使网站预编译,它仍然处于调试模式,所以不要认为Coskun Sunali的解决方案与本例相关,反正我尝试过,没有区别。
http://localhost/<websitename>/test2