MVC: VirtualPathProvider
本文关键字:VirtualPathProvider MVC | 更新日期: 2023-09-27 18:20:48
我已经在SO上搜索过了,但我没有找到解决方案,所以希望你们中的某个人能为我提供一些指导。
我希望MVC从数据库加载视图,因此我创建了一个VirtualFile和一个VirtualPathProvider。
这是来自VirtualFile:的代码
public class OxygenVirtualFile : VirtualFile
{
#region Constructors
/// <summary>
/// Create a new instance of the <see cref="OxygenVirtualFile"/>.
/// </summary>
/// <param name="virtualPath">The virtual path to the resource represented by this instance.</param>
/// <param name="body">The contents of the virtual file.</param>
public OxygenVirtualFile(string virtualPath, string body)
: base(virtualPath)
{
content = body;
}
#endregion
#region Properties
/// <summary>
/// Gets the contents of the virtual file.
/// </summary>
private readonly string content;
/// <summary>
/// A boolean that indicates wether this virtual file does exists.
/// </summary>
public bool Exists
{
get { return (content != null); }
}
#endregion
#region VirtualFile Members
/// <summary>
/// returns a read-only stream to the virtual resource.
/// </summary>
/// <returns>A read-only stream to the virtual resource.</returns>
public override Stream Open()
{
var encoding = new ASCIIEncoding();
return new MemoryStream(encoding.GetBytes(content), false);
}
#endregion
}
然后我有了提供者本身:
public class OxygenVirtualPathProvider : VirtualPathProvider
{
#region Constructors
/// <summary>
/// Create a new instance of the <see cref="OxygenVirtualPathProvider"/>.
/// </summary>
/// <param name="exludedPath">The path that should be excluded and thus not be rendered using this virtual path provider.</param>
/// <remarks>
/// If the specified path does occur somewhere in the url, the view is not rendered using this <see cref="VirtualPathProvider"/>.
/// In all the other cases, the view is rendered using this <see cref="VirtualPathProvider"/>.
/// </remarks>
public OxygenVirtualPathProvider(string exludedPath)
{
var unityContainer = DependencyResolver.Current.GetService<IUnityContainer>();
unitOfWork = unityContainer.Resolve<IUnitOfWork>();
this.exludedPath = exludedPath;
}
#endregion
#region Properties
/// <summary>
/// Gets the <see cref="IUnitOfWork"/> which is used to access the database.
/// </summary>
private readonly IUnitOfWork unitOfWork;
/// <summary>
/// Get the root path of the dynamic views.
/// </summary>
private readonly string exludedPath;
#endregion
#region Methods
/// <summary>
/// Check if the view is dynamic view.
/// </summary>
/// <param name="virtualPath">The path of the virtual view.</param>
/// <returns>True is the view is a dynamic view, false otherwise.</returns>
public bool IsDynamicView(string virtualPath)
{
// If the path which is requested does contain an excluded url, this virtual path provider will not handle this.
if (virtualPath.ToLower().Contains(exludedPath))
{ return false; }
var fileNameWithoutExtension = Path.GetFileNameWithoutExtension(virtualPath);
var viewExists = DoesViewExistInDataBase(fileNameWithoutExtension);
return viewExists && !virtualPath.ToLower().Contains(exludedPath);
}
/// <summary>
/// Verify that the requested view exists in the database.
/// </summary>
/// <param name="virtualPath">The path of the virtual view.</param>
/// <returns>True if the view exists in the database, false otherwise.</returns>
public bool DoesViewExistInDataBase(string virtualPath)
{
var fileNameWithoutExtension = Path.GetFileNameWithoutExtension(virtualPath);
return new ViewManager(unitOfWork).Exists(fileNameWithoutExtension);
}
/// <summary>
/// Gets the view from the database.
/// </summary>
/// <param name="virtualPath">The virtual path of the view to retrieve.</param>
/// <returns>A string representing the body of the view.</returns>
public String GetViewBodyFromDb(string virtualPath)
{
var fileNameWithoutExtension = Path.GetFileNameWithoutExtension(virtualPath);
return new ViewManager(unitOfWork).Get(fileNameWithoutExtension);
}
#endregion
#region VirtualPathProvider Members
/// <summary>
/// Gets a value that indicates whether a file exists in the virtual file system.
/// </summary>
/// <param name="virtualPath">The path to the virtual file.</param>
/// <returns>true if the file exists in the virtual file system; otherwise, false.</returns>
public override bool FileExists(string virtualPath)
{
return IsDynamicView(virtualPath) || base.FileExists(virtualPath);
}
/// <summary>
/// Gets a virtual file from the virtual file system.
/// </summary>
/// <param name="virtualPath">The path to the virtual file.</param>
/// <returns>A descendent of the <see cref="VirtualFile"/> class that represents a file in the virtual file system.</returns>
public override VirtualFile GetFile(string virtualPath)
{
return IsDynamicView(virtualPath) ? new OxygenVirtualFile(virtualPath, GetViewBodyFromDb(virtualPath)) : base.GetFile(virtualPath);
}
/// <summary>
/// Returns a hash of the specified virtual paths.
/// </summary>
/// <param name="virtualPath">The path to the primary virtual resource.</param>
/// <param name="virtualPathDependencies">An array of paths to other virtual resources required by the primary virtual resource.</param>
/// <returns>A hash of the specified virtual paths.</returns>
public override string GetFileHash(string virtualPath, System.Collections.IEnumerable virtualPathDependencies)
{
return base.GetFileHash(virtualPath, virtualPathDependencies);
}
/// <summary>
/// Creates a cache dependency based on the specified virtual paths.
/// </summary>
/// <param name="virtualPath">The path to the primary virtual resource.</param>
/// <param name="virtualPathDependencies">An array of paths to other resources required by the primary virtual resource.</param>
/// <param name="utcStart">The UTC time at which the virtual resources were read.</param>
/// <returns>A <see cref="CacheDependency"/> object for the specified virtual resources.</returns>
public override CacheDependency GetCacheDependency(string virtualPath, System.Collections.IEnumerable virtualPathDependencies, DateTime utcStart)
{
return Previous.GetCacheDependency(virtualPath, virtualPathDependencies, utcStart);
}
#endregion
}
为了确保我的视图正确继承,我确实返回了这个:
public string Get(string name)
{
return "@inherits System.Web.Mvc.WebViewPage<dynamic>" +
" <h2>title</h2>";
}
根据我和我在SO上发现的,这应该是可行的,但会抛出以下错误:
The view at '~/Views/Home/articles.aspx' must derive from ViewPage, ViewPage<TModel>, ViewUserControl, or ViewUserControl<TModel>.
编辑:
提供者也在global.asax文件中注册:
protected void Application_Start()
{
HostingEnvironment.RegisterVirtualPathProvider(new OxygenVirtualPathProvider("/CMS/"));
AreaRegistration.RegisterAllAreas();
RouteConfig.RegisterRoutes(RouteTable.Routes);
}
有人知道这件事吗?
好的,
我设法找到了解决办法。Mvc搜索了ASPX、ASCX、CSHTML和其他文件。
当我将VirtualPathProvider更改为仅在搜索的文件以.CSHTML结尾时加载动态文件时,错误消失了。
它现在起作用了,但我想知道我为什么会有这种行为。有谁能给我一个答案吗?