ASP.NET 5 - 使用配置设置

时间:2015-03-15 14:07:39

标签: asp.net configuration

我正在使用ASP.NET 5.我正在尝试了解新的配置模型。我看过几篇文章。但是,我仍然没有成功加载配置设置。我的config.json文件如下所示:

{
    "App" : {
        "Info" : {
            "Version":"1.0.0",
            "ReleaseDate":"03-15-2015"
        }
    }
}

我的Startup.cs文件如下所示:

public class Startup
{
    public IConfiguration Configuration { get; private set; }

    public Startup()
    {
        Configuration = new Configuration()
            .AddJsonFile("config.json");
    }

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddMvc();
    }

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

        app.UseMvc();
        app.UseWelcomePage();
    }
}

在我的一个控制器中,我有以下

MyController.cs

using System;
using Microsoft.AspNet.Mvc;

namespace MyOrg.MyApp
{
    public class MyController : Controller
    {
        [HttpGet()]
        public ActionResult Index()
        {
            var version = Configuration.Get("App:Info:Version");
            return new HttpStatusCodeResult(200);
        }
    }
}

当我启动应用时,我收到一条错误消息:

error CS0103: The name 'Configuration' does not exist in the current context
   at Microsoft.Framework.Runtime.Roslyn.RoslynProjectReference.Load(IAssemblyLo
adContext loadContext)
   at Microsoft.Framework.Runtime.Loader.ProjectAssemblyLoader.Load(String name,
 IAssemblyLoadContext loadContext)
   at Microsoft.Framework.Runtime.Loader.ProjectAssemblyLoader.Load(String name)

   at kre.host.LoaderContainer.Load(String name)
   at kre.hosting.RuntimeBootstrapper.<>c__DisplayClass6_0.<ExecuteAsync>b__4(As
semblyName assemblyName)
   at kre.hosting.RuntimeBootstrapper.<>c__DisplayClass6_0.<ExecuteAsync>b__7(Ob
ject sender, ResolveEventArgs a)
   at System.AppDomain.OnAssemblyResolveEvent(RuntimeAssembly assembly, String assemblyFullName)

我做错了什么?我觉得我已经按照我见过的例子。然而,我可以弄清楚我做错了什么。

2 个答案:

答案 0 :(得分:4)

显然,您希望访问Configuration课程中的Startup媒体资源。错误方法说它不知道Configuration是什么。因此,您需要using语句或完全限定名称。此外,您应该避免使用与框架中找到的内容相同的内容来命名。您的Startup类具有Configuration属性,但它也尝试使用Configurationfrom Microsoft.Framework.ConfigurationModel。这有多令人困惑?

Configure()中的Startup方法需要using语句或完全限定名称,以便知道Configuration类是什么。

using Microsoft.Framework.ConfigurationModel; //at the top of your class
Configuration = new Configuration(); //later in the code, we can access without fully qualifying name

Configuration = new Microsoft.Framework.ConfigurationModel.Configuration();

在您的控制器中,您可能遇到类似的问题。将以下示例中的MyOrg.MyApp.Startup替换为Startup类的命名空间。

using MyOrg.MyApp.Startup //at the top of your class
Startup.Configuration.Get("App:Info:Version"); //later in the code, we can access without fully qualifying name

 MyOrg.MyApp.Startup.Startup.Configuration.Get("App:Info:Version");

更好的做事方式

这应该足以让你入门。但是,访问Startup类以检索配置并不理想,因为现在控制器的操作方法依赖于在那里安装Startup类。那不是单元可测试的。理想情况下,您的控制器应彼此隔离。您应该定义某种接口来保存所需的配置信息,然后让控制器依赖于该接口。当您进入自己的网站时,您将使用特定于该网站配置的类进行回复。在进行单元测试时,您可以通过使用不同的类来严格控制测试值。

interface ISiteConfig
{
    string Version {get; set;}
    DateTime ReleaseDate {get; set;}
}

public class SiteConfig : ISiteConfig
{
    public string Version {get; set;}
    public DateTime ReleaseDate {get; set;}

    public SiteConfig()
    {
        var c = new Configuration()
        .AddJsonFile("config.json");
        Version = c.Get("App:Info:Version");
        ReleaseDate = c.Get("App:Info:ReleaseDate"); //may need to parse here
    }
}

public class TestConfig : ISiteConfig
{
    public string Version {get; set;}
    public DateTime ReleaseDate {get; set;}

    public TestConfig(string version, DateTime releaseDate)
    {
         Version = version;
         ReleaseDate = releaseDate;
    }
}

然后,您将使用Dependency Injection将配置实例注入Controller。

public class MyController : Controller
{
    private readonly ISiteConfig Config;

    public MyController(ISiteConfig config)
    {
        Config = config;
    }

    [HttpGet()]
    public HttpStatusCodeResult Index()
    {
        var version = Config.Version;
        return new HttpStatusCodeResult(200);
    }
}


public class Startup
{
    public void Configure(IBuilder app)
    {
        ...
        app.UseServices(services =>
        {
            ...
            // Set up the dependencies
            services.AddTransient<ISiteConfig, SiteConfig>();
            ...
        });
        ...
    }
}

现在您可以更轻松地对您的操作方法进行单元测试,因为您的单元测试可以使用TestConfig类,而站点可以使用SiteConfig类。此外,如果您想要更改配置的方式,则无需在多个不同位置替换字符串。你会有一个课程,其余的是强类型的,很容易改变,而不会炸毁你的应用程序。

您的单元测试可能如下所示:

//Arrange
var testConfig = new TestConfig("1.0", DateTime.Now );
var controller = new MyController(testConfig );  

//Act
var response = controller.Index();

//Assert
Assert.AreEqual(200, response.StatusCode);

答案 1 :(得分:0)

从Beta 5开始,接受的答案不再正确。 IConfiguration上不再有Get方法。此外,构造配置对象的方式也发生了变化。

以下代码适用于Beta 7:

// showing using statements here since this is new from Beta 5
using Microsoft.Dnx.Runtime; // renamed was Microsoft.Framework.Runtime
using Microsoft.Framework.Configuration; // renamed was Microsoft.Framework.ConfigurationModel
// other using statements here

// Startup constructor. Note: now takes IApplicationEnvironment
// this is required in order to get base path
public Startup(IHostingEnvironment env, IApplicationEnvironment appEnv)
{
        // Setup configuration sources.
        var builder = new ConfigurationBuilder(appEnv.ApplicationBasePath)
            .AddJsonFile("config.json")
            .AddJsonFile("dbconfig.json")
            .AddEnvironmentVariables();

        Configuration = builder.Build();
}

// property to hold configuration object created in constructor
public IConfiguration Configuration { get; set; }

public void ConfigureServices(IServiceCollection services)
{
   // this will bind to an IOptions<AppSettings> instance
   // where AppSettings is a class you define that has a set of 
   // properties that match your configuration section loaded from the 
   // json file
   services.Configure<AppSettings>(Configuration.GetSection("AppSettings"));

   // here I am loading a connection string from a json file and passing into an
   // new EF 6.x DB Context class
   services.AddInstance<TalentAgencyContainer>(new TalentAgencyContainer(Configuration["ConnectionStrings:TalentAgencyContainer"]));

        // Add MVC services to the services container.
        services.AddMvc();

}