如何告诉IIS在我的.NET应用程序中使用基础的全局路由来提供Web根目录下的静态文件?

5

我有一个使用.NET 5 beta-4构建并在IIS 8.5上运行的Web应用程序。

我想让IIS服务于所有静态文件,因此我删除了.NET 5静态文件中间件。这通常能够按预期正常工作。例如,/img/image.png将通过IIS正确地进行服务。

然而,在我的.NET应用程序中,我有一个捕获所有路由("/{param?}"),以满足业务需求。但是,我还有一些需要被服务的静态文件放置在我的Web根目录下,如:robots.txtfavicon.ico等。

我遇到的问题是: IIS将Web根目录下的静态文件请求路由到.NET应用程序,然后运行捕获所有路由,最终导致404错误。理想情况下,如果IIS找到了Web根目录中的静态文件,则我希望它可以直接服务于该文件。只有当找不到静态文件时,才将请求发送到.NET的捕获所有路由。

如何告诉IIS 8.5从Web根目录服务于静态文件,并且同时支持我的.NET 5应用程序中的捕获所有路由呢?


1
为什么需要使用IIS静态文件模块?对于大多数用途来说,中间件已经足够了。请参见此处的讨论:https://github.com/aspnet/Hosting/issues/323 - Tratcher
3
我认为直接使用Web服务器层而不碰应用程序服务器会更有效率。此外,我们在IIS中使用gzip压缩来提供已压缩的静态文件。如果我们通过.NET提供静态文件,我们需要使用动态压缩而不是静态压缩-这将绕过静态压缩相对于动态压缩的一些优势(例如,IIS不缓存动态压缩)。 - Stephen Watkins
3个回答

4

因为我们使用IIS来提供ASP.NET Core 1.0(以前称为ASP.NET 5)应用程序,所以我们希望使用IIS的压缩和缓存静态文件的能力。

这可以使其更有效率且在你的应用程序循环时不会影响静态资源。无论如何,建议将 app.UseStaticFiles();尽早放置于应用程序的请求管道中,以便它能够短路请求。但是,如果在Linux上,Nginx通常会自行设置为服务静态文件,而不会触及ASP.NET Core管道。因此,我们希望在IIS上执行此操作(如果不是这样,那么为什么要使用IIS?)

为了配置IIS以提供静态文件而不是ASP.NET Core(Kestrel)服务器,我们配置了StaticFileModule以运行特定文件扩展名的处理程序,此操作在AspNetCoreModule处理程序之前执行,因为顺序很重要。(上面答案中的重写方法无效)。可能有更好的方法来定义StaticFileModule处理程序以服务于wwwroot中的任何现有文件。我们仍然在应用程序中使用app.UseStaticFiles();来捕获任何未在StaticFileModule处理程序中定义的模糊静态文件。
下面是web.config文件(system.webServer部分):
<system.webServer>
<handlers>
  <add name="StaticFiles_Js" path="*.js" verb="*" modules="StaticFileModule" resourceType="File" requireAccess="Read" />
  <add name="StaticFiles_Css" path="*.css" verb="*" modules="StaticFileModule" resourceType="File" requireAccess="Read" />
  <add name="StaticFiles_Img" path="*.jpg" verb="*" modules="StaticFileModule" resourceType="File" requireAccess="Read" />
  <add name="StaticFiles_Png" path="*.png" verb="*" modules="StaticFileModule" resourceType="File" requireAccess="Read" />
  <add name="StaticFiles_Gif" path="*.gif" verb="*" modules="StaticFileModule" resourceType="File" requireAccess="Read" />
  <add name="StaticFiles_Fnt" path="*.eot" verb="*" modules="StaticFileModule" resourceType="File" requireAccess="Read" />
  <add name="StaticFiles_Ttf" path="*.ttf" verb="*" modules="StaticFileModule" resourceType="File" requireAccess="Read" />
  <add name="StaticFiles_Ico" path="*.ico" verb="*" modules="StaticFileModule" resourceType="File" requireAccess="Read" />
  <add name="StaticFiles_Pdf" path="*.pdf" verb="*" modules="StaticFileModule" resourceType="File" requireAccess="Read" />
  <add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModule" resourceType="Unspecified" />
</handlers>
<aspNetCore processPath="..\MySite.exe" arguments="" stdoutLogEnabled="false" stdoutLogFile="..\logs\stdout" forwardWindowsAuthToken="true" />
<!-- Adding Gzip compression for static files -->
<httpCompression directory="%SystemDrive%\inetpub\temp\IIS Temporary Compressed Files" minFileSizeForComp="1024">
  <scheme name="gzip" dll="%Windir%\system32\inetsrv\gzip.dll" />
  <staticTypes>
    <add mimeType="text/*" enabled="true" />
    <add mimeType="application/javascript" enabled="true" />
    <add mimeType="application/json" enabled="true" />
    <add mimeType="*/*" enabled="false" />
  </staticTypes>
</httpCompression>
</system.webServer>

要确认 IIS 用于静态文件/资源,只需使用 F12 开发人员工具查看响应头。 HTML 页面会显示响应头,表明其由 .NET 应用程序服务(Server: Kestrel),但.css 或.js 资源将会有 Server: Microsoft-IISContent-Encoding:gzip,如果你启用了压缩。

2

虽然我赞同使用中间件的想法,但如果您绝对想依靠您的Web服务器来提供静态文件而不必通过应用程序进行任何操作,您可以设置一个基于文件依赖的重写:

<rule name="Static Files" stopProcessing="true">
    <match url="(.*)" />
    <conditions logicalGrouping="MatchAny">
        <add input="{APPL_PHYSICAL_PATH}wwwroot\{R:1}" matchType="IsFile" />
    </conditions>
    <action type="Rewrite" url="/{R:1}" />
</rule>

这个应该检查你的请求是否是文件系统中的文件,如果是,则直接将请求重写到该文件,并停止对请求进行处理。


感谢你的回复,Brandon。出于自己的好奇心,我想知道为什么你同意使用中间件的想法(考虑到我的评论)?这只是维护/简单性的问题,还是有其他我没有考虑到的因素? - Stephen Watkins
您IP地址为143.198.54.68,由于运营成本限制,当前对于免费用户的使用频率限制为每个IP每72小时10次对话,如需解除限制,请点击左下角设置图标按钮(手机用户先点击左上角菜单按钮)。 - Brandon Martinez

0
从ASP.NET 5 Beta 7开始,您现在可以使用以下一行代码回退到IIS来处理静态文件:
public void Configure(
    IApplicationBuilder app, 
    IHostingEnvironment env, 
    ILoggerFactory loggerFactory)
{
    // ...Omitted

    // Enable the IIS native module to run after the ASP.NET middleware components.
    // This call should be placed at the end of your Startup.Configure method so that
    // it doesn't interfere with other middleware functionality.
    app.RunIISPipeline();
}

请参阅以下官方文档以获取更多详细信息。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接