ASP.NET 5(vNext)-获取配置设置

44

我正在编写一个基本的应用程序来学习ASP.NET 5。其中一个我觉得非常混乱的领域是配置。在ASP.NET 5之前,我可以执行以下操作:

var settingValue = ConfigurationManager.AppSettings["SomeKey"];

我以前的代码中会散布着像这样的代码行。而在 vNext 的世界里,我有一个长这样的 config.json 文件:

config.json

{
  "AppSettings": {
    "SomeKey":"SomeValue"
  }
}

然后在 Startup.cs 中,我有以下内容: Startup.cs

public IConfiguration Configuration { get; set; }
public Startup(IHostingEnvironment environment) 
{
  Configuration = new Configuration()
      .AddJsonFile("config.json");
}

从那里开始,我完全被难住了。我在/src/Website/Code/Models/MyClass.cs中有MyClass.cs。

MyClass.cs

public class MyClass
{
  public string DoSomething() 
  {
    var result = string.Empty;
    var keyValue = string.Empty; // TODO: What do I do here? How do I get the value of "AppSettings:SomeKey"?
    return result;
  }
}

我该如何获取"AppSettings:SomeKey"的值?


@MStodd - 是的。MVC6(ASP.NET 5)。 - xam developer
4个回答

17

ASP.NET 5广泛使用依赖注入,因此如果您也在使用依赖注入,则这非常简单。如果您检查示例MVC6项目,您可以看到它的工作原理:

首先,在Properties中定义了一个名为AppSettings的类,它是您的类所支持选项的强类型版本。在示例项目中,它只包含SiteTitle。

public class AppSettings
{
    public string SiteTitle { get; set; }
}

然后,通过依赖注入在ConfigureServices中初始化这个类。这里的Configuration是您在Startup类的构造函数中创建的那个。

public void ConfigureServices(IServiceCollection services)
{
    services.Configure<AppSettings>(Configuration.GetSubKey("AppSettings"));
    // ...
}

假设您的类由依赖注入容器实例化,您可以简单地请求一个IOptions,然后您就会得到一个。例如,在控制器中,您可以编写如下代码:

public class HomeController
{
    private string _title;
    public HomeController(IOptions<AppSettings> settings) 
    {
        _title = settings.Options.SiteTitle;
    }
}

我很好奇,你是指哪个MVC6示例项目?你有链接吗? - Some User
在 Visual Studio 中创建新的 MVC 项目时得到的那个。 - Richard
3
@SerjSagan 你是怎么让它工作的?在我的系统中,Configuration 没有 GetSubKey 方法。 - Matthew Verstraete
6
有几种方法。对于根级别的内容,使用 Configuration.GetSection("AppSettings"),对于嵌套的内容,使用 Configuration["Data:DefaultConnection:ConnectionString"] - Serj Sagan
3
请注意,截至今日,Asp.Net Core已经推出了RC1版本,而RC2也即将推出,这个“选项模型”是建议采用的方法。接口有一些变化:现在应该使用 settings.Value.SiteTitle,并且在 ConfigureServices 中需要使用 services.AddOptions(); 进行选项设置和依赖注入。 - superjos

15
我使用 ASP.NET 5 的依赖注入,就像这样。
config.json:
{
    "random":  "Hello World!"
}

startup.cs:

public class Startup
{
    public Startup(IHostingEnvironment env, IApplicationEnvironment appEnv)
    {
        var builder = new ConfigurationBuilder(appEnv.ApplicationBasePath)
            .AddJsonFile("config.json");

        Configuration = builder.Build();
    }

    public IConfiguration Configuration { get; set; }

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddMvc();
        services.AddSingleton<IConfiguration>(sp => { return Configuration; });
    }

    public void Configure(IApplicationBuilder app)
    {
        app.UseMvc(routes =>
        {
            routes.MapRoute(name: "default", template: "{controller=Home}/{action=Index}/{id?}");
        });

    }

}

控制器:

public class HomeController : Controller
{

    IConfiguration config;

    public HomeController(IConfiguration config)
    {
        this.config = config;
    }

    public IActionResult Index()
    {
        var template = "<marquee>{0}</marquee>";
        var content = string.Format(template, config.Get("random"));
        return Content(content, "text/html");
    }
}

1
在最新版本的 ASP.NET Core 中,var builder = new ConfigurationBuilder().AddJsonFile("appsettings.json") - Vahid Amiri
...并且在Core 2.0中再次更改 - Marc L.

14

我强烈推荐使用OptionsModel而不是直接读取配置。它允许将强类型模型绑定到配置。

这里是一个示例:GitHub.com/aspnet/Options/test/Microsoft.Extensions.Options.Test/OptionsTest.cs

对于您的特定情况,请创建一个模型:

class AppSettings {
    public string SomeSetting {get;set;}
}

并将其绑定到您的配置中:

var config = // The configuration object
var options = ConfigurationBinder.Bind<AppSettings>(config); 
Console.WriteLine(options.SomeSetting);

这样你就不必担心设置来自哪里,如何存储或结构是什么。您只需预定义选项模型,然后神奇的事情就会发生。


1
创建一些具有属性的类。类似于此处的代码(https://github.com/aspnet/Options/blob/dev/test/Microsoft.Framework.OptionsModel.Test/OptionsTest.cs#L23),其中包含“NestedOptions”。 - Victor Hurdugaci
我审查了OptionsModel方法。然而,除了强类型值之外,它对我来说并不清楚其价值所在。我认为OptionsModel方法存在的更大问题是如何将值传递到可重用库中。例如,如果我想创建一个可重用的日志记录库,选项如何传递到该库中? - Some User
我认为这个功能更多的是由ConfigurationBinder而不是OptionsModel实现的。我一直在试图弄清楚Options(IOptionOptionManager等)的作用,但还没有真正理解。 - Ben Collins
ConfigurationBinder 最近已从 Options 移动到 Configuration。 - Victor Hurdugaci
2
@VictorHurdugaci 感谢您修复链接,但对我来说,我仍然不知道如何从project.jsonconfig.json中获取数据。 - Matthew Verstraete
显示剩余4条评论

12

使用这个:

var value = Configuration.Get("AppSettings:SomeKey");

基于这篇博客文章。冒号类似于点表示法,用于向下导航层次结构。

如果需要在其他类中使用该值,则应注入该值。ASP.NET具有内置的依赖项注入功能,但如果您只需要一个MyClass实例,则可以新建它,而不是设置DI容器。

public IConfiguration Configuration { get; set; }

public Startup(IHostingEnvironment environment) 
{
    Configuration = new Configuration()
      .AddJsonFile("config.json");
    //generally here you'd set up your DI container. But for now we'll just new it up
    MyClass c = new MyClass(Configuration.Get("AppSettings:SomeKey"));
}

public class MyClass
{
    private readonly string Setting; //if you need to pass multiple objects, use a custom POCO (and interface) instead of a string.

    public MyClass(string setting) //This is called constructor injection
    {
        Setting = setting;
    }

    public string DoSomething() 
    {
        var result = string.Empty;
        //Use setting here
        return result;
    }
}

Configuration 属性/类是从哪里来的?我在 MyClass.cs 的顶部添加了 using Microsoft.Framework.ConfigurationModel,但我无法使用 Configuration.Get - xam developer
这太丑了。最好写成像 class MyClass { public MyClass(IConfiguration config... 这样的形式。 - metadings
21
@VictorHurdugaci,您当然可以根据自己的判断使用负分。但我认为这是一个极其不好的理由来打负分给别人的答案。这是一种新的架构,我不知道有这个选项。我已经从你们公司看过很多演示,没有一个演示展示了强类型模型绑定选项。我的答案可以完美地解决问题,并清晰地展示了如何解决问题。当然,强类型模型绑定很好,但如果我的公司建议其他工作方法,我认为打负分给有可行替代方案的人是不礼貌的。 - mason
@metadings 你看了我的回答吗?我在回答中提出了建议。之所以我没有那样做,是因为我不想把原始代码改得面目全非。你必须先学会走,然后才能跑。 - mason
10
@Victor:因为你更喜欢自己的答案,就对别人的回答进行投票贬低,这样做真的很不好。投票应该针对错误或不恰当的答案。如果回答方式可以解决问题,那么请尊重它。 - drobertson
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接