如何使用IIS运行ASP.NET Core程序,当您使用ASP.NET Core 开发的网站或Web Api想要在IIS上运行时,您会发现IIS中的.NET Core应用程序与以前版本的ASP.NET完全不同。江湖人士会在这篇文章中,解释ASP.NET Core如何在IIS环境下运行,以及如何将ASP.NET Core应用程序部署到IIS。
IIS和ASP.NET Core
了解有关托管ASP.NET Core最重要的一点是,它作为一个独立的进程控制台应用程序运行。它不是托管在IIS内部,它不需要运行IIS。ASP.NET Core应用程序使用此自托管服务器实例在内部拥有自己的自托管Web服务器和进程请求。
但是,您可以将IIS作为ASP.NET Core应用程序的前端代理运行,因为Kestrel是原始Web服务器,不支持像IIS支持的完整服务器的所有功能。这实际上是在Windows上推荐的做法,以提供端口80/443转发哪个红隼不直接支持。对于Windows IIS(或其他反向代理),即使使用ASP.NET Core应用程序,仍将是服务器的重要组成部分。
让我们来看看IIS如何适应ASP.NET核心应用程序。
了解有关托管ASP.NET Core最重要的一点是,ASP.NET Core 应用程序作为一个独立的进程自我寄宿式运行。并不是托管在IIS内部,换句话说ASP.NET Core的应用程序不需要IIS也可以运行。ASP.NET Core应用程序使用自托管服务器实例在内部拥有自己的自托管Web服务器和进程请求。
但是,您可以将IIS作为ASP.NET Core应用程序的前端代理运行实现类似nginx的功能,因为Kestrel是原始Web服务器,不支持像IIS支持的完整服务器的所有功能。这实际上是Windows上推荐的做法,以便提供kestrel不直接支持的端口80/443转发。对于Windows IIS(或其他反向代理),即使使用ASP.NET Core应用程序,仍将是服务器的重要组成部分。
让我们来看看IIS如何适应ASP.NET核心应用程序。
经典的ASP.NET托管
在我们看一下ASP.NET Core主机之前,让我们回顾一下经典的ASP.NET运行ASP.NET应用程序的方式:
在传统的ASP.NET应用程序中,所有东西都托管在IIS应用程序池的IIS工作进程(w3wp.exe)中。AppPool托管您的ASP.NET应用程序,您的应用程序由IIS中的内置ASP.NET托管功能实例化。本机运行时管理器代表您的应用程序实例化.NET运行时,并调出HttpRuntime
用于通过ASP.NET应用程序管道发送请求的对象,因为来自本机http.sys驱动程序的请求进来。来自http.sys的请求被分配到映射到应用程序池的适当的站点以及在那里托管的HttpRuntime实例。
ASP.NET Core 与 IIS
与ASP.NET Core不同的是,它并不在IIS进程中运行,而是作为一个单独的,进程外的Console应用程序运行,它使用Kestrel组件运行自己的Web服务器。 Kestrel是.NET Web服务器的一个实现,它已经为吞吐量性能进行了大量的优化。 它将网络请求传送到您的应用程序中速度快,功能强大,但它只是一个原始的Web服务器。 它不包含像IIS那样的全功能服务器的Web管理服务。
如果你在Windows上运行,你可能需要在IIS后面运行Kestrel,以获得诸如通过主机头进行端口80/443转发,进程生命周期管理和证书管理等基础设施功能。
下面是在IIS Web前端运行ASP.NET Core应用程序时的样子:
ASP.NET Core的应用程序是通过dotnet运行时命令调用的独立控制台应用程序。它们没有加载到IIS工作进程中,而是通过一个名为的AspNetCoreModule
执行外部控制台应用程序的本机IIS模块加载。
AspNetCoreModule必须安装在您的服务器上,并且是ASP.NET Core Server Hosting Bundle的一部分。
一旦你安装了托管包(或者你的开发机器上安装了.NET Core SDK),你可以在IIS的模块里面找到AspNetCoreModule:
AspNetCoreModule是一个本地IIS模块,在请求周期的早期就挂钩到IIS管道中,并立即将所有流量重定向到后端ASP.NET Core应用程序。所有请求 – 甚至是那些映射到顶层处理程序的请求,如ASPX
绕过IIS管道,并被转发到ASP.NET Core进程。这意味着你不能轻易地将ASP.NET Core和其他框架混合在同一个Site / Virtual目录中,这感觉有点像退后一步,因为你可以在IIS中轻松地混合框架。
虽然在IIS里面创建站点或虚拟目录时仍会创建应用程序池,但您需要将应用程序池设置为使用“ 无托管代码”。由于应用程序池仅作为转发请求的代理,因此不需要实例化.NET运行时。
AspNetCoreModule的工作是确保当第一个请求进入时你的应用程序被加载,并且如果由于某种原因应用程序崩溃,进程将保持加载状态。您本质上获得了与由WAS(Windows激活服务)管理的传统ASP.NET应用程序相同的行为。
一旦运行,传入的Http请求将由该模块处理,然后路由到您的ASP.NET Core应用程序。
所以,来自Web的请求以及在主端口(80)或SSL端口(443)上路由到IIS的内核模式http.sys驱动程序。然后将请求转发到为您的应用程序配置的不是端口80/443的HTTP端口上的ASP.NET Core应用程序。本质上,IIS只是将请求转发到在不同端口上运行Kestrel Web服务器的ASP.NET Core Web上的反向代理。
Kestrel提取请求并将其推入ASP.NET Core中间件管道,然后处理您的请求并将其传递到您的应用程序逻辑。然后将生成的HTTP输出传递回IIS,然后通过Internet将其推回到发起请求的HTTP客户端 – 浏览器,移动客户端或应用程序。
AspNetCoreModule是通过web.config
应用程序根目录中的文件配置的,该文件指向dotnet
用于启动.NET Core应用程序的启动命令(dotnet)和参数(您的应用程序的主dll)。web.config文件中的配置将该模块指向应用程序的根文件夹以及需要启动的启动DLL。
以下是web.config的样子:
<?xml version="1.0" encoding="utf-8"?> <configuration> <!-- Configure your application settings in appsettings.json. Learn more at http://go.microsoft.com/fwlink/?LinkId=786380 --> <system.webServer> <handlers> <add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModule" resourceType="Unspecified" /> </handlers> <aspNetCore processPath="dotnet" arguments=".AlbumViewerNetCore.dll" stdoutLogEnabled="false" stdoutLogFile=".logsstdout" forwardWindowsAuthToken="false" /> </system.webServer> </configuration>
你可以看到这个模块引用了dotnet.exe和.NET核心应用程序中保存Main方法的编译入口点DLL 。
我们需要IIS吗?
我们已经讨论过,在Windows上运行ASP.NET Core时,建议您使用IIS作为前端代理。虽然可以通过IP地址和可用端口直接访问Kestrel,但有几个原因让您不希望在生产环境中直接以这种方式公开您的应用程序。
首先,如果您希望在一台共享端口80和端口443的服务器上运行多个应用程序,则无法直接运行Kestrel。Kestrel不支持在一个IP地址上允许多个端口80绑定所需的主机头路由。没有IIS(或者实际上是http.sys),你目前不能单独使用Kestrel来做这件事(我想这也不是计划的)。
通过IIS运行的AspNetCoreModule还提供必要的流程管理,以确保您的应用程序在第一次访问时被加载,确保它保持运行并在崩溃时重新启动。AspNetCoreModule提供了所需的流程管理,以确保即使在崩溃之后,您的AspNetCore应用程序也始终可用。
通过IIS证书存储设置证书并让IIS处理SSL身份验证,通过IIS正确运行安全SSL请求也是一个好主意。然后,来自IIS的底层HTTP请求可以简单地将不安全的HTTP请求发送到您的应用程序。这意味着即使在底层上有多个服务器为实际的HTTP内容提供服务,前端IIS服务器也只需要一个证书。
IIS还可以提供静态文件服务,静态内容的gzip压缩,静态文件缓存,Url重写以及IIS提供的其他一些本地功能。IIS在处理非应用程序请求方面非常好,而且效率很高,所以值得利用它。您可以让IIS处理它真正擅长的任务,并让动态任务通过您的ASP.NET Core应用程序。
所有这一切的底线是,如果你在Windows上托管,你会想使用IIS和AspNetCoreModule。
IIS运行ASP.NET Core程序
所以我看到这个问题偶尔会出现:
我可以运行完整的IIS运行和调试我的ASP.NET核心应用程序,就像我可以与经典的应用程序?
稍微回避一下这个问题:在开发过程中运行IIS应该有很少的原因。是的,在过去没有被很好的理由,因为总是有一些事情,相比于IIS Express在完整的IIS的表现非常不同运行完整的IIS。
但是,使用ASP.NET Core在开发过程中几乎没有理由运行完整的IIS。为什么?因为ASP.NET Core应用程序实际上并不在IIS内部运行。无论是从IIS,IIS Express运行调用,还是dotnet run
从命令行直接执行 – 您都运行完全相同的代码,并且在大多数情况下运行的环境完全相同。在IIS中运行真的不会再给你任何东西,你不能轻易地用命令行环境来模拟。
唯一的原因,你可能需要在IIS下运行,如果有东西,IIS提供的HTTP服务,是真正从ASP.NET核心处理的单独条款。但即使如此,这些功能很可能不会在应用程序环境中调试。
运行IIS
你不能从你的开发环境中运行IIS的原因是ASP.NET Core应用程序在执行之前必须被发布。开发文件夹不包含运行您的应用程序所需的所有文件。当您“调试”或“运行”您的应用程序时,应用程序首先发布到一个单独的位置并从那里运行。因为这个原因,你不会在Visual Studio中看到IIS作为一个选项。
如果您绝对必须使用IIS运行,则可以先将应用程序发布到本地文件夹,然后配置IIS虚拟目录或站点,然后使用它运行您的站点。
为IIS发布ASP.NET核心应用程序
为了使用IIS运行应用程序,您必须首先发布它。有两种方法可以在今天做到这一点:
- 使用
dotnet publish
- 使用Visual Studio发布功能
运用 dotnet publish
使用dotnet publish
构建应用程序并将项目的可运行,自包含的版本复制到磁盘上的新位置。您指定一个输出文件夹所有文件发布。这与从临时文件夹运行网站的传统ASP.NET没有太大区别。借助ASP.NET Core,您可以将应用程序明确地发布到您选择的位置 – 这些文件不再被隐藏起来,并且被魔法复制。
典型的发布命令可能如下所示:
dotnet publish --framework netcoreapp1.0 --output "c:tempAlbumViewerWeb" --configuration Release
这发布应用程序的c:tempalbumviewerWeb
。
如果你打开这个文件夹,你会发现它包含你的原始应用程序结构加上所有转储到根文件夹的nuget依赖关系程序集:
手动IIS托管发布文件夹
一旦你已经发布了你的应用程序,并且已经把它移动到了你的服务器上(通过FTP或其他机制),我们就可以把IIS连接到这个文件夹。
我要创建一个虚拟应用程序目录:
请注意,我创建了一个AspNetCore应用程序池,其.NET运行时设置为无托管代码,如前所示。
IIS身份和权限
您可能还必须将IIS App Pool Identity调整为默认ApplicationPoolIdentity以外的其他值,以确保您的应用程序能够访问运行所需的资源。我通常从NETWORKSERVICE开始,然后转到一个与应用程序所需的实际权限相匹配的自定义帐户。
而这就是所有需要发生的事情。您现在应该可以导航到您的站点或虚拟,并且应用程序正在运行。
现在,您可以将此本地部署的网站复制到Web服务器(通过FTP或直接文件复制或其他发布解决方案),建立一个站点或虚拟,并且您将进入比赛。
从Visual Studio发布
该DOTNET发布步工程,整个项目复制到文件夹,但它实际上并没有你的项目发布到Web站点(目前-这很可能是在稍后推出)。
为了使增量发布工作,这对于ASP.NET Core应用程序来说确实非常重要,因为存在太多的依赖关系,所以需要使用作为Visual Studio Web Publishing功能一部分提供的MsDeploy。
目前,Visual Studio Tooling UI非常不完整,但支持底层功能。我会指出一些你可以用来调整它的工具。
在RC2 Web工具和“发布”对话框中进入Visual Studio时,将发现无法创建指向IIS的发布配置文件。有文件和Azure发布的选项,但没有办法通过用户界面来创建新的网站发布。
但是,您可以通过创建自己的.pubxml
文件并将其放入PropertiesPublishProfiles
项目文件夹中进行欺骗。
特定于版本的解决方法
请注意,几乎可以肯定的是,这将在工具更新后得到修复,因此,如果您从现在开始的一个月内阅读本文,请仔细阅读这些步骤,然后检查是否可以直接通过Visual Studio UI创建IIS发布配置文件。
要在ASP.NET Core Web项目中创建“手动配置文件”,请执行以下操作:
- 创建一个文件夹
PropertiesPublishProfiles
- 创建一个文件
<MyProfile>.pubxml
您可以复制非.pubxml
ASAP.NET Core项目中的现有项目或创建一个项目。下面是一个与IIS一起使用的配置文件的示例:
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <PropertyGroup> <WebPublishMethod>MSDeploy</WebPublishMethod> <LastUsedBuildConfiguration>Release</LastUsedBuildConfiguration> <LastUsedPlatform>Any CPU</LastUsedPlatform> <SiteUrlToLaunchAfterPublish>http://samples.west-wind.com/AlbumViewerCore/index.html</SiteUrlToLaunchAfterPublish> <LaunchSiteAfterPublish>True</LaunchSiteAfterPublish> <ExcludeApp_Data>False</ExcludeApp_Data> <PublishFramework>netcoreapp1.0</PublishFramework> <UsePowerShell>True</UsePowerShell> <EnableMSDeployAppOffline>True</EnableMSDeployAppOffline> <MSDeployServiceURL>https://publish.west-wind.com</MSDeployServiceURL> <DeployIisAppPath>samples site/albumviewercore</DeployIisAppPath> <RemoteSitePhysicalPath /> <SkipExtraFilesOnServer>True</SkipExtraFilesOnServer> <MSDeployPublishMethod>RemoteAgent</MSDeployPublishMethod> <EnableMSDeployBackup>False</EnableMSDeployBackup> <UserName>username</UserName> <_SavePWD>True</_SavePWD> <ADUsesOwinOrOpenIdConnect>False</ADUsesOwinOrOpenIdConnect> <AuthType>NTLM</AuthType> </PropertyGroup> </Project>
AuthType NTLM修复
记<AuthType>NTLM</AuthType>
下文件底部的按键。这个键非常重要,否则发布操作不起作用。如果您从现有文件进行复制,请确保添加此密钥,因为默认情况下不太可能拥有此密钥。
一旦创建了一个.pubxml
文件,现在可以在Visual Studio中打开发布对话框,并选择此配置文件:
此时,您应该能够将您的站点发布到远程服务器上的IIS,并对您的内容使用增量更新。