• ASP.NET Core 系列[1]:ASP.NET Core 初识


    ASP.NET Core 是一个跨平台的高性能开源框架,是一个用于连接到互联网的基于云的现代应用程序。 ASP.NET Core 用于构建如 Web 应用、物联网(IoT)应用和移动后端应用,这些应用可以在 .NET Core 或 .NET Framework上运行,你可以在 Windows、Mac 和 Linux 上跨平台的开发和运行你的 ASP.NET Core 应用。

    ASP.NET Core项目解读

    由于相比以前传统的ASP.NET项目而言, ASP.NET Core 的项目结构也变的完全不同,对于刚接触 ASP.NET Core 的小白来讲,我觉得有必要来简单解读一下。

    注:这里的解读是针对ASP.NET Core 2.1

    项目文件夹总预览

    Program类

        public class Program
        {
            public static void Main(string[] args)
            {
                CreateWebHostBuilder(args).Build().Run();
            }
    
            public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
                WebHost.CreateDefaultBuilder(args)
                    .UseStartup<Startup>();
        }

    我们可以看到程序中有一个 Program 类型,按照我们以前的认知,这个类不是只出现在控制台项目中的嘛。那么接下来我们来看看这个类里面都有些什么,又都干了什么。

    WebHost

    webHost相当于一个用Socket实现的Web服务。

    1、WebHost使用了建造者模式

    2、CreateDefaultBuilder:我们用反编译工具来查看下这个方法里面都干了什么。

    public static IWebHostBuilder CreateDefaultBuilder(string[] args)
    {
        IWebHostBuilder arg_31_0 = new WebHostBuilder();
        Action<WebHostBuilderContext, KestrelServerOptions> arg_31_1;
        if ((arg_31_1 = WebHost.<>c.<>9__8_0) == null)
        {
            arg_31_1 = (WebHost.<>c.<>9__8_0 = new Action<WebHostBuilderContext, KestrelServerOptions>(WebHost.<>c.<>9.<CreateDefaultBuilder>b__8_0));
        }
        IWebHostBuilder arg_70_0 = HostingAbstractionsWebHostBuilderExtensions.UseContentRoot(WebHostBuilderKestrelExtensions.UseKestrel(arg_31_0, arg_31_1), Directory.GetCurrentDirectory()).ConfigureAppConfiguration(delegate(WebHostBuilderContext hostingContext, IConfigurationBuilder config)
        {
            IHostingEnvironment hostingEnvironment = hostingContext.get_HostingEnvironment();
            JsonConfigurationExtensions.AddJsonFile(JsonConfigurationExtensions.AddJsonFile(config, "appsettings.json", true, true), string.Format("appsettings.{0}.json", hostingEnvironment.get_EnvironmentName()), true, true);
    if (HostingEnvironmentExtensions.IsDevelopment(hostingEnvironment))
            {
                Assembly assembly = Assembly.Load(new AssemblyName(hostingEnvironment.get_ApplicationName()));
                if (assembly != null)
                {
                    UserSecretsConfigurationExtensions.AddUserSecrets(config, assembly, true);
                }
            }
            EnvironmentVariablesExtensions.AddEnvironmentVariables(config);
            if (args != null)
            {
                CommandLineConfigurationExtensions.AddCommandLine(config, args);
            }
        });
        Action<WebHostBuilderContext, ILoggingBuilder> arg_70_1;
    if ((arg_70_1 = WebHost.<>c.<>9__8_2) == null)
        {
            arg_70_1 = (WebHost.<>c.<>9__8_2 = new Action<WebHostBuilderContext, ILoggingBuilder>(WebHost.<>c.<>9.<CreateDefaultBuilder>b__8_2));
        }
        IWebHostBuilder arg_94_0 = WebHostBuilderExtensions.ConfigureLogging(arg_70_0, arg_70_1);
        Action<WebHostBuilderContext, IServiceCollection> arg_94_1;
        if ((arg_94_1 = WebHost.<>c.<>9__8_3) == null)
        {
            arg_94_1 = (WebHost.<>c.<>9__8_3 = new Action<WebHostBuilderContext, IServiceCollection>(WebHost.<>c.<>9.<CreateDefaultBuilder>b__8_3));
        }
        IWebHostBuilder arg_BD_0 = WebHostBuilderIISExtensions.UseIISIntegration(arg_94_0.ConfigureServices(arg_94_1));
        Action<WebHostBuilderContext, ServiceProviderOptions> arg_BD_1;
        if ((arg_BD_1 = WebHost.<>c.<>9__8_4) == null)
        {
            arg_BD_1 = (WebHost.<>c.<>9__8_4 = new Action<WebHostBuilderContext, ServiceProviderOptions>(WebHost.<>c.<>9.<CreateDefaultBuilder>b__8_4));
        }
        IWebHostBuilder webHostBuilder = WebHostBuilderExtensions.UseDefaultServiceProvider(arg_BD_0, arg_BD_1);
        if (args != null)
        {
            HostingAbstractionsWebHostBuilderExtensions.UseConfiguration(webHostBuilder, CommandLineConfigurationExtensions.AddCommandLine(new ConfigurationBuilder(), args).Build());
        }
        return webHostBuilder;
    }

    以下是Action<WebHostBuilderContext, KestrelServerOptions> arg_31_1;委托的逻辑

    internal void <CreateDefaultBuilder>b__8_0(WebHostBuilderContext builderContext, KestrelServerOptions options)
    {
        options.Configure(builderContext.get_Configuration().GetSection("Kestrel"));
    }

    以下是Action<WebHostBuilderContext, IServiceCollection> arg_94_1;委托的逻辑

    internal void <CreateDefaultBuilder>b__8_3(WebHostBuilderContext hostingContext, IServiceCollection services)
    {
        WebHost.<>c__DisplayClass8_1 <>c__DisplayClass8_ = new WebHost.<>c__DisplayClass8_1();
        <>c__DisplayClass8_.hostingContext = hostingContext;
        OptionsServiceCollectionExtensions.PostConfigure<HostFilteringOptions>(services, new Action<HostFilteringOptions>(<>c__DisplayClass8_.<CreateDefaultBuilder>b__5));
        ServiceCollectionServiceExtensions.AddSingleton<IOptionsChangeTokenSource<HostFilteringOptions>>(services, new ConfigurationChangeTokenSource<HostFilteringOptions>(<>c__DisplayClass8_.hostingContext.get_Configuration()));
        ServiceCollectionServiceExtensions.AddTransient<IStartupFilter, HostFilteringStartupFilter>(services);
    }

    以下是Action<WebHostBuilderContext, ServiceProviderOptions> arg_BD_1;委托的逻辑

    internal void <CreateDefaultBuilder>b__8_4(WebHostBuilderContext context, ServiceProviderOptions options)
    {
        options.set_ValidateScopes(HostingEnvironmentExtensions.IsDevelopment(context.get_HostingEnvironment()));
    }

    以下是Action<WebHostBuilderContext, ILoggingBuilder> arg_70_1委托的逻辑

    internal void <CreateDefaultBuilder>b__8_2(WebHostBuilderContext hostingContext, ILoggingBuilder logging)
    {
        LoggingBuilderExtensions.AddConfiguration(logging, hostingContext.get_Configuration().GetSection("Logging"));
        logging.AddConsole();
        DebugLoggerFactoryExtensions.AddDebug(logging);
    }

    由以上代码我们可以得出以下结论:

      a.添加Kestrel和IIS的web服务器

      b.添加Configuration配置系统

        支持 appsettings.json 和多环境的 appsettings.{0}.json

        支持CommandLine

      c.添加日志系统(这里通过反编译WebHostBuilderExtensions扩展类,可以知道是调用了IServiceCollection的AddLogging扩展方法,然后我们转到 LoggingServiceCollectionExtensions扩展类,找到AddLogging扩展方法,然后将日志注入到IServiceCollection)

         默认添加对Console和Debug的输出

    3、UseStartup:通过反编译查看源代码

            public static IWebHostBuilder UseStartup(this IWebHostBuilder hostBuilder, Type startupType)
            {
                string str = IntrospectionExtensions.GetTypeInfo(startupType).get_Assembly().GetName().get_Name();
                return hostBuilder.UseSetting(WebHostDefaults.ApplicationKey, str).ConfigureServices(delegate (IServiceCollection services) {
                    if (IntrospectionExtensions.GetTypeInfo((Type) typeof(IStartup)).IsAssignableFrom(IntrospectionExtensions.GetTypeInfo(startupType)))
                    {
                        services.AddSingleton(typeof(IStartup), startupType);
                    }
                    else
                    {
                        services.AddSingleton(typeof(IStartup), delegate (IServiceProvider sp) {
                            IHostingEnvironment requiredService = sp.GetRequiredService<IHostingEnvironment>();
                            return new ConventionBasedStartup(StartupLoader.LoadMethods(sp, startupType, requiredService.EnvironmentName));
                        });
                    }
                });
            }

    由上代码可得出结论:最终将Startup类添加到服务中。

    4、Build:反编译查看源代码

     public IWebHost Build()
            {
                AggregateException exception;
                IWebHost host2;
                if (this._webHostBuilt)
                {
                    throw new InvalidOperationException(Microsoft.AspNetCore.Hosting.Resources.WebHostBuilder_SingleInstance);
                }
                this._webHostBuilt = true;
                IServiceCollection serviceCollection = this.BuildCommonServices(out exception);
                IServiceCollection services = serviceCollection.Clone();
                IServiceProvider provider = <Build>g__GetProviderFromFactory|13_0(serviceCollection);
                if (!this._options.SuppressStatusMessages)
                {
                    if (Environment.GetEnvironmentVariable("Hosting:Environment") != null)
                    {
                        Console.WriteLine("The environment variable 'Hosting:Environment' is obsolete and has been replaced with 'ASPNETCORE_ENVIRONMENT'");
                    }
                    if (Environment.GetEnvironmentVariable("ASPNET_ENV") != null)
                    {
                        Console.WriteLine("The environment variable 'ASPNET_ENV' is obsolete and has been replaced with 'ASPNETCORE_ENVIRONMENT'");
                    }
                    if (Environment.GetEnvironmentVariable("ASPNETCORE_SERVER.URLS") != null)
                    {
                        Console.WriteLine("The environment variable 'ASPNETCORE_SERVER.URLS' is obsolete and has been replaced with 'ASPNETCORE_URLS'");
                    }
                }
                ILogger<WebHost> requiredService = provider.GetRequiredService<ILogger<WebHost>>();
                foreach (IGrouping<string, string> grouping in from g in Enumerable.GroupBy<string, string>(this._options.GetFinalHostingStartupAssemblies(), delegate (string a) {
                    return a;
                }, (IEqualityComparer<string>) StringComparer.get_OrdinalIgnoreCase()) select g)
                {
                    requiredService.LogWarning(string.Format("The assembly {0} was specified multiple times. Hosting startup assemblies should only be specified once.", grouping), Array.Empty<object>());
                }
                this.AddApplicationServices(services, provider);
                WebHost host = new WebHost(services, provider, this._options, this._config, exception);
    try
                {
                    host.Initialize();
                    host2 = host;
                }
                catch
                {
                    host.Dispose();
                    throw;
                }
                return host2;
            }

    由以上代码可以看出,该方法就是用来初始化操作的。

      a.初始化了服务容器(BuildCommonServices这个方法中初始化容器时,注册了大把的服务)

      b.初始化了WebHost(host.Initialize();)

      c.我们反编译一个Initialize方法,   this._startup = this._hostingServiceProvider.GetService<IStartup>(); 最终可以看到,是从服务中获取的。那么是时候

         注入进去的呢,当然是UseStartup<T>这个方法注入的。

    5、Run

      这个方法就是用来运行Web应用程序并阻止调用线程,直到host停止。因为在运行之前要做很多的事情。(在启动之前做了无数的事情)

    Startup类

        public class Startup
        {
            public void ConfigureServices(IServiceCollection services)
            {
            }
            public void Configure(IApplicationBuilder app, IHostingEnvironment env)
            {
                if (env.IsDevelopment())
                {
                    app.UseDeveloperExceptionPage();
                }
    
                app.Run(async (context) =>
                {
                    await context.Response.WriteAsync("Hello World!");
                });
            }
        }

    1、ConfigureServices:这个方法是运行是调用的,使用这个方法为程序的服务容器添加服务的

      a.上面已经讲过,在Program类中的IWebHostBuilder中的Build()方法里面,程序初始化服务容器的时候就已经为我们添加了许多的服务,所以说,这个方法只是为了给开发

       人员进行扩展。

    2、Configure:这个方法是运行是调用的,这个方法是用来配置HTTP请求管道的

      a.可以在管道中添加自定义或者Microsoft封装好的中间件

      b.可以根据环境的不同,选择不同的中间件

    通过编译追踪,最终调用的是IApplicationBuilder中的Use(Func<RequestDelegate, RequestDelegate> middleware);方法,而这个方法做的事情就是,将中间件添加到这个类型

    的_components集合中。反编译代码如下:

         private readonly IList<Func<RequestDelegate, RequestDelegate>> _components;
    
            public IApplicationBuilder Use(Func<RequestDelegate, RequestDelegate> middleware)
            {
                this._components.Add(middleware);
                return this;
            }

    launchSettings.json启动文件

    解决问题:快速的做环境切换,方便开发和调试

    为了让你的程序在多环境一样保持稳定

    wwwroot

    用来存放静态资源。

  • 相关阅读:
    The Dfferents between Redirect and Forward锻炼英文水平
    在Asp.net中将GridView打印为word或者Excel
    oracle数据无法导入表情况之一
    对“不是内部或外部命令,也不是可运行的程序?”处理
    想去 2008 北京 sun 科技日
    Bad version number in .class file
    Applet问题
    KTV
    命令行下的mysql的基本操作
    Ajax之DWR框架使用小结(2)
  • 原文地址:https://www.cnblogs.com/hhzblogs/p/9784909.html
Copyright © 2020-2023  润新知