短: 对于每个请求,都会创建一个新的OWIN上下文,我希望能够针对某些资源类型或路径(图像,css,js)阻止这种情况。
展开: 在我们的应用程序启动中,我们注册了一个dbcontext创建委托,以便每个请求只创建一次dbcontext。
public virtual void Configuration(IAppBuilder app)
{
app.CreatePerOwinContext(Factory.DbContextCreateDelegate);
}
如果客户端请求样式表,则将创建OWIN上下文,因此还将创建新的dbcontext。我希望能够根本不创建OwinContext,或者至少能够阻止某些请求类型/路径执行某些“on create”回调。
或者,正如我所知,为什么(部分)“禁用”OWIN的方法会导致问题,我想听听最佳做法是什么?如何在不为每个请求创建数据库上下文的情况下提供静态文件? (这里的小说法是我们的静态文件是使用虚拟路径提供程序提供的嵌入式资源...“普通”静态文件也会出现问题。)
背景:昨天我开始注意到我们应用程序的某些部分偶尔都没有加载。有时它是单个图像,有时是整个CSS文件。经过一些调查后,我发现有些请求丢失了http 500错误,抛出的异常通常是SQL连接超时(但也有其他异常)。
虽然我们当然正在尝试修复这些例外情况。我确实认为,当客户端请求单个图像时,我们的应用程序设置数据库连接完全是胡说八道...这是单个页面请求的大约10个数据库连接???
对我而言似乎是一个明显的问题,但我昨天一直在谷歌搜索,没有找到任何接近解决方案或解决方法。我错过了什么堆栈?
编辑:我刚试过一种方法,我实际上并没有创建dbcontext而是创建了一个存根。事后看来,这显然不是这个问题的解决方案,因为OwinContext试图继续它的进程,并且当它试图使用该存根dbcontext从数据库中获取用户时将严重失败。 dbcontext不是问题,我需要完全绕过Owin ......我想......
答案 0 :(得分:11)
Microsoft.Owin.StaticFiles 救援!
我仍然想知道为什么MVC OWIN模板应用程序默认不启用它。但是对于大多数情况,在OWIN中启用静态文件只需要一行代码。
设置Owin将文件夹及其内容视为静态文件:
public virtual void Configuration(IAppBuilder app)
{
app.UseStaticFiles("/PathToYourStaticFilesFolder");
}
不幸的是,对于我来说,我们使用VirtualPathProvider的实现将大部分静态内容作为嵌入资源提供。幸运的是,这也相对容易实现,但它需要在VirtualPathProvider周围编写一个包装器来实现OWIN所需的IFileSystem和IFileInfo接口。
我最终解决方案的代码的相关部分,而不是发布整个VirtualPathProvider,因为有大量的在线示例。
VirtualPathProvider周围的包装器:
/// <summary>
/// Represents a virtual file system.
/// A wrapper around <see cref="MyCustomVirtualPathProvider"/> implementing
/// IFileSystem for use in Owin StaticFiles.
/// </summary>
public class VirtualFileSystem : IFileSystem
{
/// <summary>
/// Locate the path in the virtual path provider
/// </summary>
/// <param name="subpath">The path that identifies the file</param>
/// <param name="fileInfo">The discovered file if any</param>
/// <returns>
/// True if a file was located at the given path
/// </returns>
public bool TryGetFileInfo(string subpath, out IFileInfo fileInfo)
{
MyCustomVirtualPathProvider virtualPathProvider =
(MyCustomVirtualPathProvider) HostingEnvironment.VirtualPathProvider;
if (!virtualPathProvider.FileExists(subpath))
{
fileInfo = null;
return false;
}
try
{
EmbeddedResourceVirtualFile virtualFile =
(EmbeddedResourceVirtualFile) virtualPathProvider.GetFile(subpath);
fileInfo = new EmbeddedResourceFileInfo(virtualFile);
return true;
}
catch (InvalidCastException)
{
fileInfo = null;
return false;
}
}
/// <summary>
/// Not used in our implementation
/// </summary>
/// <param name="subpath"></param>
/// <param name="contents"></param>
/// <returns></returns>
public bool TryGetDirectoryContents(string subpath, out IEnumerable<IFileInfo> contents)
{
throw new NotImplementedException();
}
}
嵌入资源的包装器:
/// <summary>
/// Represents the file info of an embedded resource
/// </summary>
public class EmbeddedResourceFileInfo : IFileInfo
{
/// <summary>
/// Return file contents as readonly stream. Caller should dispose stream when complete.
/// </summary>
/// <returns>
/// The file stream
/// </returns>
public Stream CreateReadStream()
{
return virtualFile.Open();
}
/// <summary>
/// The length of the file in bytes, or -1 for a directory info
/// </summary>
public long Length => virtualFile.Length;
/// <summary>
/// The name of the file
/// </summary>
public string Name => virtualFile.Name;
/// <summary>
/// When the file was last modified
/// </summary>
public DateTime LastModified => virtualFile.LastModified;
/// <summary>
/// Returns null as these are virtual files
/// </summary>
public string PhysicalPath => null;
/// <summary>
/// True for the case TryGetDirectoryContents has enumerated a sub-directory
/// </summary>
public bool IsDirectory => virtualFile.IsDirectory;
private readonly EmbeddedResourceVirtualFile virtualFile;
/// <summary>
/// Construct using a <see cref="EmbeddedResourceVirtualFile"/>
/// </summary>
/// <param name="virtualFile"></param>
public EmbeddedResourceFileInfo(EmbeddedResourceVirtualFile virtualFile)
{
this.virtualFile = virtualFile;
}
}
最后,设置Owin以使用我们的虚拟文件系统:
public virtual void Configuration(IAppBuilder app)
{
var staticFilesOptions = new StaticFileOptions
{
FileSystem = new VirtualFileSystem()
};
app.UseStaticFiles(staticFilesOptions);
}