Использование папки wwwroot (основной стиль ASP.NET) в проекте ASP.NET 4.5
Мне очень нравится подход новых веб-приложений asp.net (asp.net 5\core 1.0), в котором папка wwwroot является корневым каталогом и обслуживаются только статические файлы.
Возможно ли с помощью маршрутизации или другой конфигурации, что папка wwwroot в проекте asp.net 4.5 ведет себя аналогичным образом, так что статические файлы обслуживаются только из нее, и это "корень" веб-приложения для статических файлов?
(Отчасти я хочу спросить, что у меня есть угловое приложение, размещенное в проекте asp.net 5 в VS2015, но мне нужно перенести это в проект asp.net 4.5, но я хотел бы сохранить существующую структуру на диске)
Попытка использования OWIN
Я попытался сделать это с помощью пустого проекта веб-приложения ASP.NET 4.5 и OWIN. Таким образом, в моей структуре папок есть мое угловое приложение с основным файлом 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 в корневой URL-адрес загружает мой файл gulp из корня папки проекта. Это именно то, чего я пытаюсь избежать.
Есть идеи?
3 ответа
Я считаю, что у меня есть рабочий метод для этого сейчас. Я немного погуглил и поэкспериментировал, но в итоге я придумал следующий процесс:
Создайте новый проект 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>
Я всегда открыт для лучших предложений о том, как это сделать, но это, по крайней мере, мне кажется.
Хотя OWIN работал для меня в моей среде разработки, запущенной в VS 2017, он не работал после развертывания в Azure. Мы также запускаем 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 или файл, который действительно существует в корне. Если оба условия выполняются, загружается HTML-документ SPA по умолчанию (в нашем случае мы используем реагирование).
По сути, это позволяет реагирующему маршрутизатору 4 обрабатывать все остальные маршруты после того, как все остальные условия не смогли найти соответствие, и сделать так, чтобы он не выдавал ошибку 404 при попытке загрузить один из маршрутов реагирующего маршрутизатора.
Если вы хотите использовать 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.