Asp .Net Core 学习笔记

Startup类

  1. 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();
    }

  1. 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();
        });
    }
  1. 构造函数

    • 只能注入以下三种服务类型

      • IWebHostEnvironment
      • IHostEnvironment
      • IConfiguration

依赖注入

  1. ASP.NET Core 提供了一个内置的服务容器 IServiceProvider

  2. 在configureService方法中进行注册服务

    服务的生命周期

    • 暂时的

      • 暂时生存期服务是每次从服务容器进行请求时创建的。

      • 注册方法:AddTransient

        services.AddTransient<IMyDependency, MyDependency>();
        
    • 范围内

      • 对于 Web 应用,指定了作用域的生存期指明了每个客户端请求(连接)创建一次服务。在处理请求的应用中,在请求结束时会释放有作用域的服务。

      • 注册方法:AddScoped

        services.AddScoped<IMyDependency, MyDependency>();
        
    • 单例

      • 创建时机

        • 在首次请求它们时进行创建
        • 在向容器直接提供实现实例时由开发人员进行创建( 很少用到此方法)
      • 注册方法:AddSingleton

        services.AddSingleton<IMyDependency, MyDependency>();
        
      • 注意点:

        • 允许服务容器管理服务的生存期
        • 单一实例服务必须是线程安全的,并且通常在无状态服务中使用。
  3. 服务注入到使用它的类的构造函数中。 框架负责创建依赖关系的实例,并在不再需要时将其释放。

    1. startup类的ConfigureServices注册服务

      public void ConfigureServices(IServiceCollection services)
      {
          services.AddScoped<IMyDependency, MyDependency>();
      
          services.AddRazorPages();
      }
      
    2. 构造函数注入

      //接口
      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");
          }
      }
      
      

中间件

  1. 使用IApplicationBuilder创建中间件

    1. Map

      1. 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.");
                });
            }
        }
        
    2. Use

      1. 用 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.");
                });
            }
        
    3. Run

      1. 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.");
                });
            }
        

主机

  1. 概念
    1. 主机是封装应用资源的对象,例如:

      • 依赖关系注入 (DI)
      • Logging
      • Configuration
      • IHostedService实现

配置

  1. 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}");
        }
    }
    
  2. 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>();
                });
    }
    
    1. 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"]}'");
          }
      }
      
    2. 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);
          }
      }
      
    3. 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.");
              }
          }
      }
      
  3. 整体demo,将数据绑定到实体上

    1. 配置文件

      {
        "Name": "张三",
        "Age": "14",
        "Address": "某某区",
        "interest": [ "打篮球", "跑步", "跳绳" ],
        "proxy": {"name":"李四","age":18},
        "Courses": [
          {
            "CourseName": "语文",
            "Score": 90
          },
          {
            "CourseName": "数学",
            "Score": 91
          },
          {
            "CourseName": "英语",
            "Score": 19
          }
        ]
      }
      
    2. 实体

          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; }
      
          }
      
    3. 读取数据,绑定到实体

             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();
              }
      
    4. 使用DI的方式读取配置文件(待实现)

posted @   排骨锅包肉  阅读(6)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
点击右上角即可分享
微信分享提示