您的位置:首页 > 编程语言 > ASP

[转]ASP.NET Core 1 Deploy to IIS

2017-01-11 10:05 681 查看
本文转自:

http://webmodelling.com/webbits/aspnet/aspnet-deploy-iis.aspx

15 Sep 2016. This tutorial will show step by step how to deploy an ASP.NET Core 1 project to Internet Information Server (IIS) on a Windows 2012 R2 production server.

ASP.NET Core 1 hosting is quite different from earlier asp.net versions, this difference is hidden then developing using VS2015 & IISExpress but shows itself very clearly then comes time to deploy to an IIS production server - this tutorial will give you an understanding of the ASP.NET Core 1 hosting system and how to deploy ASP.NET Core 1 to an IIS production server.

Index :

Understanding ASP.NET Core 1 hosting

Prepare IIS

Prepare your web application

Create the IIS website

Appendixes :

Appendix : Create a self hosted ASP.NET Core App

Appendix : Understanding proxies

Appendix : Common errors & solutions

Comments

Main references :

ASP.NET Core server fundamentals @docs.asp.net

ASP.NET Core Publishing to IIS @docs.asp.net

ASP.NET Core Hosting @docs.asp.net

ASP.NET Core & IIS @Rick Strahl - very good



Understanding ASP.NET Core 1 hosting

In ASP.NET Classic (latest version is 4.6.2) your web application dll was loaded into the IIS worker process, w3wp.exe, together with an instance of the .NET Framework. In IIS each application pool corresponds to 1 worker process, so if 2 web applications shared an application pool then the worker process would load each web application dll and one instance of .NET Framework.

In ASP.NET Core (latest version 1.0) your web application is loaded into it's own separate process together with an instance of Kestrel - together called ASP.NET Core App Host. The ASP.NET Core App Host process is startet by dotnet run, which is executed by ASP.NET Core Module from within IIS. The ASP.NET Core App Host will through Kestrel listen to a specific port and the ASP.NET Core Module will forward requests to that port.



In the above schematic IIS will map (eg. through http host header) an http request to a specific web application. The web application uses a web.config file to configure IIS to use ASP.NET Core Module for this web application. ASP.NET Core Module will use dotnet to load the web application as an ASP.NET Core App Host in an external process setting up a port (default 5000) based communication between the ASP.NET Core Module and the ASP.NET Core App Host. ASP.NET Core Module is then forwarding http requests to ASP.NET Core App Host. Inside of ASP.NET Core App Host the Kestrel part will poll the port and then receiving a request building an array of context relevant objects all collected into HttpContext, which is then made available for the ASP.NET Core App.

While indeed there are other ways to host ASP.NET Core, the above schematic is the current Microsoft recommended way to host ASP.NET Core on a Windows server (note that Kestrel is a cross platform web server and while I often read about how fast Kestrel is, the upcoming Windows only web server called WebListener should be even faster - as WebListener matures Microsoft may change their recommendation to use WebListener on Windows servers).

The ASP.NET Core App Host is running by itself and listening to http requests by itself as well - it will work all by itself. It is NOT necessary to use IIS or another webserver as a frontend (reverse proxy) for the ASP.NET Core App Host. However there are several reasons why the reverse proxy topology recommeded by microsoft is a good idea, here are some : (I probably don't get them all)

Kestrel does NOT support http host header redirect - so with Kestrel only we can have only one web application on port 80.

ASP.NET Core module guarantees that the ASP.NET Core App Host is loaded and also restarted if necessary - if manually starting up an ASP.NET Core App Host from the command prompt and the process crashes, you are responsible yourself to startup the app again.

IIS can handle cashing, SSL and static content compression (I am not confident to which extent Kestrel can do these and there may be a host of other details better handled by IIS).



Prepare IIS & Production server

ASP.NET Core can run on either .NET Framework (latest version 4.6.2) or .NET Core (latest version 1.0). If the ASP.NET Core App is targeting .NET Framework then the .NET Framework runtime must be loaded within the ASP.NET Core App Host process, while if the ASP.NET Core App is targeting .NET Core then the .NET Core runtime must be loaded within the ASP.NET Core App Host process.

Then you publish an ASP.NET Core App from within Visual Studio and that App is targeting .NET Core, then the .NET Core Runtime is added to the published output (together with other library dependencies for that particular app) and will be loaded as part of the ASP.NET Core App Host - this means we do NOT need to install .NET Core Runtime on the production server if hosting only Visual Studio published ASP.NET Core Apps.

Then you publish an ASP.NET Core App using whatever means and that App is targeting .NET Framework, then the .NET Framework is NOT added to the published output (only specific library dependencies for that particular app) - this means that we DO need to install .NET Framework runtime on the production server if hosting ASP.NET Core Apps targeting .NET Framework.

ASP.NET Core targeting .NET Framework : .NET Framework NEED to be installed on the production server.

ASP.NET Core targeting .NET Core : .NET Core does NOT necessarily need to be installed on the production server.

Install ASP.NET Core Module :

Note that the ASP.NET Core Module installer also contains dotnet so that ASP.NET Core Module can use dotnet to startup an ASP.NET Core App Host.

Download the ASP.NET Core Module installer from Microsoft here : https://www.microsoft.com/net/download

Double click on the ASP.NET Core Module installer to install it.

Confirm that the ASP.NET Core Module is installed :

You can either use applicationHost.config :

Open a file explorer and navigate to C:\Windows\System32\inetsrv\config and open applicationHost.config in any text editor.

In applicationHost.config find the <globalModules> section and confirm the existence of ASP.NET Core Module.

Or you can use IIS Manager :

In IIS Manager click on the server root and select Modules.

Confirm that ASP.NET Core Module is installed.

Install .NET Core SDK :

Installing .NET Core SDK (or alternatively but less flexible .NET Core runtime standalone) is ONLY necessary if you want to compile ASP.NET Core Apps directly on the production server (which indeed you may want) or if you want to host ASP.NET Core Apps that have been published without amending the .NET Core Runtime.

.NET Core SDK contains .NET Core (that is the .NET Core runtime and libraries) as well as the command line version dotnet. With .NET Core SDK it is therefore possible to build & start ASP.NET Core Apps from the command line allowing us among other things to self host an ASP.NET Core App without using a reverse proxy.

Download the .NET Core SDK installer from Microsoft here : https://www.microsoft.com/net/download

Double click on the .NET Core SDK installer to install it.

Confirm that the .NET Core SDK is installed :

Open a command console and execute the following commands :
shell> cd /

shell> mkdir testCoreSdk

shell> cd testCoreSdk

shell> dotnet new : creates a new C# .NET Core application in current folder.

shell> dotnet restore : reads the project.json file and downloads all dependencies specified in project.json.

shell> dotnet run : compiles and starts the .NET Core application.

In the command console, you should see a "Hello World".

Install .NET Framework :

Installing .NET Framework is ONLY necessary if you want to build ASP.NET Classic applications OR if you want to build ASP.NET Core Apps targeting .NET Framework (instead of targeting .NET Core).

Download the .NET Framework installer from Microsoft here : https://www.microsoft.com/net/download

Double click on the .NET Framework installer to install it.

Confirm that the .NET Framework is installed :
Open the Registry Editor.

Navigate to HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full

Check the value of the Release key :

394806 : .NET Framework 4.6.2

394271 : .NET Framework 4.6.1

See full list of values here.



Prepare you web application

Create a new web application, here in Visual Studio :

Open Visual Studio.

From the Visual Studio menu select Files -> New -> Project.

In the "New Project" dialog left pane select Installed -> Templates -> Web

In the "New Project" dialog web menu, you have 3 project options in the right pane :

An ASP.NET Classic application targeting .NET Framework - this project type have a very different hosting topology, which this tutorial will not discuss.

An ASP.NET Core application targeting .NET Framework - most powerful API available.

An ASP.NET Core application targeting .NET Core - cross platform.

Select any of the 2 ASP.NET Core project types and give it a name, eg. select ASP.NET Core targeting .NET Core and name the project testAspNetCore

In the "Select a template" dialog select Web Application to get some MVC related file structure auto created (MVC and WebApi is actually the same thing (exact same thing), however the templates differ a little bit).

After Visual Studio have created the project template files, you will need to wait a little bit while Visual Studio automatically downloads listed dependencies in the project.json file.

Be sure to know your project.json file :

In Visual Studio Solution Explorer open the project.json file.
Depending whether your ASP.NET Core App is targeting .NET Framework or .NET Core, you will get slightly different project.json - most significantly the frameworks{} section will be different :

: targeting .NET Core.

: targeting .NET Framework.

Be sure to know your Program.cs file :

In Visual Studio Solution Explorer open the Program.cs file.

Your ASP.NET Core App Host must load a webserver in its own process, this means that a webserver (typically Kestrel or WebListener) needs to be chosen at application start. With ASP.NET Core 1 RTM, the entry point of the ASP.NET Core App was moved from Startup to Program and now looks like this : (Visual Studio 2015 Update 3 template)

using System.IO;
using Microsoft.AspNetCore.Hosting;

namespace testNetCore
{
public class Program
{
public static void Main(string[] args)
{
var host = new WebHostBuilder()
.UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory())
.UseIISIntegration()
.UseStartup<Startup>()
.Build();

host.Run();
}
}
}

The Program entry point, Main, is called by dotnet run and starts up the ASP.NET Core App Host as a console application. In Main we instantiate a WebHostBuilder by which we build, configure and startup the ASP.NET Core App Host.

The Visual Studio template added configurations are : (see more WebHostBuilder documentation here)

.UseKestre() : Specifying an IServer is mandatory, here we tell IWebHost to use Kestrel.

.UseContentRoot(Directory.GetCurrentDirectory()) : ContentRoot determines where the server will search for content files like eg. MVC View files. Since Program.cs is located in the project folder, Directory.GetCurrentDirectory() will return the project folder.

.UseIISIntegration() : Obviously specifies that we will use IIS as a reverse proxy, however I don't understand exactly what UseIISIntegration will be doing (since ASP.NET Core Module is just forwarding requests to Kestrel, why does the IWebHost, ASP.NET Core App Host, need to know anything about it).

.UseStartup<Startup>() : The most easy way to configure our ASP.NET Core App is to use the Startup class, here we specify that we want to do it that way.

.Build : builds an IWebHost, the ASP.NET Core App Host, to host the ASP.NET Core App.

Note that the template code call .Run() on the IWebHost. We could instead call just .Start() to start listening on the configured addresses. However .Run() will in addition to invoking .Start() also block the calling thread until the host is shut down.

Publish your web application :

Here we will publish to local file system first and then in the next section copy the published project to production server.

In Visual Studio Solution Explorer right click on the project name node and select Publish...

To continue publishing the project you will need a profile :

You already have a publishing profile and just need to select it.

You do NOT have a publishing profile and need to create a profile :

Click on the Custom button.

In the "New Custom Profile" popup box just write a name, eg. your own name, and then click the Ok button.

Ok, you now have a publishing profile.

Select the Connection tab and set the Publish method to FileSystem and note the Target location - you need it later then copying the published files to the production server.

Select the Settings tab and set :

Configuration : Release or Debug - note that if changing to Debug the target location in the Connection tab will change.

Target Framework : can currently NOT be selected (that may change in the future) but is set from the project.json frameworks{} section

Target Runtime : can also currently NOT be selected (that may change in the future) but is also set from the project.json frameworks{} section :

Target Framework = .NET Core => Target Runtime = Any.

Target Framework = .NET Framework => Target Runtime = win7-x64 (I am not sure if other runtimes are or will be available, eg. win7-x86)

Select the Preview tab to confirm the Target location and click on the Publish button.

Open a file explorer and confirm you can find your published files, in my case it is C:\inetpub\wwwroot\_sandbox\testAspNetCore\src\testAspNetCore\bin\Release\PublishOutput



Creating the IIS website

Copy published project to production server

Create a folder on your production IIS server to host all the published files - in my case C:\Websites\TestAspNetCore

Copy the published files :

Source location : Dev machine - C:\inetpub\wwwroot\_sandbox\testAspNetCore\src\testAspNetCore\bin\Release\PublishOutput

Target location : Production server - C:\Websites\TestAspNetCore

Be sure to know your web.config file

Then publishing an ASP.NET Core App, the template added web.config file will be rewritten to the following :

<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.webServer>
<handlers>
<add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModule" resourceType="Unspecified" />
</handlers>
<aspNetCore processPath="dotnet" arguments=".\testAspNetCore.dll" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" forwardWindowsAuthToken="false" />
</system.webServer>
</configuration>

Then a request is coming for an IIS website, IIS will load any handlers and forward the request to these handlers, here AspNetCoreModule. In addition the above web.config tells the ASP.NET Core Module to execute dotnet with the argument of the ASP.NET Core App DLL.

Note, you can compare the unpublished template created web.config with the published version and see the difference.

Create a new site in IIS

Open IIS and add a new website to the server root.

In the "Add Website" dialog fill in the relevant information, especially notice :

Application pool : default a new web application will run under it's own application pool of the same name as the web application - this we also prefer this time.

Physical path : C:\Websites\TestAspNetCore - physical path MUST point to the folder of published files.

Host name : testaspnetcore.com - http1/1 will contain the domain in the header and IIS will use that header value to map the request to a specific website (note that the Host name you set in IIS have nothing to do with how the request find the IIS - it only take effect AFTER the request have found IIS, IIS will then further map the request to a specific website).

You should now see your web application in the Sites list (if your new web application does not show up under Sites in the left pane, just right click on Sites and choose Refresh).

In IIS Manager navigate to "Application Pools", then right click on the application pool that your web application is running under and select "Advanced Settings".

In the "Advanced Settings" dialog change ".NET CLR Version" to "No Managed Code" and click the OK button.
Whether your ASP.NET Core App is targeting .NET Framwework or .NET Core, the IIS website worker process, w3wp.exe, will not load any managed code only the ASP.NET Core Module - therefore the worker process should not load .NET Framework nor .NET Core (whatever runtime your ASP.NET Core App is targeting, that runtime will run within the ASP.NET Core App Host process).

DNS Mapping

If you have mapped the IIS website to a public domain you don't need to do this step. However in this totorial I have mapped the IIS website to an ad-hoc domain, testaspnetcore.com. None of my computers knows the IP address of testaspnetcore.com, so if I write http://testaspnetcore.com in my browser, the browser will NOT be able to resolve the domain to the IP address of the production server.

To be able to browse testaspnetcore.com, the browser need to be able to resolve testaspnetcore.com into the IP of the production server there testaspnetcore.com is hosted.

On your development machine open a file explorer and navigate to C:\Windows\System32\drivers\etc.

From the C:\Windows\System32\drivers\etc folder open the hosts file in a text editor.

Add a record for testaspnetcore.com pointing to the IP of your production server :

192.168.1.214 : IP of the my test production server (you need to specify the IP of your own production server).

testAspNetCore.com : domain that IIS on the production server will host header map to the IIS website.

After saving your hosts file all programs (including ping & your browsers) will be able to resolve testaspnetcore.com into the IP of your production server.

Open a command console and ping your domain : shell> ping testaspnetcore.com to test that indeed your development machine can resolve the domain correctly.

Test it works

Open a browser on the IIS mapped url - in my case testaspnetcore.com.

Congratulations, you should now understand how to host ASP.NET Core Apps using IIS as a reverse proxy - the Microsoft recommended ASP.NET Core hosting topology for windows.



Appendix : Create a self hosted ASP.NET Core App

A self hosted ASP.NET Core App just means an ASP.NET Core App Host that is not hiding behind a reverse proxy and instead is facing direct access from the outside (typically the internet).

Open a command console.

shell> cd /

shell> mkdir testSelfHost

Copy ALL files from your project folder on your development machine to your C:\testSelfHost on your production machine.

shell> cd C:\testSelfHost

shell> dotnet run : the ASP.NET Core App Host may be compiled and then started by invoking Program.Main.
Important : the host will output the domains & ports that it is listening on - default and in my case it is localhost:5000.

Test it out in a browser on your PRODUCTION machine.

Changing the domain and port :
Default dotnet run will set the domain to localhost and the port to 5000, however you can change it (here using the command line) using the ASPNETCORE_URLS environment variable.

If your ASP.NET Core App Host process is running in your command console, the press ctrl+c to end the host process.

shell> SET ASPNETCORE_URLS=https://*:5123 && dotnet run : start the ASP.NET Core App Host again but this time set the host to anything and the port to 5123.

Test it out in a browser on your DEVELOPMENT machine.

Changing the environment :
The environment can have 3 different values : Development, Staging or Production. Default dotnet run will set the environment to Production, however you can change it (here using the command line) using the ASPNETCORE_ENVIRONMENT environment variable.

If your ASP.NET Core App Host process is running in your command console, the press ctrl+c to end the host process.

shell> SET ASPNETCORE_URLS=https://*:5123 && ASPNETCORE_ENVIRONMENT=Staging && dotnet run : start the ASP.NET Core App Host again this time not only setting the host to anything and the port to 5123 but also setting the environment to Staging.

Using the command line to set host, port & environment is a little cumbersome, it would be great if in the future we could set host, port & environment as parameters, eg. like this : shell> dotnet run -h * -p 5123 -e production



Appendix : Understanding Proxies

In general a proxy is an entity that acts on behalf of another entity, eg. a person granted power of attorny can act on behalf of you in legal matters. However, in IT a proxy is typically a process that acts on behalf of another process.

In IT we talk about forward proxies and reverse proxies :

Forward proxy : acts on behalf of a client (a requesting host) or multiple clients.

Reverse proxy : acts on behalf of a server (a responding host) or multiple servers.

Forward proxy

The image below shows how then a client on a network tries to access a target server, the client is routed instead to a forward proxy. The forward proxy will then create a new independent request to the target server and forward the response back to the client that initiated a request. The target server creating the response thinks the request comes from the forward proxy and does not know anything about any client behind the forward proxy.



The advantages of a forward proxy are :

Increased security because :

Hackers cannot know anything about clients behind the forward proxy.

System admin can implement internet security rules on a single machine instead of all machines on the LAN.

Increased speed if implementing cache on the forward proxy since identitical response payloads does not need to transfer all the way from the actual response creator.

Reverse proxy

The image below shows how then a client tries to access a service, let's say a file transfer service, the client is told that the service resides on the reverse proxy IP, however the reverse proxy does not actually contain the service itself but will request the relevant server that do contain the service and send the response back to the client.



The advantages of a reverse proxy are :

Easy to scale to load balancing (in fact the only topology difference between reverse proxy and load balancing is that a reverse proxy also gives meaning with only 1 server).

Increased security because :

Hackers cannot know anything about servers behind the reverse proxy.

System admin can implement security rules on a single point of access instead of on all the servers.

Hackers can avoid their real servers being blocked (or even shut down) then a reverse proxy is identified as a malware source.

Reverse proxies will often be responsible for caching in which case a reverse proxy will increase the speed then response creation can be skipped.

In case of load balancing also :

Increased availability because failure detection will allow the reverse proxy to avoid diverting traffic to the failing servers.

Increased speed because multiple servers are in works.



Appendix : Common errors and solutions

The program can't start because api-ms-win-crt-runtime-l1-1-0.dll is missing from your computer.

In addition you will see HTTP Error 502.5 - Process Failure if you try to request your site in a browser.

When : Executing dotnet whether from a command prompt or by ASP.NET Core module.

Reason : The following often repeated quote may describe the reason "The problem is that the KB2999226 (Universal CRT) which is part of the Visual C++ Redistributable for Visual Studio 2015 failed to install".

Solution : (for all 3 downloads mentioned in this solution be sure to select correct image size : x86 or x64)

Open Windows Update and select Check for updates. Keep updating, restarting and check for updates until no more updates are available.

Check if dotnet is working - if not then continue :

Uninstall any current version of Visual C++ Redistributable (Control Panel -> Programs -> Programs and Features -> Uninstall a program)

Download Visual C++ Redistributable (https://beta.visualstudio.com/downloads/ - scroll down to find Visual C++ Redistributable)

Install the just downloaded Visual C++ Redistributable.

Check if dotnet is working - if not then continue :

Download KB2975061 (https://www.microsoft.com/en-us/download/details.aspx?id=43530) and install it (KB2975061 seems to be a Windows 8.1 only patch, however it works well on Windows 2012 R2 and is NECESARY to successfully install the next patch KB2919355).

Download KB2919355 (https://www.microsoft.com/en-us/download/details.aspx?id=42335) and install it (very big file).

Open Windows Update again and select Check for updates. Keep updating, restarting and check for updates until no more updates are available.

Check if dotnet is working - indeed it should be working now

HTTP Error 502.5 - Process Failure.

When : Requesting your ASP.NET Core app in a browser.

I have personally had this error for the following 5 separate reasons :

Reason 1 : ASP.NET Core Module have not been installed

Reason 2 : dotnet have not been installed

Reason 3 : dotnet cannot execute (see error 1 above how to solve that)

Reason 4 : Trying to host an ASP.NET Core App targeting .NET Framework (instead of .NET Core) without .NET Framework have been installed

Reason 5 : Incompatible package versions in project.json, which happened because I used one of Visual Studio project templates which wrote out a huge project.json and in project.json I then updated .NET Core from 1.0.0 to 1.1.0 but missed one of the template written packages which then became incompatible.

Solution 1 : Download ASP.NET Core Module and install it.

Solution 2 : If ASP.NET Core Module is installed, then dotnet should also be installed. However if you install say ASP.NET Core Module and ASP.NET Core SDK and then de-install ASP.NET Core SDK, then dotnet will be de-installed as well even if the ASP.NET Core Module is still installed and working. One way to solve the problem is to repair your ASP.NET Core Module installation either by double click on the ASP.NET Core Module installer and select repair OR go through Control Panel -> Uninstall Programs and right click on the ASP.NET Core Module and select Change from the shortcut menu which will also launch the ASP.NET Core Module installer from which you can then select Repair.

Solution 3 : See above error 1 for how to solve that problem.

Solution 4 : Download .NET Framework (latest version is 4.6.2) and install it.

Solution 5 : Correct the version incompatibilities :

First debug Program.Main to get a meaningful error, in my case :

An unhandled exception of type 'System.IO.FileLoadException' occurred in xxx.dll

Additional information: Could not load file or assembly 'Microsoft.Extensions.Configuration.EnvironmentVariables, Version=1.1.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60'. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)

From the debug error it was possible to detect the package with the wrong version - Intellisense had even warned me, but apparently I had ignored it.

In my case I could update version from 1.0.0 to 1.1.0, which matched the .NET Core version specified.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: