Использование папки wwwroot (ASP.NET 5 стиль) в ASP.NET 4.5 проект
Мне очень нравится подход нового asp.net (asp.net 5core 1.0) веб-приложения с папкой wwwroot, являющейся корневым и только статическими файлами, обслуживаемыми там.
возможно через маршрутизацию или другую конфигурацию иметь папку wwwroot в asp.net 4.5 проект ведет себя аналогичным образом, так что статические файлы подаются только из него, и это "корень" webapp для статических файлов?
(часть моей мотивации в этом вопросе заключается в том, что у меня есть приложение angular размещено в asp.net 5 проект в VS2015, но мне нужно переместить это в asp.net 4.5 проект, но хотелось бы сохранить существующую структуру на диске)
попытка использовать OWIN
Я попытался это сделать с помощью пустого ASP.NET 4.5 проект веб-приложения и OWIN. Таким образом, моя структура папок имеет мое угловое приложение с основным индексом.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);
}
}
}
это не удается, хотя-источник моего индекса.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); } } }
-
добавить следующие веб.файл конфигурации, чтобы предотвратить 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 по умолчанию (в нашем случае мы используем react).
эффективно это позволяет react-router 4 обрабатывать все другие маршруты после всех других условий выше не удалось найти совпадение и сделать так, чтобы он не выдавал ошибку 404 при попытке загрузить один из маршрутов react-router.
Если вы хотите использовать 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.