ASP.NET Core 6启动时如何访问Configuration

ASP.NET Core 6 how to access Configuration during startup

在早期版本中,我们有 Startup.cs class 并且我们在 Startup 文件中得到如下配置对象。

public class Startup 
{
    private readonly IHostEnvironment environment;
    private readonly IConfiguration config;

    public Startup(IConfiguration configuration, IHostEnvironment environment) 
    {
        this.config = configuration;
        this.environment = environment;
    }

    public void ConfigureServices(IServiceCollection services) 
    {
        // Add Services
    }

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env) 
    {
        // Add Middlewares
    }

}

现在在 .NET 6 中(使用 Visual Studio 2022),我们看不到 Startup.cs class。看起来它的日子已经屈指可数了。那么我们如何获得这些对象,如 Configuration(IConfiguration) 和 Hosting Environment(IHostEnvironment)

我们如何获取这些对象,比如从 appsettings 中读取配置?当前 Program.cs 文件如下所示。

using Festify.Database;
using Microsoft.EntityFrameworkCore;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddRazorPages();

builder.Services.AddDbContext<FestifyContext>();


////////////////////////////////////////////////
// The following is Giving me error as Configuration 
// object is not avaible, I dont know how to inject this here.
////////////////////////////////////////////////


builder.Services.AddDbContext<FestifyContext>(opt =>
        opt.UseSqlServer(
            Configuration.GetConnectionString("Festify")));


var app = builder.Build();

// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();

app.UseAuthorization();

app.MapRazorPages();

app.Run();

我想知道如何从 appsettings.json 中读取配置?

WebApplication.CreateBuilder(args) 返回的

WebApplicationBuilder 公开了 Configuration and Environment 属性:

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
...
ConfigurationManager configuration = builder.Configuration; // allows both to access and to set up the config
IWebHostEnvironment environment = builder.Environment;
WebApplicationBuilder.Build() 返回的

WebApplication 也公开了 ConfigurationEnvironment:

var app = builder.Build();
IConfiguration configuration = app.Configuration;
IWebHostEnvironment environment = app.Environment;

同时检查 migration guide and code samples

Program.cs 中创建了如下所示的 WebApplicationBuilder。

var builder = WebApplication.CreateBuilder(args);

一旦我们创建了构建器,配置就可用了。

让我们假设您有默认的 appSettings.json。下面的示例代码将 return 来自 JSON 配置文件的配置默认日志级别设置。

builder.Configuration["Logging:LogLevel:Default"] // returns "Warning"

应用 运行 后,您可以在应用的其他 class 中通过依赖注入访问配置设置。

public MyClass(IConfiguration configuration)
{
   var logLevel = configuration["Logging:LogLevel:Default"];
}

一个值得考虑的好功能是创建一个代表您的设置的 class,然后将配置绑定到该 class 类型的一个实例。例如,假设您创建了一个名为 MyAppSettings 的新 class,其结构与您的 appSettings.json 相同,您可以执行以下操作:

var myAppSettings = builder.Configuration.Get<MyAppSettings>();
string logLevel = myAppSettings.Logging.LogLevel.Default;

您只需添加“生成器”即可。在您的配置之前

喜欢:

builder.Services
       .AddDbContext<FestifyContext>
    (opt =>opt.UseSqlServer(builder.Configuration
                                   .GetConnectionString("Festify")));

以下代码对我有用:

Program.cs:

var builder = WebApplication.CreateBuilder(args);
string connString = builder.Configuration.GetConnectionString("conStr");
ConnectionString = connString;

...

partial class Program
{
    public static string? ConnectionString { get; private set; }
}

calling class:
string cnStr = Program.ConnectionString;

这对我有用 ---

// Read in from JSON file
builder.Services.Configure<ConnectionKeys>(builder.Configuration.GetSection("ConnectionKeys"));

.NET 6 已经在 Program.cs

中提供了构建器对象
var builder = WebApplication.CreateBuilder(args);

仅使用此构建器访问配置和环境为例,从 app.settings.cs 获取 ConnectionString,如下所示:

builder.Services.AddDbContext<DataContext>( options =>
{
  options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnectiion"));
});

//.NET6 Program.cs -(获取应用程序配置属性)

var builder = WebApplication.CreateBuilder(args);

builder.Configuration.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true);
builder.Configuration.AddJsonFile($"appsettings.Dev.json", optional: true);
builder.Configuration.AddEnvironmentVariables();

// projectwide instances
  public IConfiguration _configuration;
        public AccountsAPIController(IConfiguration configuration)
        {
            _configuration = configuration;
        }

// _configuration.GetConnectionString("DefaultConnection");

这与之前的答案略有不同,我将其包括在内是因为我正在审查类似的内容。

在您的 Program.cs 中,您还可以将代码分组到一个方法中并调用它以减少 run-on 一点或将类似的东西分组。我不会把所有的代码都放进去;我不会在此处列出 using 指令的完整列表,但足以演示该技术,我将省略一些方法代码。这对于您的解决方案来说还不够,甚至可能太多了,需要您的自定义修饰。

using AutoMapper;
using MicroKnights.Log4NetHelper;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.DataProtection;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.Authorization;
using Microsoft.AspNetCore.Mvc.Infrastructure;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
...
//all your using directives
using StackExchange.Redis;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;

//a variable to hold configuration
IConfiguration Configuration;

var builder = WebApplication.CreateBuilder(args);
Configuration = builder.Configuration;

// call some methods
ConfigureAuth(builder.Services);
ConfigureRedis(builder.Services);
ConfigureSession(builder.Services);
ConfigureMvc(builder.Services);
ConfigureServices(builder.Services);

var app = builder.Build();
ConfigureMiddleWare(app);
app.Run();
// we are done with the main part, now the methods

void ConfigureMvc(IServiceCollection services)
{
    builder.Services.AddMvc(config =>
    {
        var policy = new AuthorizationPolicyBuilder().RequireAuthenticatedUser().Build();
        config.Filters.Add(new AuthorizeFilter(policy));
    })
    .AddRazorPagesOptions(options => { options.Conventions.AddPageRoute("/Home/Login", ""); })
    .AddJsonOptions(options =>
    {
        options.JsonSerializerOptions.PropertyNameCaseInsensitive = true;
        options.JsonSerializerOptions.PropertyNamingPolicy = null;
    });
}

void ConfigureSession(IServiceCollection services)
{
    builder.Services.AddSession(options =>
    {
        options.Cookie.Name = "mygreatsite_session";
        options.IdleTimeout = TimeSpan.FromMinutes(60);
    });
}

void ConfigureRedis(IServiceCollection services)
{
    var redisConfig = new RedisOptions();
    Configuration.GetSection(RedisOptions.RedisConfig).Bind(redisConfig);
    services.AddStackExchangeRedisCache(options =>
    {
        options.Configuration = redisConfig.ConnectionString;
        options.InstanceName = "mygreatsite_";
    });
    services.AddDataProtection()
        .SetApplicationName("MyGreatSite.Website")
        .PersistKeysToStackExchangeRedis(ConnectionMultiplexer.Connect(redisConfig.ConnectionString), "DataProtection-Keys");
}

void ConfigureMiddleWare(WebApplication app)
{
    if (builder.Environment.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
        app.UseBrowserLink();
    }
    else
    {
        app.UseExceptionHandler("/Home/Error");
    }

    app.UseRouting();
    app.UseCors("default");
    app.UseCookiePolicy();
    app.UseAuthentication();
    app.UseAuthorization();
    app.UseSession();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapDefaultControllerRoute().RequireAuthorization();
        endpoints.MapControllerRoute(
            name: "Default",
            pattern: "{controller=Home}/{action=Login}"
        );
    });
}