我正在编写一个IFileProvider
,打算从数据库中加载内容。我在下面改编了这段代码,作为概念验证,如果特定请求与“联系人”匹配,我只是对字符串进行硬编码。
在磁盘上,我的Pages文件夹中有一个文件contact.cshtml
。如果我不不使用新的DatabaseFileProvider
,则contact.cshtml
页面将按预期完美呈现。
当我在下面添加IFileProvider
时,对contact.cshtml
页的请求确实被覆盖-再次如预期的那样。
但是,如果尝试拦截对不存在的cshtml文件的请求,则我的代码将永远不会遭到攻击。例如,您可以在我的评论中看到,如果将工作“联系人”替换为“动态”,则该工作将无法执行。
我确定这与我将IFileProvider
与MVC的默认PhysicalFileProvider
交织在一起的方式有关。
这是我的设置:
public class DatabaseFileProvider : IFileProvider
{
public IFileInfo GetFileInfo(string subpath)
{
var result = new DatabaseFileInfo(subpath);
return result.Exists ? result as IFileInfo : new NotFoundFileInfo(subpath);
}
}
public class DatabaseFileInfo : IFileInfo
{
private string _viewPath;
private byte[] _viewContent;
private DateTimeOffset _lastModified;
private bool _exists = false;
public DatabaseFileInfo(string viewPath)
{
_viewPath = viewPath;
GetView(viewPath);
}
public bool Exists => _exists;
public bool IsDirectory => false;
public DateTimeOffset LastModified => _lastModified;
public long Length
{
get
{
using (var stream = new MemoryStream(_viewContent))
{
return stream.Length;
}
}
}
public string Name => Path.GetFileName(_viewPath);
public string PhysicalPath => null;
public Stream CreateReadStream()
{
return new MemoryStream(_viewContent);
}
private void GetView(string viewPath)
{
if (viewPath == null) return;
if (viewPath.ToLower().IndexOf("_view") != -1) return;
// PROBLEM: this only works if the file EXISTS on disk ???!!! Try switching out "contact" (works) with "dynamic" (doesn't work)
// Not even the breakpoint gets hit?
if (viewPath.ToLower().ToLower().IndexOf("contact") == -1) return;
var html = "This is NOT cshtml";
_viewContent = Encoding.UTF8.GetBytes(html);
_lastModified = DateTime.Now;
_exists = true;
}
}
`
...并在我的Startup.cs
文件中:
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.Configure<RazorViewEngineOptions>(opts => {
opts.FileProviders.Clear();
opts.FileProviders.Add(new DatabaseFileProvider());
opts.FileProviders.Add(Environment.ContentRootFileProvider);
/*
opts.FileProviders.Clear();
opts.FileProviders.Add(new CompositeFileProvider(
Environment.ContentRootFileProvider,
new DatabaseFileProvider()
));
*/
}
);
}
如您所见,我使用CompositeFileProvider
进行了第二次实现,但是问题仍然存在。我也改变了提供商的顺序。
我确定自己在做些愚蠢的事情-有人可以指出我正确的方向吗?非常感谢。
答案 0 :(得分:0)
仅供参考,我最终找到了答案,那就是确保您实现IFileProvider.GetDirectoryContents
方法。我一直无视此问题,因为我认为这只是为了方便目录浏览,但是看起来.Net Core在启动时会预先查询所有提供程序的内容,并且此方法用于准确地告诉您已经。