背景
首先让我解释一下背景。我正在开发一个项目,该项目试图将使用通过 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。index.html
因此,如果请求的文件不存在,我需要我的 OWIN 中间件返回该文件,并让我的 AngularJS 应用程序确定它是否真的是 404。
如果您熟悉 SPA 和 AngularJS,这是一种正常且直接的方法。如果我使用 MVC 或 ASP.NET 路由,我可以将默认路由设置为返回 myindex.html
或类似内容的 MVC 控制器。但是,我已经声明我没有使用 MVC,并且我正在尝试使其尽可能简单和轻量级。
这位用户也有类似的困境,并通过 IIS 重写解决了这个问题。就我而言,它不起作用,因为a)我的内容实际上并不存在于重写URL模块可以找到它的地方,所以它总是返回index.html
b)我想要一些不依赖IIS但在内部处理的东西OWIN中间件,可以灵活使用。
TL; DNR 我,大声哭泣。
很简单,如何拦截 404 Not Found 并使用 OWIN 中间件返回 my -served的内容(注意:不重定向) ?FileServer
index.html