Виртуальный каталог внутри основного приложения ASP.NET в IIS

У нас есть приложение, использующее ASP.NET Core 1.0 RC1 и размещенное на IIS. Он работает нормально. Теперь у нас есть статический контент, который доступен в общем доступе к файлу и должен быть доступен из приложения.

До ASP.NET 5 мы добавили виртуальный каталог в IIS и могли легко получить доступ к общему контенту. С помощью нашего приложения ASP.NET 5 это, к сожалению, не работает. Мы просто получаем 404 назад при попытке доступа к статическому контенту.

Наше приложение использует app.UseIISPlatformHandler() и app.UseStaticFiles(), но это не работает. Мы обнаружили, что мы могли бы использовать app.UseFileServer() с пользовательским FileServerOptions для получения желаемого поведения, но нам любопытно, возможно ли это также с обычным "старым" способом добавления виртуального каталога в IIS.

Ответ 1

Сегодня я столкнулся с этой проблемой и, наконец, смог ее исправить. Трюк (для меня, вероятно, не для всех) заключается в том, что обработчик aspNetCore отключен в под-приложении и включен в основном приложении ASP.NET Core.

В моем приложении ASP.NET Core есть базовый Web.config

<configuration>
  <system.webServer>
    <handlers>
        <add name="aspNetCore" path="*" verb="*" type="" modules="AspNetCoreModule" scriptProcessor="" resourceType="Unspecified" requireAccess="Script" allowPathInfo="false" preCondition="" responseBufferLimit="4194304" />
    </handlers>
    <aspNetCore processPath="dotnet" arguments=".\bin\Debug\netcoreapp2.0\myapp.dll" stdoutLogEnabled="true" stdoutLogFile=".\logs\stdout" />
  </system.webServer>
</configuration>

и приложение, добавленное как под-приложение в IIS, имеет

<configuration>
  <!-- removed -->
  <system.webServer>
      <handlers>
          <remove name="aspNetCore" />
       </handlers>
  </system.webServer>
</configuration>

Ответ 2

Я нашел блог, который, я думаю, был написан ОП.

В результате мы вовсе не используем виртуальный каталог в IIS, а сопоставляем ваш путь в Startup.cs с каталогом физического сервера. Я надеюсь, что OP не возражает против того, что я вставил блог ниже, но он помог мне, когда я впервые столкнулся с этой проблемой сегодня.

Источник: https://www.jauernig-it.de/asp-net-coreiis-serving-content-from-a-file-share/

Существуют ситуации, когда вы хотите предоставить статическое содержимое вашему приложению, которое не является его частью, например, потому что оно существует в общем файловом ресурсе. Контент веб-сайта, который управляется бизнес-подразделением, может быть таким примером использования. В ASP.NET до Core это не было проблемой в IIS: просто создайте виртуальный каталог на своем веб-сайте IIS и укажите его для общего файлового ресурса.

К сожалению, в ASP.NET Core этот подход больше не работает. Если вы добавляете виртуальный каталог в приложение ASP.NET Core в IIS, он не распознается и возвращается 404. Это из-за DNX/Kestrel, который работает под IIS (используя модуль HttpPlatformHandler) и к которому IIS только посредничает запросы. Kestrel ничего не знает о виртуальных каталогах из IIS. А поскольку основные приложения ASP.NET не зависят от IIS и могут также выполняться без него (например, с автономной работой Kestrel), это следует рассматривать как хорошую вещь.

Но теперь нам нужно другое решение для нашей проблемы… к счастью, ASP.NET Core предоставляет нам программный интерфейс для обслуживания файлов из любого места. Просто добавьте следующий код в ваш метод Startup.cs Configure():

app.UseFileServer(new FileServerOptions
{
    FileProvider = new PhysicalFileProvider(@"\\server\path"),
    RequestPath = new PathString("/MyPath"),
    EnableDirectoryBrowsing = false
});

По сути, это добавляет файловый сервер к физическому пути к серверу, который затем доступен по определенному пути запроса, в данном случае с отключенным просмотром каталога. Вы также можете обслуживать по пути относительно вашего приложения, используя новый PhysicalFileProvider (env.WebRootPath + "\ path") (данный env имеет тип IHostingEnvironment в качестве параметра Configure()). Вуаля, вот и все. Нет необходимости добавлять "виртуальный каталог" в IIS, этот материал устарел и ушел в прошлое. Для меня это хорошо, потому что мы становимся более независимыми от всего IIS…

Ответ 3

Не напрямую.

Видите ли, проблема в том, что когда у вас есть приложение .NET-Core, оно запускается в Kestrell, а не в IIS (для .NET Core <2.2).

Теперь, чтобы разместить ваше приложение .NET-Core в IIS, AspNetCoreModule запускает ваше приложение .NET-Core с Kestrell на порту X 127.0.0.1, а затем перенаправляет трафик с вашего виртуального каталога iis-domain + на порт X на 127.0.0.1 (он может использовать что-то еще, кроме TCP).

Проблема 1 в том, что Kestrell имеет довольно ограниченную функциональность, то есть не имеет виртуальных каталогов.
Проблема 2 в том, что IIS, в отличие от nginx, на самом деле не выполняет обратное проксирование должным образом, или мы должны сказать "полностью".

IIS может пересылать domainxy: 80 на 127.0.0.1:random в порядке. Но что он не делает должным образом, так это переписывает domainxy: 80/foo в 127.0.0.1:random (images, header, json-ajax-results, urls, return-url, cookies и т.д. И наоборот). Вместо этого он переписывает домен: 80/foo в 127.0.0.1:random/foo, что является проблемой, если сервер 127.0.0.1:random (Kestrell) не поддерживает виртуальные каталоги.

Поэтому, если вы хотите запустить свое приложение в своем виртуальном каталоге, у вас есть два варианта (оба включают изменение "вашего" приложения - если вы можете это сделать):
1) Поместите все свои вещи в каталог "foo" (включая маршрут контроллера MVC), если ваше приложение будет развернуто только один раз.

2) Как предложено в https://github.com/aspnet/Hosting/issues/416#issuecomment-149046552, вы можете настроить каркас приложения для имитации этой папки, как в RoR:

 public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
    string virtual_directory = "/Virt_DIR";
    // virtual_directory = "/";

    if (virtual_directory.EndsWith("/"))
        virtual_directory = virtual_directory.Substring(0, virtual_directory.Length - 1);

    if (string.IsNullOrWhiteSpace(virtual_directory))
        Configure1(app, env, loggerFactory); // Don't map if you don't have to 
        // (wonder what the framework does or does not  do for that case)
    else 
        app.Map(virtual_directory, delegate(IApplicationBuilder mappedApp) 
            {
                Configure1(mappedApp, env, loggerFactory);
            }
        );
}

// Configure is called after ConfigureServices is called.
public void Configure1(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
       [...]  (here comes what used to be in your old Configure method)

Вам нужно будет где-то настроить имя виртуального каталога. Осторожно, когда у вас есть/возвращаются URL-адреса в JavaScript/ajax-запросах, они не будут автоматически отображаться. Вы должны сделать это сами, но так было и со старым ASP.NET.

Действительно, как RoR:

карта Rails.application.config.relative_url_root || "/" делать
запустить RedmineApp :: Application
конец

Что касается виртуального каталога в приложении: нет, это не так просто.
IIS - это полноценный веб-сервер, который будет обслуживать содержимое этого сопоставленного каталога так, как он был там (если он может читать содержимое).

Если вы перенаправите весь родительский каталог в Kestrell, то IIS не сможет обслуживать подкаталог, и ваше приложение должно будет это сделать. Это означает, что вам нужно настроить статический файловый сервер для этого конкретного каталога и сообщить ему, где находятся файлы, как вы это сделали.

То, что вы могли бы сделать, это сказать IIS не использовать прокси для этого конкретного виртуального подкаталога (точно так же, как вы можете определить местоположение статического файла в nginx - за исключением того, что IIS, вероятно, не поддерживает эту функцию).

Однако вы можете создать символическую ссылку (или mount/junction) в каталоге вашего приложения, который идет в сетевую папку, если Windows способна на это (mklink). Тогда .NET Core сможет обслуживать его статически. Но на самом деле, это звучит как взломать.

Если вы не можете настроить IIS, вам действительно следует использовать app.UseFileServer() и определить местоположение документа в базе данных. Таким образом, вы можете просто удалить и повторно вставить приложение позже.

Ответ 4

Я знаю его вопрос с 1,8 года, но если кому-то нужно решить ту же проблему, попробуйте использовать это:

public void Configure(IApplicationBuilder app)
{
    app.UseStaticFiles(); // For the wwwroot folder

    app.UseStaticFiles(new StaticFileOptions()
    {
        FileProvider = new PhysicalFileProvider(
            Path.Combine(Directory.GetCurrentDirectory(), @"wwwroot", "images")),
        RequestPath = new PathString("/MyImages")
    });
}

Совершенно возможно изменить параметры PhysicalFileProvider в любую локальную или общую папку, и с этим служит файл.

Выполнение этого таким образом не рекомендуется БЕЗОПАСНОСТЬ. Но, для исследования предложить, его приемлемым.

Статический файловый модуль не предоставляет авторизации. Любые файлы, обслуживаемые им, включая wwwroot являются общедоступными. Слушать файлы на основе авторизация: Храните их вне wwwroot и любой директории доступных для статического промежуточного программного обеспечения и обслуживать их через действия контроллера, возвращая FileResult, где авторизация приложенное.

В документах Microsoft Asp.Net мы можем найти более полную информацию, чтобы помочь с этой проблемой.

Проверьте эту ссылку: https://docs.microsoft.com/en-us/aspnet/core/fundamentals/static-files

Ответ 5

Мое решение использовало path="/" вместо path="*" в web.config файле

Ответ 6

Испытываете ту же/похожую проблему, используя ASP.NET CORE 2.1.

Пока веб файлы хранились в папке /wwwroot/, я создавал ВИРТУАЛЬНУЮ КАТАЛОГ для этой папки в IIS и при просмотре просматривал папки и файлы правильно. Однако браузер (http) их не тянет.

Я решил свою проблему, создав виртуальную директорию вне корня.

РАБОТАЕТ ЭТОМ СПОСОБОМ:

ВЕБ-САЙТ

/Wwwroot/

/CSS/

/JS/

/Library/

/ВИРТУАЛЬ-ПАПКА/

НЕ РАБОТАЕТ ЭТОМ СПОСОБОМ:

ВЕБ-САЙТ

/Wwwroot/

/CSS/

/JS/

/Library/

/ВИРТУАЛЬ-ПАПКА/