IIS中的ASP.NET Core应用程序内的虚拟目录

Mat*_*ias 18 iis virtual-directory asp.net-core

我们有一个使用ASP.NET Core 1.0 RC1并在IIS上托管的应用程序.它工作正常.现在我们有静态内容,可以在文件共享上使用,并且应该可以从应用程序访问.

在ASP.NET 5之前,我们在IIS中添加了一个虚拟目录,可以轻松访问共享内容.使用我们托管的ASP.NET 5应用程序,遗憾的是这似乎不起作用.我们只是404在尝试访问静态内容时回来了.

我们的应用程序正在使用app.UseIISPlatformHandler()app.UseStaticFiles(),但这不起作用.我们发现我们可以使用app.UseFileServer()自定义FileServerOptions来获得所需的行为,但我们很好奇是否也可以使用在IIS中添加虚拟目录的常规"旧"方式.

Per*_*mal 17

我今天遇到了这个问题,最后成功解决了这个问题.诀窍(对我而言,可能不适合所有人)确保aspNetCore在子应用程序中禁用处理程序并在主(ASP.NET Core)应用程序中启用.

我的ASP.NET核心应用程序有一个基本的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>
Run Code Online (Sandbox Code Playgroud)

并将应用程序添加为IIS中的子应用程序

<configuration>
  <!-- removed -->
  <system.webServer>
      <handlers>
          <remove name="aspNetCore" />
       </handlers>
  </system.webServer>
</configuration>
Run Code Online (Sandbox Code Playgroud)

  • 您需要对该解决方案给予更多信任。非常简单且易于在某种发布管理软件下的任何东西中实现。 (3认同)
  • 我赞成这一点,因为它确切地解决了我的问题.我在IIS Express的根站点上运行了一个dotnet core 2 Web应用程序,需要设置一个虚拟应用程序文件夹以指向一个遗留的.net 4.5应用程序.当我第一次尝试时,请求只是挂起重定向,我无法弄清楚为什么(没有404它刚刚死亡).将上述处理程序删除添加到我的遗留应用程序的Web.config中可以立即解决问题!非常感谢这是有效的,否则我会处于紧张状态. (2认同)

poo*_*ook 13

我找到了一个我认为必须由OP编写的博客.

结果是根本不使用IIS中的虚拟目录,而是将Startup.cs中的路径映射到物理服务器目录.我希望OP不介意我已经粘贴了下面的博客,但它帮助了我今天第一次遇到这个问题.

资料来源:https://www.jauernig-it.de/asp-net-coreiis-serving-content-from-a-file-share/

在某些情况下,当您希望为应用程序提供静态内容时,这不是其中的一部分,例如,因为它存在于公共文件共享中.由业务部门管理的网站内容可能就是这样一个用例.在Core之前的ASP.NET中,这在IIS中没有问题:只需在IIS网站中创建一个虚拟目录并将其指向文件共享.

不幸的是,使用ASP.NET Core,这种方法不再适用.如果在IIS中向ASP.NET Core应用程序添加虚拟目录,则无法识别该目录并返回404.这是因为DNX/Kestrel在IIS下运行(使用HttpPlatformHandler模​​块),IIS只会代理请求.Kestrel不知道IIS中的任何虚拟目录.并且因为ASP.NET Core应用程序独立于IIS而且也可以在没有它的情况下运行(例如运行Kestrel standalone),这应该被视为一件好事.

但是现在我们需要另一个解决方案来解决我们的问题......幸运的是,ASP.NET Core为我们提供了一个编程接口来从任何地方提供文件.只需将以下代码添加到Startup.cs Configure()方法:

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

这实质上是将文件服务器添加到物理服务器路径,然后在某个请求路径上可用,在这种情况下禁用目录浏览.您还可以使用新的PhysicalFileProvider(env.WebRootPath +"\ path")从相对于您的应用程序的路径提供服务(给定env的类型为IHostingEnvironment作为Configure()的参数).瞧,就是这样.没有必要在IIS中添加"虚拟目录",这个东西已被弃用并且已成为过去.对我来说,这是一件好事,因为我们更加独立于整个IIS ......

  • 这对我有用。需要使用Microsoft.Extensions.FileProviders; (2认同)
  • 辉煌。第一次工作。 (2认同)
  • 正是我所需要的。 (2认同)
  • 这应该是公认的答案。简直就是完美。 (2认同)
  • 有没有办法首先获取当前默认的PhysicalFileProvider或默认的FileServerOptions,以便我可以直接传递它并仅调整RequestPath而不影响其他任何内容? (2认同)

Ste*_*ger 6

不直接。

\n

您会看到,问题是,当您有 .NET-Core 应用程序时,该应用程序在 Kestrell 中运行,而不是在 IIS 中运行(对于 .NET Core < 2.2)。

\n

现在,为了在 IIS 中托管您的 .NET-Core 应用程序,AspNetCoreModule 在端口 X 127.0.0.1 上使用 Kestrell 启动您的 .NET-Core 应用程序,然后将流量从 iis 域+虚拟目录反向代理到端口 X在 127.0.0.1 上(它可能使用 TCP 以外的其他东西)。

\n

问题 1 是,Kestrell 的功能非常有限,这意味着没有虚拟目录。
\n问题 2 是,与 nginx 不同,IIS 并没有真正正确地进行反向代理,或者我们应该说“完全”。

\n

IIS 可以将 domainxy:80 转发到 127.0.0.1:random 好吧。\n但它没有正确执行的操作是将 domainxy:80/foo 重写为 127.0.0.1:random (images, header, json-ajax-results, urls, \n相反,它将domain:80/foo重写为127.0.0.1:random/foo,如果127.0.0.1:random (Kestrell)上的服务器不这样做,这就会出现问题\不支持虚拟目录。

\n

因此,如果您想在虚拟目录中运行应用程序,您有两个选择(都涉及修改“您的”应用程序 - 如果您可以这样做):

\n
    \n
  1. 如果您的应用程序仅部署一次,请将所有内容放入目录“foo”(包括 MVC 控制器路由)。

    \n
  2. \n
  3. 正如https://github.com/aspnet/Hosting/issues/416#issuecomment-149046552中所建议的,您可以让应用程序框架为您模拟该文件夹,有点像 RoR 中的那样:

    \n
  4. \n
\n
    public void Configure(IApplicationBuilder app, \n                          IHostingEnvironment env,\n                          ILoggerFactory loggerFactory)\n    {\n        string virtual_directory = "/Virt_DIR";\n        // virtual_directory = "/";\n\n        if (virtual_directory.EndsWith("/"))\n            virtual_directory = virtual_directory.Substring(0, virtual_directory.Length - 1);\n\n        if (string.IsNullOrWhiteSpace(virtual_directory))\n            Configure1(app, env, loggerFactory); // Don\'t map if you don\'t have to \n            // (wonder what the framework does or does not  do for that case)\n        else \n            app.Map(virtual_directory, delegate(IApplicationBuilder mappedApp) \n                {\n                    Configure1(mappedApp, env, loggerFactory);\n                }\n            );\n    }\n    \n    // Configure is called after ConfigureServices is called.\n    public void Configure1(IApplicationBuilder app, \n                           IHostingEnvironment env, \n                           ILoggerFactory loggerFactory)\n    {\n         //  [...]  (here comes what used to be in your old Configure method)\n    }\n\n
Run Code Online (Sandbox Code Playgroud)\n

您必须在某处配置虚拟目录的名称。\n当您在 JavaScript/ajax 请求中拥有/返回 URL 时请小心,它们不会被自动映射。您必须自己执行此操作,但旧版 ASP.NET 也曾经采用过这种方式。

\n

真的,就像 RoR 一样:

\n
\n

映射 Rails.application.config.relative_url_root || “/”做
\n\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0run RedmineApp::Application
\nend

\n
\n

至于应用程序内的虚拟目录:\n不,这并不那么简单。
\nIIS 是一个完整的网络服务器,它将像原来一样提供映射目录的内容(如果它可以读取内容)。

\n

如果您将整个父目录转发到 Kestrell,则 IIS 无法为该子目录提供服务,而您的应用程序必须这样做。这意味着您必须为该特定目录设置一个静态文件服务器,并告诉它文件在哪里,就像您所做的那样。

\n

您可以做的是告诉 IIS 不要代理该特定的虚拟子目录(就像您可以在 nginx 中定义静态文件位置一样 - 只不过 IIS 可能不支持该功能)。

\n

但是,您可以在应用程序目录中创建一个指向网络文件夹的符号链接(或挂载/连接),如果 Windows 能够这样做 (mklink)。那么.NET Core 应该能够静态地提供它。但实际上,这听起来像是一种黑客行为。

\n

如果您无法配置 IIS,那么您确实应该使用 app.UseFileServer() 并定义文档在数据库中的位置。这样您就可以稍后删除并重新插入该应用程序。

\n


Raf*_*ael 6

我知道这是一个 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")
    });
}
Run Code Online (Sandbox Code Playgroud)

完全可以将 PhysicalFileProvider 的参数更改为任何本地或共享文件夹,并以此提供文件。

出于安全考虑,不建议这样做。但是,对于研究建议来说,这是可以接受的。

静态文件模块不提供授权检查。它提供的任何文件(包括 wwwroot 下的文件)都是公开可用的。要基于授权提供文件:将它们存储在 wwwroot 和静态文件中间件可访问的任何目录之外,并通过控制器操作提供它们,返回应用授权的 FileResult。

在 Microsoft 的 Asp.Net 文档中,我们可以找到更完整的信息来帮助解决此问题。

检查此链接:https ://learn.microsoft.com/en-us/aspnet/core/fundamentals/static-files