这篇文章简单记录 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

asp.net core 系列之Startup的更多相关文章

  1. ASP.NET Core系列(三):启动类Startup

    前面讲了ASP.NET Core 的项目结构,查看完整的ASP.NET Core系列文章:https://www.cnblogs.com/zhangweizhong/category/1477144. ...

  2. asp.net core系列 30 EF管理数据库架构--必备知识 迁移

    一.管理数据库架构概述 EF Core 提供两种主要方法来保持 EF Core 模型和数据库架构同步.一是以 EF Core 模型为基准,二是以数据库为基准. (1)如果希望以 EF Core 模型为 ...

  3. asp.net core系列 39 Web 应用Razor 介绍与详细示例

    一. Razor介绍 在使用ASP.NET Core Web开发时, ASP.NET Core MVC 提供了一个新特性Razor. 这样开发Web包括了MVC框架和Razor框架.对于Razor来说 ...

  4. asp.net core系列 38 WebAPI 返回类型与响应格式--必备

    一.返回类型 ASP.NET Core 提供以下 Web API Action方法返回类型选项,以及说明每种返回类型的最佳适用情况: (1) 固定类型 (2) IActionResult (3) Ac ...

  5. asp.net core 系列 22 EF(连接字符串,连接复原,DbContext)

    一.连接字符串 在上二篇中,ASP.NET Core 应用程序连接字符串是写死在ConfigureServices代码中,下面介绍通过配置来实现.连接字符串可以存储在 appsettings.json ...

  6. asp.net core 系列 18 web服务器实现

    一. ASP.NET Core Module 在介绍ASP.NET Core Web实现之前,先来了解下ASP.NET Core Module.该模块是插入 IIS 管道的本机 IIS 模块(本机是指 ...

  7. asp.net core 系列 16 Web主机 IWebHostBuilder

    一.概述 在asp.net core中,Host主机负责应用程序启动和生存期管理.host主机包括Web 主机(IWebHostBuilder)和通用主机(IHostBuilder).Web 主机是适 ...

  8. asp.net core 系列 14 错误处理

    一.概述 本文介绍处理 ASP.NET Core 应用中常见错误的一些方法.主要是关于:开发环境异常页:非开发环境配置自定义异常处理页:配置状态代码页(没有正文响应,http状态400~599的). ...

  9. 技术的正宗与野路子 c#, AOP动态代理实现动态权限控制(一) 探索基于.NET下实现一句话木马之asmx篇 asp.net core 系列 9 环境(Development、Staging 、Production)

    黄衫女子的武功似乎与周芷若乃是一路,飘忽灵动,变幻无方,但举手抬足之间却是正而不邪,如说周芷若形似鬼魅,那黄衫女子便是态拟神仙. 这段描写出自<倚天屠龙记>第三十八回. “九阴神抓”本是& ...

随机推荐

  1. Android 4.0开发之GridLayOut布局实践

    在上一篇教程中http://blog.csdn.net/dawanganban/article/details/9952379,我们初步学习了解了GridLayout的布局基本知识,通过学习知道,Gr ...

  2. Python Tricks(二十一)—— 排列组合的计算

    使用循环: 阶乘的实现: def fac(n): r = 1. for i in range(1, n+1): r *= i return r 排列:Anm=m!n!=(m−n+1)⋯m def pe ...

  3. android module 模块共用远程包

    在项目有多模块,需要使用到同一个第三方包时,引入报错,个人解决方法如下 1. 在模块build.gradle 文件中配置maven远程地址 可从app下的build.gradle文件里复制 allpr ...

  4. C#中的字符串——用Stringbuilder类很重要

    注:这篇文章基本是<C#高级编程>(第七版)第九章的学习笔记. 众所周知,C#中处理字符串通常用的都是string,它其实是.NET基础类System.String类的映射.注意一个是小写 ...

  5. HDU 1143 Tri Tiling(递归)

    意甲冠军:一些现有的1*2小盒子.求拼3*n多少个长方形的拼写. 思考: 因为它是一个递归式.肯定会遇到层的关系.仔细观察,研究发现,每层应设置2一层.(奇数层不能是矩形)而从显卡好最后一层的最后一战 ...

  6. python下载图片(3)

    # -*- coding: utf-8 -*-"""some function by metaphy,2007-04-03,copyleftversion 0.2&quo ...

  7. 解决popup不随着window一起移动的问题

    原文:解决popup不随着window一起移动的问题 当我们设置Popup的StayOpen="True"时,会发现移动窗体或者改变窗体的Size的时候,Popup并不会跟随着一起 ...

  8. java线:辛格尔顿隐藏ThreadLocal实现线程数据共享

    效果图分享: A和B需要共享同一线程,还有一组的相同A和B共享还有一组线程,两组相互之间不受影响. 代码: package cn.itcast.lesson6; import java.util.Ra ...

  9. 在 DEBIAN 上安装 SQL SERVER

    微软在开源 .NET Framework 之后,相继推出了跨平台的编辑器 Visual Studio Code,跨平台的 SQL Server 数据库 SQL Server vNext,Visual ...

  10. String,CString,TCHAR,char之间区别和联系

    char是类型TCHAR也是!不过他可以通过是否定义了UNICODE宏来判断到底是char还是w_char; TCHAR是一种字符串类型,它让你在以MBCS和UNNICODE来build程序时可以使用 ...