Asp.Net Core 項目運行部署到發布


1.項目創建

使用Visual Studio 2019 創建一個Asp.NetCore WebApplication 並選擇MVC項目命名為OnePublish。

 確認運行無誤后我們來探討一下Asp.NetCore項目的運行啟動方式以及他與Asp.Net的區別。

2.項目運行

IIS Express運行效果:

結果不出乎意料和Asp.Net相似都能成功的運行Web項目,但在Asp.NetCore中新增了一種使用CommandLine運行的方式,我們可以從配置文件或者VS設置中可以看出。

項目屬性設置:

 LaunchSettings.json

 1 {
 2   "iisSettings": {
 3     "windowsAuthentication": false,
 4     "anonymousAuthentication": true,
 5     "iisExpress": {
 6       "applicationUrl": "http://localhost:54012",
 7       "sslPort": 0
 8     }
 9   },
10   "profiles": {
11     "IIS Express": {
12       "commandName": "IISExpress",
13       "launchBrowser": true,
14       "environmentVariables": {
15         "ASPNETCORE_ENVIRONMENT": "Development"
16       }
17     },
18     "OnePublish": {
19       "commandName": "Project",
20       "launchBrowser": true,
21       "applicationUrl": "http://localhost:5000",
22       "environmentVariables": {
23         "ASPNETCORE_ENVIRONMENT": "Development"
24       }
25     }
26   }
27 }

我們可以看見以"OnePublish"為名的CommandLine也可以成功運行Web項目,那Asp.NetCore是如何做到從命令行實現Web項目的呢?

原因在於ASP.NET Core不再是由IIS工作進程(w3wp.exe)托管,而是使用自托管Web服務器(Kestrel)運行,IIS則是作為反向代理的角色轉發請求到Kestrel不同端口的ASP.NET Core程序中,隨后就將接收到的請求推送至中間件管道中去,處理完你的請求和相關業務邏輯之后再將HTTP響應數據重新回寫到IIS中,最終轉達到不同的客戶端(瀏覽器,APP,客戶端等)。

官方文檔圖解:

Kestrel used as an edge (Internet-facing) web server:

Kestrel used in a reverse proxy configuration:

我的理解為:當Kestrel作為Eage Server監聽某一個ip或者端口時,它可以接受所有由該端口發送的信息並解決他們的請求。但當有反向代理的存在時如(IIS,Nginx,Apache),反向代理可以接受多個Kestrel托管的端口來接受他們的信息並完成他們的請求。總結來說在Asp.NetCore中Kestrel已經組成一個完整的生態,而代理服務器大多起一個監聽的作用了。那Kestrel在哪里啟動的呢?

首先我們來觀察一下這兩個類文件。

 Program.cs:

 1 using Microsoft.AspNetCore.Hosting;
 2 using Microsoft.Extensions.Hosting;
 3 
 4 namespace OnePublish
 5 {
 6     public class Program
 7     {
 8         public static void Main(string[] args)
 9         {
10             CreateHostBuilder(args).Build().Run();
11         }
12 
13         public static IHostBuilder CreateHostBuilder(string[] args) =>
14             Host.CreateDefaultBuilder(args)
15                 .ConfigureWebHostDefaults(webBuilder =>
16                 {
17                     webBuilder.UseStartup<Startup>();
18                 });
19     }
20 }

我們知道Main函數一般為程序的入口。在此函數中我們可以看見是調用了一系列方法,這可能還不夠簡單明了,我們對此方法做一點簡化。

1 public static void Main(string[] args)
2         {
3             var hostBuilder = CreateHostBuilder(args);
4             var host = hostBuilder.Build();
5             host.Run();
6         }

現在我們可以理解為它使用CreateHsotBuilder()方法創建了一個hostBuilder,在利用hostBuilder創建了一個host主機實體對象,在Run這個Host主機。

那么這個HostBuiler到底做了什么配置又創建了一些什么東西呢?

我們對源碼進行解讀一下:

 1 public static IHostBuilder CreateDefaultBuilder(string[] args)
 2     {
 3       HostBuilder hostBuilder = new HostBuilder();
 4       hostBuilder.UseContentRoot(Directory.GetCurrentDirectory());
 5       hostBuilder.ConfigureHostConfiguration((Action<IConfigurationBuilder>) (config =>
 6       {
 7         config.AddEnvironmentVariables("DOTNET_");
 8         if (args == null)
 9           return;
10         config.AddCommandLine(args);
11       }));
12       hostBuilder.ConfigureAppConfiguration((Action<HostBuilderContext, IConfigurationBuilder>) ((hostingContext, config) =>
13       {
14         IHostEnvironment hostingEnvironment = hostingContext.HostingEnvironment;
15         config.AddJsonFile("appsettings.json", true, true).AddJsonFile("appsettings." + hostingEnvironment.EnvironmentName + ".json", true, true);
16         if (hostingEnvironment.IsDevelopment() && !string.IsNullOrEmpty(hostingEnvironment.ApplicationName))
17         {
18           Assembly assembly = Assembly.Load(new AssemblyName(hostingEnvironment.ApplicationName));
19           if (assembly != (Assembly) null)
20             config.AddUserSecrets(assembly, true);
21         }
22         config.AddEnvironmentVariables();
23         if (args == null)
24           return;
25         config.AddCommandLine(args);
26       })).ConfigureLogging((Action<HostBuilderContext, ILoggingBuilder>) ((hostingContext, logging) =>
27       {
28         int num = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? 1 : 0;
29         if (num != 0)
30           logging.AddFilter<EventLogLoggerProvider>((Func<LogLevel, bool>) (level => level >= LogLevel.Warning));
31         logging.AddConfiguration((IConfiguration) hostingContext.Configuration.GetSection("Logging"));
32         logging.AddConsole();
33         logging.AddDebug();
34         logging.AddEventSourceLogger();
35         if (num == 0)
36           return;
37         logging.AddEventLog();
38       })).UseDefaultServiceProvider((Action<HostBuilderContext, ServiceProviderOptions>) ((context, options) =>
39       {
40         bool flag = context.HostingEnvironment.IsDevelopment();
41         options.ValidateScopes = flag;
42         options.ValidateOnBuild = flag;
43       }));
44       return (IHostBuilder) hostBuilder;
45     }

可以看到它對路徑做了一個默認的規定,並的確的使用的CommandLine並可接受參數,這也是為什么我們可以通過CommandLine控制Web程序的原因,還有對appsettings.json文件的引用,從這里我們可以看出我們也是可以自定義配置文件的。還添加了Logging這些基本功能。

繼續向源碼解讀可以看到在ConfigureWebDefaults方法中,Asp.NetCore確實使用了Kestrel並對他的一些option進行了默認的規定。到這里我們就基本了明白了Asp.NetCore WebApplication的啟動流程了。

internal static void ConfigureWebDefaults(IWebHostBuilder builder)
    {
      builder.ConfigureAppConfiguration((Action<WebHostBuilderContext, IConfigurationBuilder>) ((ctx, cb) =>
      {
        if (!ctx.HostingEnvironment.IsDevelopment())
          return;
        StaticWebAssetsLoader.UseStaticWebAssets(ctx.HostingEnvironment, ctx.Configuration);
      }));
      builder.UseKestrel((Action<WebHostBuilderContext, KestrelServerOptions>) ((builderContext, options) => options.Configure((IConfiguration) builderContext.Configuration.GetSection("Kestrel")))).ConfigureServices((Action<WebHostBuilderContext, IServiceCollection>) ((hostingContext, services) =>
      {
        services.PostConfigure<HostFilteringOptions>((Action<HostFilteringOptions>) (options =>
        {
          if (options.AllowedHosts != null && options.AllowedHosts.Count != 0)
            return;
          string str = hostingContext.Configuration["AllowedHosts"];
          string[] strArray1;
          if (str == null)
            strArray1 = (string[]) null;
          else
            strArray1 = str.Split(new char[1]{ ';' }, StringSplitOptions.RemoveEmptyEntries);
          string[] strArray2 = strArray1;
          HostFilteringOptions filteringOptions = options;
          string[] strArray3;
          if (strArray2 == null || strArray2.Length == 0)
            strArray3 = new string[1]{ "*" };
          else
            strArray3 = strArray2;
          filteringOptions.AllowedHosts = (IList<string>) strArray3;
        }));
        services.AddSingleton<IOptionsChangeTokenSource<HostFilteringOptions>>((IOptionsChangeTokenSource<HostFilteringOptions>) new ConfigurationChangeTokenSource<HostFilteringOptions>(hostingContext.Configuration));
        services.AddTransient<IStartupFilter, HostFilteringStartupFilter>();
        if (string.Equals("true", hostingContext.Configuration["ForwardedHeaders_Enabled"], StringComparison.OrdinalIgnoreCase))
        {
          services.Configure<ForwardedHeadersOptions>((Action<ForwardedHeadersOptions>) (options =>
          {
            options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
            options.KnownNetworks.Clear();
            options.KnownProxies.Clear();
          }));
          services.AddTransient<IStartupFilter, ForwardedHeadersStartupFilter>();
        }
        services.AddRouting();
      })).UseIIS().UseIISIntegration();
    }

3.區別:

在我看來Asp.Net就像一個全家桶,在我默認使用框架中基本上包含了所有進行Web開發的框架如HttpContext,Session等。而Asp.NetCore更像是一個自選桶你可以在StartUp.cs中自定義的添加你需要的Services。在我看來,Asp.NetCore變得更加透明和更加靈活了。

4.部署和發布。

1. 我們將此項目用文件系統打包部署到本地即可。點擊Publish即可。

2. 確保打開Windows的IIS服務。

 確保IIS中安裝了AspNetCoreModule.

 若無安裝(去安裝):下載安裝即可

 現在來添加IIS服務

 

 

 運行成功,即發布成功了。

 若不能成功運行請檢查部署目錄中是否有此文件。

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM