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

时间:2016-03-16 08:17:17

标签: iis asp.net-core virtual-directory

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

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

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

5 个答案:

答案 0 :(得分:16)

我今天遇到了这个问题,最后设法解决了这个问题。诀窍(对我而言,可能不适合所有人)确保在子应用程序中禁用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>

并且在IIS中作为子应用程序添加的应用程序已

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

答案 1 :(得分:11)

我找到了一个我认为必须由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
});
  

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

答案 2 :(得分:4)

不直接。

你知道,问题是,当你有一个.NET-Core应用程序时,应用程序是在Kestrell中运行的,而不是在IIS中运行的。

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

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

IIS可以转发domainxy:80到127.0.0.1:随机正常。 但它做得不好的是重写domainxy:80 / foo到127.0.0.1:random(images,header,json-ajax-results,urls,return-urls,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)

您必须在某处配置虚拟目录的名称。 当您在JavaScript / ajax-requests中拥有/返回URL时,请小心,它们不会自动映射。你必须自己做这件事,但过去也是如此。

真的,就像RoR:

  

映射Rails.application.config.relative_url_root || “/”做   运行RedmineApp :: Application
  端

对于应用程序中的虚拟目录: 不,这不是那么简单。
IIS是一个完整的Web服务器,它将像那里一样提供该映射目录的内容(如果它可以读取内容)。

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

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

但是,如果Windows具有该功能(mklink),则可以在应用程序目录中创建一个符合网络文件夹的符号链接。然后.NET Core应该能够静态地提供它。但实际上,这听起来像是一个黑客。

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

答案 3 :(得分:1)

我知道这个问题是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的参数更改为任何本地或共享文件夹,并使用此文件提供文件。

以这种方式执行此操作并非建议使用安全性。但是,对于研究提出,它是可以接受的。

  

静态文件模块提供no   授权检查。它提供的任何文件,包括那些文件   wwwroot是公开的。基于的服务文件   授权:将它们存储在wwwroot和任何目录之外   可以访问静态文件中间件并通过它服务它们   控制器动作,返回授权所在的FileResult   应用

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

点击此链接:https://docs.microsoft.com/en-us/aspnet/core/fundamentals/static-files

答案 4 :(得分:0)

我的解决方案是在path="/"文件上使用path="*"代替web.config