程序和启动类
ASP.NET Core 6.x
ASP.NET Core 6.x 对于 Program
类带来了一些重大变化:
- 如果选择使用顶层语句,就没有了
Program.Main()
的模板代码
- 隐式 using 指令
- 不再需要
Startup
类,因为所有内容都在 Program
文件中
- 引入了
WebApplication
和 WebApplicationBuilder
有人说这些变化对于新手学习 ASP.NET Core 是好事。但是我个人感觉正好相反。我认为将 Program
和 Startup
分开更有意义,至少对我来说是这样。
总之...
下面是 Program.cs
的示例代码:
public class Program
{
public static void Main(string[] args)
{
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllersWithViews();
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/errors");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.MapControllerRoute(
name: "areaRoute",
pattern: "{area:exists}/{controller=home}/{action=index}/{id?}");
app.MapControllerRoute(
name: "default",
pattern: "{controller=home}/{action=index}/{id?}");
app.Run();
}
}
你可以从
WebApplication.CreateBuilder()
到
builder.Build()
之间的部分看出,它是旧的
ConfigureServices(IServiceCollection services)
所做的工作。而在
app.Run()
之前的部分则是
Startup
中旧的
Configure()
所做的工作。
最重要的是,
IConfiguration
被注入到管道中,因此你可以在控制器中使用它。
ASP.NET Core 3.x引入了一些变化,试图支持其他方法,如worker services,因此它用更通用的主机构建器替换了web host。
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
};
}
}
Startup
类看起来与2.x版本非常相似。
ASP.NET Core 2.x
在
Startup
构造函数中不需要新建
IConfiguration
。它的实现将由DI系统注入。
public class Program
{
public static void Main(string[] args)
{
BuildWebHost(args).Run();
}
public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.Build();
}
public class Startup
{
public IHostingEnvironment HostingEnvironment { get; private set; }
public IConfiguration Configuration { get; private set; }
public Startup(IConfiguration configuration, IHostingEnvironment env)
{
this.HostingEnvironment = env;
this.Configuration = configuration;
}
}
ASP.NET Core 1.x
你需要告诉Startup
加载appsettings文件。
public class Program
{
public static void Main(string[] args)
{
var host = new WebHostBuilder()
.UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory())
.UseIISIntegration()
.UseStartup<Startup>()
.UseApplicationInsights()
.Build();
host.Run();
}
}
public class Startup
{
public IConfigurationRoot Configuration { get; private set; }
public Startup(IHostingEnvironment env)
{
var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
.AddEnvironmentVariables();
this.Configuration = builder.Build();
}
...
}
获取值
有很多方法可以从应用程序设置中获取您配置的值:
假设您的appsettings.json
文件如下所示:
{
"ConnectionStrings": {
...
},
"AppIdentitySettings": {
"User": {
"RequireUniqueEmail": true
},
"Password": {
"RequiredLength": 6,
"RequireLowercase": true,
"RequireUppercase": true,
"RequireDigit": true,
"RequireNonAlphanumeric": true
},
"Lockout": {
"AllowedForNewUsers": true,
"DefaultLockoutTimeSpanInMins": 30,
"MaxFailedAccessAttempts": 5
}
},
"Recaptcha": {
...
},
...
}
简单方法
您可以通过将整个配置注入到控制器/类的构造函数中(通过 IConfiguration
),并使用指定的键获取所需的值:
public class AccountController : Controller
{
private readonly IConfiguration _config;
public AccountController(IConfiguration config)
{
_config = config;
}
[AllowAnonymous]
public IActionResult ResetPassword(int userId, string code)
{
var vm = new ResetPasswordViewModel
{
PasswordRequiredLength = _config.GetValue<int>(
"AppIdentitySettings:Password:RequiredLength"),
RequireUppercase = _config.GetValue<bool>(
"AppIdentitySettings:Password:RequireUppercase")
};
return View(vm);
}
}
选项模式
ConfigurationBuilder.GetValue<T>
在只需要从应用程序设置中获取一个或两个值时非常好用。但是,如果您想从应用程序设置中获取多个值,或者不想在多个地方硬编码这些键字符串,使用选项模式可能更容易。选项模式使用类来表示层次结构。
要使用选项模式:
- 定义类来表示结构
- 注册与这些类绑定的配置实例
- 将
IOptions<T>
注入到您想要获取值的控制器/类的构造函数中
1. 定义配置类来表示结构
您可以定义具有属性的类,这些属性需要与您的应用程序设置中的键完全匹配。类的名称不必与应用程序设置中的部分名称相匹配:
public class AppIdentitySettings
{
public UserSettings User { get; set; }
public PasswordSettings Password { get; set; }
public LockoutSettings Lockout { get; set; }
}
public class UserSettings
{
public bool RequireUniqueEmail { get; set; }
}
public class PasswordSettings
{
public int RequiredLength { get; set; }
public bool RequireLowercase { get; set; }
public bool RequireUppercase { get; set; }
public bool RequireDigit { get; set; }
public bool RequireNonAlphanumeric { get; set; }
}
public class LockoutSettings
{
public bool AllowedForNewUsers { get; set; }
public int DefaultLockoutTimeSpanInMins { get; set; }
public int MaxFailedAccessAttempts { get; set; }
}
2. 注册配置实例
然后,您需要在启动时的ConfigureServices()
中注册此配置实例:
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
...
namespace DL.SO.UI.Web
{
public class Startup
{
...
public void ConfigureServices(IServiceCollection services)
{
...
var identitySettingsSection =
_configuration.GetSection("AppIdentitySettings");
services.Configure<AppIdentitySettings>(identitySettingsSection);
...
}
...
}
}
注意:如果您在service.Configure<>
的重载扩展方法中没有看到以IConfiguration
为参数的版本,那么您可能需要安装Microsoft.Extensions.Options.ConfigurationExtensions
NuGet包。
对于ASP.NET Core 6.x
由于我在ASP.NET Core 6.x开头提到的更改,您需要绑定该部分并将其添加到DI中,如下所示:
public class Program
{
public static void Main(string[] args)
{
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllersWithViews();
builder.Services.Configure<AppIdentitySettings>(
builder.Configuration.GetSection("AppIdentitySettings")
);
var app = builder.Build();
...
app.Run();
}
}
你可以在这里阅读更多关于此处的内容。
3. 注入 IOptions
最后,在你想要获取值的控制器/类中,你需要通过构造函数注入IOptions<AppIdentitySettings>
:
public class AccountController : Controller
{
private readonly AppIdentitySettings _appIdentitySettings;
public AccountController(IOptions<AppIdentitySettings> appIdentitySettingsAccessor)
{
_appIdentitySettings = appIdentitySettingsAccessor.Value;
}
[AllowAnonymous]
public IActionResult ResetPassword(int userId, string code)
{
var vm = new ResetPasswordViewModel
{
PasswordRequiredLength = _appIdentitySettings.Password.RequiredLength,
RequireUppercase = _appIdentitySettings.Password.RequireUppercase
};
return View(vm);
}
}