• asp.net core 系列之Startup


    这篇文章简单记录 ASP.NET Core中 ,startup类的一些使用。

     一.前言

    Startup类中,一般有两个方法:

    • ConfigureServices 方法: 用来配置应用的 service 。 
    • Configure 方法:创建应用的请求处理管道

    它们都在应用启动时,被ASP.NET Core runtime 调用:

    public class Startup
    {
        // Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            ...
        }
    
        // Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app)
        {
            ...
        }
    }

     

    当应用的 host 被built(建立)时,Startup类被指定到应用中。

    而在 Program 中,当 host builder 上的 Build 被调用时,应用的 host 被 built 。

    Startup类是通过调用WebHostBuilderExtensions.UseStartup<TStartup>方法指定的。

    public class Program
    {
        public static void Main(string[] args)
        {
            CreateWebHostBuilder(args).Build().Run(); //Build方法被调用时,应用的host被建立,同时Startup被指定到应用中
        }
    
        public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
            WebHost.CreateDefaultBuilder(args)
                .UseStartup<Startup>();
    }

    在startup类中,一种依赖注入的常见用法:

    public class Startup
    {
        private readonly IHostingEnvironment _env;
        private readonly IConfiguration _config;
        private readonly ILoggerFactory _loggerFactory;
    
        public Startup(IHostingEnvironment env, IConfiguration config, 
            ILoggerFactory loggerFactory)
        {
            _env = env;
            _config = config;
            _loggerFactory = loggerFactory;
        }
    
        public void ConfigureServices(IServiceCollection services)
        {
            var logger = _loggerFactory.CreateLogger<Startup>();
    
            if (_env.IsDevelopment())
            {
                // Development service configuration
    
                logger.LogInformation("Development environment");
            }
            else
            {
                // Non-development service configuration
                logger.LogInformation($"Environment: {_env.EnvironmentName}");
            }
    
            // Configuration is available during startup.
            // Examples:
            //   _config["key"]
            //   _config["subsection:suboption1"]
        }
    }

    注入IHostingEnvironment , 当定义不同环境的Startup (例如,StartupDevelopment 等),在运行时,选择合适的Startup。 

    二.ConfigureServices方法

    它有三个特点:

    • 可选的 
    • 在调用Configure方法之前调用 ConfigureServices
    • Configuration options 按约定设置

    1. 比较典型的是调用 Add{Service} 和 services.Configure{Service} 。例如:Configure Identity services.

     

    2. host 可能会 在Startup方法被调用之前,配置一些服务。 例如: The host.

     

    在startup被调用之前,CreateDefaultBuilder方法配置了一个host 。

    3. Add{Service}是IServiceCollection的扩展方法,下面是一些使用:

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddDbContext<ApplicationDbContext>(options =>
            options.UseSqlServer(
                Configuration.GetConnectionString("DefaultConnection")));
        services.AddDefaultIdentity<IdentityUser>()
            .AddDefaultUI(UIFramework.Bootstrap4)
            .AddEntityFrameworkStores<ApplicationDbContext>();
    
    
        services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
    
        // Add application services. 添加应用的服务
        services.AddTransient<IEmailSender, AuthMessageSender>();
        services.AddTransient<ISmsSender, AuthMessageSender>();
    }

    添加 services 到 service container 使它们在应用和Configure方法中可用。services方法可以通过 dependency injection 或 ApplicationServices 解析。

    三.The Configure method

    Configure方法用来指定应用怎样 处理HTTP request。请求管道(request pipeline)通过添加中间组件到IApplicationBuilder实例中来配置。

    ASP.NET Core 模板 配置的管道:

    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseExceptionHandler("/Error");
            app.UseHsts();
        }
    
        app.UseHttpsRedirection();
        app.UseStaticFiles();
        app.UseCookiePolicy();
    
        app.UseMvc();
    }

    使用Use扩展方法添加一个或多个中间组件到请求管道。例如,UseMvc扩展方法添加 Routing Middleware 到请求管道 并且配置MVC 作为一个默认的处理器。

    四.Convenience methods

    不使用Startup类配置services和request processing pipeline。在host builder 上调用ConfigureServices和Configure的简便方法。如果存在多个ConfigureServices的调用,会依次添加。如果存在多个Configure方法的调用,最后一个Configure的调用会被使用。

    public class Program
    {
        public static IHostingEnvironment HostingEnvironment { get; set; }
        public static IConfiguration Configuration { get; set; }
    
        public static void Main(string[] args)
        {
            CreateWebHostBuilder(args).Build().Run();
        }
    
        public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
            WebHost.CreateDefaultBuilder(args)
                .ConfigureAppConfiguration((hostingContext, config) =>
                {
                })
                .ConfigureServices(services =>
                {
                    ...
                })
                .Configure(app =>
                {
                    var loggerFactory = app.ApplicationServices
                        .GetRequiredService<ILoggerFactory>();
                    var logger = loggerFactory.CreateLogger<Program>();
                    var env = app.ApplicationServices.GetRequiredServices<IHostingEnvironment>();
                    var config = app.ApplicationServices.GetRequiredServices<IConfiguration>();
    
                    logger.LogInformation("Logged in Configure");
    
                    if (env.IsDevelopment())
                    {
                        ...
                    }
                    else
                    {
                        ...
                    }
    
                    var configValue = config["subsection:suboption1"];
    
                    ...
                });
    }

    五.Extend Startup with startup filters (使用startup filter扩展 Startup)

    使用 IStartupFilter ,在应用的Configure 中间件管道的开头或末尾配置中间件

    IStartupFilter 实现Configure方法,它会接收和返回一个Action<IApplicationBuilder>。而IApplicationBuilder定义了一个类来配置一个应用的请求管道。

    这些filters会按照添加到services container的顺序被调用。

    下面是一个例子:

    RequestSetOptionsMiddleware

    public class RequestSetOptionsMiddleware
    {
        private readonly RequestDelegate _next;
        private IOptions<AppOptions> _injectedOptions;
    
        public RequestSetOptionsMiddleware(
            RequestDelegate next, IOptions<AppOptions> injectedOptions)
        {
            _next = next;
            _injectedOptions = injectedOptions;
        }
    
        public async Task Invoke(HttpContext httpContext)
        {
            Console.WriteLine("RequestSetOptionsMiddleware.Invoke");
    
            var option = httpContext.Request.Query["option"]; //取请求中的option参数
    
            if (!string.IsNullOrWhiteSpace(option))
            {
                _injectedOptions.Value.Option = WebUtility.HtmlEncode(option);
            }
    
            await _next(httpContext);
        }
    }

    RequestSetOptionsMiddleware 中间件被配置在 RequestSetOptionsStartupFilter 类中:

    public class RequestSetOptionsStartupFilter : IStartupFilter
    {
        public Action<IApplicationBuilder> Configure(Action<IApplicationBuilder> next)
        {
            return builder =>
            {
                builder.UseMiddleware<RequestSetOptionsMiddleware>();
                next(builder);
            };
        }
    }

    IStartupFilter 在 ConfigureServices中被注册到 service container, 并且从Startup类的外部增强Startup:

    WebHost.CreateDefaultBuilder(args)
        .ConfigureServices(services =>
        {
            services.AddTransient<IStartupFilter, 
                RequestSetOptionsStartupFilter>();
        })
        .UseStartup<Startup>()
        .Build();

    当option的查询字符串存在时,中间件会在MVC中间件之前处理这个值

    中间件的执行顺序是按照IStartupFilter的注册顺序

    六. 补充

    这里晚上补充下 ApplicationServices 解析services的使用

    IApplicationBuilder app 

    app.ApplicationServices.GetService 方法

    如上,IApplicationBuilder类型,即可得到ApplicationServices,然后利用其方法来解析services

    参考网址:

    https://docs.microsoft.com/en-us/aspnet/core/fundamentals/startup?view=aspnetcore-2.2

  • 相关阅读:
    influxdb服务器 relay
    browse-agent type and curl post
    使用 Ansible 管理 MySQL 复制
    ansible里的item和with_items
    Ansible 从MySQL数据库添加或删除用户
    ansibel---tag模块
    ll | wc -l的陷阱
    ansible 判断和循环
    Ansible详解(二)
    Ansible详解(一)
  • 原文地址:https://www.cnblogs.com/Vincent-yuan/p/11105523.html
Copyright © 2020-2023  润新知