【发布时间】:2015-01-18 03:04:53
【问题描述】:
背景
首先让我解释一下背景。我正在开发一个项目,该项目试图将使用通过 OWIN 配置的 Web API 配置的后端服务器(现在托管在 IIS 上,但将来可能会使用其他 OWIN 支持的主机)与使用 AngularJS 的前端结合。
AngularJS 前端完全是静态内容。我完全避免使用 MVC/Razor、WebForms、Bundles 等服务器端技术,以及与前端及其使用的资产有关的任何东西,而是使用 Node.js、Grunt/Gulp 等最新最好的技术. 处理 CSS 编译、捆绑、缩小等。由于我不会在这里讨论的原因,我将前端和服务器项目放在同一个项目中的不同位置(而不是直接将它们全部放在 Host 项目中(见粗略)下图)。
MyProject.sln
server
MyProject.Host
MyProject.Host.csproj
Startup.cs
(etc.)
frontend
MyProjectApp
app.js
index.html
MyProjectApp.njproj
(etc.)
所以就前端而言,我需要做的就是让我的主机为我的静态内容提供服务。在 Express.js 中,这是微不足道的。使用 OWIN,我可以使用 Microsoft.Owin.StaticFiles 中间件轻松完成此操作,而且效果很好(非常流畅)。
这是我的OwinStartup 配置:
string dir = AppDomain.CurrentDomain.RelativeSearchPath; // get executing path
string contentPath = Path.GetFullPath(Path.Combine(dir, @"../../../frontend/MyProjectApp")); // resolve nearby frontend project directory
app.UseFileServer(new FileServerOptions
{
EnableDefaultFiles = true,
FileSystem = new PhysicalFileSystem(contentPath),
RequestPath = new PathString(string.Empty) // starts at the root of the host
});
// ensure the above occur before map handler to prevent native static content handler
app.UseStageMarker(PipelineStage.MapHandler);
渔获
基本上,它只是在frontend/MyProjectApp 中托管所有内容,就好像它就在 MyProject.Host 的根目录中一样。所以很自然,如果你请求一个不存在的文件,IIS 会产生一个 404 错误。
现在,因为这是一个 AngularJS 应用程序,并且它支持 html5mode,所以我将有一些不是服务器上的物理文件的路由,而是在 AngularJS 应用程序中作为路由处理。如果用户要放到 AngularJS 上(在此示例中,除了 index.html 或物理存在的文件之外的任何内容),即使该路由在 AngularJS 应用程序中可能有效,我也会得到 404。因此,如果请求的文件不存在,我需要我的 OWIN 中间件返回 index.html 文件,并让我的 AngularJS 应用程序确定它是否真的是 404。
如果您熟悉 SPA 和 AngularJS,这是一种正常且直接的方法。如果我使用 MVC 或 ASP.NET 路由,我可以将默认路由设置为返回我的 index.html 的 MVC 控制器,或者类似的东西。但是,我已经声明我没有使用 MVC,并且我正在尝试使其尽可能简单和轻量级。
This user 有类似的困境,并通过 IIS 重写解决了它。在我的情况下,它不起作用,因为 a) 我的内容实际上并不存在于重写 URL 模块可以找到它的地方,所以它总是 返回 index.html 和 b) 我想要一些不'不依赖IIS,而是在OWIN中间件中处理,所以可以灵活使用。
TL;DNR 我,大声哭泣。
很简单,如何使用 OWIN 中间件拦截 404 Not Found 并返回(注意:not 重定向)我的 FileServer-served index.html 的内容?
【问题讨论】:
标签: c# asp.net owin static-files owin-middleware