Использование папки wwwroot (стиль ASP.NET 5) в проекте ASP.NET 4.5
Мне очень нравится подход к новым веб-приложениям asp.net(asp.net 5\core 1.0) с папкой wwwroot, являющейся корневым и только статическими файлами, которые там обслуживаются.
Возможно через маршрутизацию или другую конфигурацию, чтобы иметь папку wwwroot в проекте asp.net 4.5, работает аналогичным образом, так что статические файлы обслуживаются только из него, а это "корень" веб-приложения для статического файлы?
(Часть моей мотивации в том, что у меня есть приложение angular, размещенное в проекте asp.net 5 в VS2015, но мне нужно переместить его в проект asp.net 4.5, но хотелось бы сохранить существующая структура на диске)
Попытка использования OWIN
Я попытался это сделать, используя пустой проект веб-приложения ASP.NET 4.5 и OWIN. Таким образом, у моей структуры папок есть мое приложение angular с основным файлом index.html в папке wwwroot в папке проекта. В корне проекта нет файлов HTML.
Я добавил OWIN через nuget и следующий загрузочный файл:
[assembly: OwinStartup(typeof(MyApp.UI.Startup))]
namespace MyApp.UI
{
public class Startup
{
public void Configuration(IAppBuilder app)
{
string root = AppDomain.CurrentDomain.BaseDirectory;
var physicalFileSystem = new PhysicalFileSystem(Path.Combine(root, "wwwroot"));
var options = new FileServerOptions
{
EnableDefaultFiles = true,
FileSystem = physicalFileSystem
};
options.StaticFileOptions.FileSystem = physicalFileSystem;
options.StaticFileOptions.ServeUnknownFileTypes = false;
options.DefaultFilesOptions.DefaultFileNames = new[] {"index.html"};
app.UseFileServer(options);
}
}
}
Это не удается - источник моего файла index.html загружается, когда я запускаю его, но все файлы css, js и т.д., с которыми он ссылается, терпят неудачу с 404. Еще хуже, если я добавлю gulpfile.js на root url загружает мой файл gulp из корня папки проекта. Это именно то, чего я пытаюсь избежать.
Любые идеи?
Ответы
Ответ 1
Я считаю, что у меня есть рабочий метод для этого. Взял немного поиска и экспериментирования, но в итоге я придумал следующий процесс:
-
Создайте новый проект ASP.NET 4.5 в VS2015, выбрав Пустой шаблон
-
Добавьте ссылки OWIN через nuget (Install-Package Microsoft.Owin.Host.SystemWeb
и Microsoft.Owin.StaticFiles
)
-
Добавьте файл запуска, похожий на этот:
[assembly: OwinStartup(typeof(MyApp.Startup))]
namespace MyApp.UI
{
public class Startup
{
public void Configuration(IAppBuilder app)
{
string root = AppDomain.CurrentDomain.BaseDirectory;
var physicalFileSystem = new PhysicalFileSystem(Path.Combine(root, "wwwroot"));
var options = new FileServerOptions
{
RequestPath = PathString.Empty,
EnableDefaultFiles = true,
FileSystem = physicalFileSystem
};
options.StaticFileOptions.FileSystem = physicalFileSystem;
options.StaticFileOptions.ServeUnknownFileTypes = false;
app.UseFileServer(options);
}
}
}
-
Добавьте в свой файл web.config следующее, чтобы IIS не обслуживал статические файлы, которые вам не нужны, и принудительно все через конвейер OWIN:
<system.webServer>
<handlers>
<remove name="StaticFile"/>
<add name="Owin" verb="" path="*" type="Microsoft.Owin.Host.SystemWeb.OwinHttpHandler, Microsoft.Owin.Host.SystemWeb"/>
</handlers>
</system.webServer>
Я всегда готов к лучшим предложениям о том, как это сделать, но это, по-видимому, работает для меня.
Ответ 2
Хотя OWIN работал у меня в моей среде dev, работающей в VS 2017, она не работала после развертывания в лазурном режиме. Мы также запускаем SPA, и сохраняем выход webpack в ~/wwwroot/, но хотели, чтобы он загружался, как если бы он был в корне проекта ~/, как это делает .net core webapi. Я выполнил его, используя только переписанный URL:
<system.webServer>
<rewrite>
<rules>
<rule name="wwwRootFix" stopProcessing="true">
<match url="(.*)" />
<conditions logicalGrouping="MatchAll">
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
<add input="{APPL_PHYSICAL_PATH}wwwroot\{R:1}" matchType="IsFile" />
<add input="{REQUEST_URI}" pattern="^/(api)" negate="true" />
<add input="{REQUEST_URI}" pattern="^/(wwwroot)" negate="true" />
</conditions>
<action type="Redirect" url="/wwwroot/{R:1}" />
</rule>
<rule name="React Routes" stopProcessing="true">
<match url=".*" />
<conditions logicalGrouping="MatchAll">
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
<add input="{REQUEST_URI}" pattern="^/(api)" negate="true" />
<add input="{REQUEST_URI}" pattern="^/(wwwroot)" negate="true" />
</conditions>
<action type="Rewrite" url="/wwwroot/index.html" />
</rule>
</rules>
</rewrite>
</system.webServer>
Первое правило гарантирует, что файл, который вы ищете, не существует в корне, не является папкой, найден в новом пути, это не папка wwwroot, ни это часть api. Если ВСЕ эти условия выполнены, он пытается загрузить данные из wwwroot.
Второе правило проверяет, чтобы вы не пытались загрузить api, или файл, который действительно существует в корне. Если оба условия выполнены, он загружает по умолчанию документ SPA html (в нашем случае мы используем реакцию).
Эффективно это позволяет реагировать маршрутизатору 4 обрабатывать все другие маршруты после того, как все другие условия выше не смогли найти совпадение и сделать так, чтобы он не выдавал ошибку 404 при попытке загрузить один из ответных маршрутизаторов маршруты.
Ответ 3
Если вы хотите использовать IIS для этого, вы можете создать правило перезаписи:
<system.webServer>
<rewrite>
<rules>
<rule name="RewriteUnknownToIndex" patternSyntax="ECMAScript" stopProcessing="true">
<match url="^wwwroot/.*" negate="true" />
<action type="Rewrite" url="/wwwroot/index.html" />
</rule>
</rules>
</rewrite>
</system.webServer>
Вы также можете добавить префикс к регулярному выражению url, например ^(wwwroot|api)/.*
, если это веб-api, который вы хотите разместить в/api.