Asp .Net Core 学习笔记
Startup类
-
ConfigureServices方法
- 注册服务,并通过依赖注入(DI)或者 ApplicationServices 在整个应用中使用服务
- 使用IServiceCollection的各种Add{Service}进行注册,例如,AddDbContext、AddDefault、AddEntityFrameworkStores 和 AddPages
- 在 Configure 方法配置应用服务之前,由主机调用
示例:
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(
Configuration.GetConnectionString("DefaultConnection")));
services.AddDefaultIdentity<IdentityUser>(
options => options.SignIn.RequireConfirmedAccount = true)
.AddEntityFrameworkStores<ApplicationDbContext>();
services.AddRazorPages();
}
-
Configure
- 用于指定应用响应 HTTP 请求的方式,
- 创建应用的请求处理管道,通过将中间件组件添加到IApplicationBuilder 实例来配置请求管道
示例:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapRazorPages();
});
}
-
构造函数
-
只能注入以下三种服务类型
- IWebHostEnvironment
- IHostEnvironment
- IConfiguration
-
依赖注入
-
ASP.NET Core 提供了一个内置的服务容器 IServiceProvider
-
在configureService方法中进行注册服务
服务的生命周期
-
暂时的
-
暂时生存期服务是每次从服务容器进行请求时创建的。
-
注册方法:AddTransient
services.AddTransient<IMyDependency, MyDependency>();
-
-
范围内
-
对于 Web 应用,指定了作用域的生存期指明了每个客户端请求(连接)创建一次服务。在处理请求的应用中,在请求结束时会释放有作用域的服务。
-
注册方法:AddScoped
services.AddScoped<IMyDependency, MyDependency>();
-
-
单例
-
创建时机
- 在首次请求它们时进行创建
- 在向容器直接提供实现实例时由开发人员进行创建( 很少用到此方法)
-
注册方法:AddSingleton
services.AddSingleton<IMyDependency, MyDependency>();
-
注意点:
- 允许服务容器管理服务的生存期
- 单一实例服务必须是线程安全的,并且通常在无状态服务中使用。
-
-
-
服务注入到使用它的类的构造函数中。 框架负责创建依赖关系的实例,并在不再需要时将其释放。
-
startup类的ConfigureServices注册服务
public void ConfigureServices(IServiceCollection services) { services.AddScoped<IMyDependency, MyDependency>(); services.AddRazorPages(); }
-
构造函数注入
//接口 public interface IMyDependency { void WriteMessage(string message); } //实现 public class MyDependency : IMyDependency { public void WriteMessage(string message) { Console.WriteLine($"MyDependency.WriteMessage Message: {message}"); } } //注入IMyDependency public class Index2Model : PageModel { private readonly IMyDependency _myDependency; public Index2Model(IMyDependency myDependency) { _myDependency = myDependency; } public void OnGet() { _myDependency.WriteMessage("Index2Model.OnGet"); } }
-
中间件
-
使用IApplicationBuilder创建中间件
-
Map
-
Map 扩展用作约定来创建管道分支。
public class Startup { private static void HandleMapTest1(IApplicationBuilder app) { app.Run(async context => { await context.Response.WriteAsync("Map Test 1"); }); } private static void HandleMapTest2(IApplicationBuilder app) { app.Run(async context => { await context.Response.WriteAsync("Map Test 2"); }); } public void Configure(IApplicationBuilder app) { app.Map("/map1", HandleMapTest1); app.Map("/map2", HandleMapTest2); app.Run(async context => { await context.Response.WriteAsync("Hello from non-Map delegate."); }); } }
-
-
Use
-
用 Use 将多个请求委托链接在一起。 next 参数表示管道中的下一个委托。 可通过不调用 next 参数使管道短路。
public void Configure(IApplicationBuilder app) { app.Use(async (context, next) => { // Do work that doesn't write to the Response. await next.Invoke(); // Do logging or other work that doesn't write to the Response. }); app.Run(async context => { await context.Response.WriteAsync("Hello from 2nd delegate."); }); }
-
-
Run
-
Run 委托不会收到 next 参数。 第一个 Run 委托始终为终端,用于终止管道。 Run 是一种约定。
public void Configure(IApplicationBuilder app) { app.Use(async (context, next) => { // Do work that doesn't write to the Response. await next.Invoke(); // Do logging or other work that doesn't write to the Response. }); app.Run(async context => { await context.Response.WriteAsync("Hello from 2nd delegate."); }); }
-
-
主机
- 概念
-
主机是封装应用资源的对象,例如:
- 依赖关系注入 (DI)
- Logging
- Configuration
- IHostedService实现
-
配置
-
GetValue
ConfigurationBinder.GetValue 从配置中提取一个具有指定键的值,并将它转换为指定的类型。 此方法是 IConfiguration 的扩展方法:
public class TestNumModel : PageModel { private readonly IConfiguration Configuration; public TestNumModel(IConfiguration configuration) { Configuration = configuration; } public ContentResult OnGet() { // 如果在配置中找不到 NumberKey,则使用默认值 99 var number = Configuration.GetValue<int>("NumberKey", 99); return Content($"{number}"); } }
-
GetSection、GetChildren 和 Exists
前置文件:
MySubsection.json
{ "section0": { "key0": "value00", "key1": "value01" }, "section1": { "key0": "value10", "key1": "value11" }, "section2": { "subsection0": { "key0": "value200", "key1": "value201" }, "subsection1": { "key0": "value210", "key1": "value211" } } }
将
MySubsection.json
添加到配置提供程序public class Program { public static void Main(string[] args) { CreateHostBuilder(args).Build().Run(); } public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .ConfigureAppConfiguration((hostingContext, config) => { config.AddJsonFile("MySubsection.json", optional: true, reloadOnChange: true); }) .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup<Startup>(); }); }
-
GetSection
IConfiguration.GetSection 会返回具有指定子节键的配置子节。
public class TestSectionModel : PageModel { private readonly IConfiguration Config; public TestSectionModel(IConfiguration configuration) { //获取section1的值 Config = configuration.GetSection("section1"); } public ContentResult OnGet() { //返回section1:key0和section1:key1的值 return Content( $"section1:key0: '{Config["key0"]}'\n" + $"section1:key1: '{Config["key1"]}'"); } }
-
GetChildren
返回Section节点的子节点
public class TestSection4Model : PageModel { private readonly IConfiguration Config; public TestSection4Model(IConfiguration configuration) { Config = configuration; } public ContentResult OnGet() { string s = null; var selection = Config.GetSection("section2"); //判断节点是否存在 if (!selection.Exists()) { throw new System.Exception("section2 does not exist."); } var children = selection.GetChildren(); //循环打印节点数据 foreach (var subSection in children) { int i = 0; var key1 = subSection.Key + ":key" + i++.ToString(); var key2 = subSection.Key + ":key" + i.ToString(); s += key1 + " value: " + selection[key1] + "\n"; s += key2 + " value: " + selection[key2] + "\n"; } return Content(s); } }
-
Exists
调用 ConfigurationExtensions.Exists 以验证该节是否存在
public class TestSection4Model : PageModel { private readonly IConfiguration Config; public TestSection4Model(IConfiguration configuration) { Config = configuration; } public void OnGet() { string s = null; var selection = Config.GetSection("section2"); //判断节点是否存在 if (!selection.Exists()) { throw new System.Exception("section2 does not exist."); } } }
-
-
整体demo,将数据绑定到实体上
-
配置文件
{ "Name": "张三", "Age": "14", "Address": "某某区", "interest": [ "打篮球", "跑步", "跳绳" ], "proxy": {"name":"李四","age":18}, "Courses": [ { "CourseName": "语文", "Score": 90 }, { "CourseName": "数学", "Score": 91 }, { "CourseName": "英语", "Score": 19 } ] }
-
实体
public class Proxy { public string Name { get; set; } public int Age { get; set; } } public class Courses { public string CourseName { get; set; } public int Score { get; set; } } public class Config { public string Name { get; set; } public int Age { get; set; } public string Address { get; set; } public string[] interest { get; set; } public Proxy proxy { get; set; } public Courses[] Courses { get; set; } }
-
读取数据,绑定到实体
public void configBeseRead() { //构建configBuilder ConfigurationBuilder configurationBuilder = new ConfigurationBuilder(); configurationBuilder.AddJsonFile("config.json", false, false); //绑定到根节点 IConfigurationRoot configuration = configurationBuilder.Build(); string name = configuration["Name"]; Console.WriteLine($"name:{name}"); //读取子节点的数值 var proxyName = configuration.GetSection("proxy:name").Value; Console.WriteLine($"proxyName:{proxyName}"); var proxyAge = configuration.GetSection("proxy:age").Value; Console.WriteLine($"proxyAge:{proxyAge}"); //把配置文件绑定到类上 //绑定父节点 Config config = configuration.Get<Config>(); Console.WriteLine("打印整个配置文件"); Console.WriteLine(JsonConvert.SerializeObject(config)); Console.ReadKey(); //只绑指定定子节点 Proxy proxy = configuration.GetSection("proxy").Get<Proxy>(); Console.WriteLine("打印单个对象子节点"); Console.WriteLine(JsonConvert.SerializeObject(proxy)); Console.ReadKey(); List<Courses> courses = configuration.GetSection("Courses").Get<List<Courses>>(); Console.WriteLine("打印集合对象子节点"); Console.WriteLine(JsonConvert.SerializeObject(courses)); Console.ReadKey(); }
-
使用DI的方式读取配置文件(待实现)
-
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南