• 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服务

     

     

     运行成功,即发布成功了。

     若不能成功运行请检查部署目录中是否有此文件。

     

     

  • 相关阅读:
    Silverlight实例教程
    Silverlight实例教程
    Delphi:ADOConnection连接SQLServer自动断网问题解决
    用delphi写多屏幕程序
    GitHub中watch、star、fork的作用
    JFinal Weixin 1.6发布【转】
    JFinal2.0极速开发视频教程发布【转】
    Android之Http通信——1.初识Http协议
    UVa 10986
    重写MPAndroidChart显示标记
  • 原文地址:https://www.cnblogs.com/Xieyiincuit/p/13797235.html
Copyright © 2020-2023  润新知