Фон
Сначала позвольте мне объяснить предысторию. Я работаю над проектом, который пытается выйти замуж за бэкэнд-сервер, который использует Web API, настроенный через OWIN, размещенный в 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
или файл, который физически существует, в этом примере), я бы получил 404, хотя этот маршрут может быть действительным в приложении AngularJS. Поэтому мне нужно мое промежуточное ПО OWIN, чтобы вернуть файл index.html
в случае, если запрошенный файл не существует, и пусть мое приложение AngularJS выяснит, действительно ли это 404.
Если вы знакомы с SPA и AngularJS, это обычный и прямой подход. Если бы я использовал MVC или ASP.NET-маршрутизацию, я мог бы просто установить маршрут по умолчанию на контроллер MVC, который возвращает мой index.html
, или что-то в этом направлении. Тем не менее, я уже заявил, что не использую MVC, и я стараюсь, чтобы это было максимально простым и легким.
Этот пользователь имел аналогичную дилемму и решил его с переписыванием IIS. В моем случае это не работает, потому что: а) мой контент физически не существует, где модуль URL перезаписи может его найти, поэтому он всегда возвращает index.html
и b) Я хочу что-то, что не полагается на IIS, но обрабатывается в промежуточном ПО OWIN, поэтому его можно использовать гибко.
TL; DNR me, для громкого крика.
Просто, как я могу перехватить 404 Not Found и вернуть содержимое (примечание: не перенаправить) my FileServer
-served index.html
с использованием промежуточного программного обеспечения OWIN?