ASP.NET 5 - 使用配置设置

标签 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();
    }
}

在我的一个 Controller 中,我有以下内容

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)

我做错了什么?我觉得我已经遵循了我所看到的例子。不过,我可以找出我做错了什么。

最佳答案

显然您想要访问Configuration您的属性(property)Startup类(class)。错误方法说它不知道什么 Configuration是。所以你需要一个using语句或完全限定名称。另外,您应该避免将事物命名为与框架中找到的事物相同的事物。您的Startup类有一个 Configuration属性,但它也尝试使用 Configuration from 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();

在您的 Controller 中,您可能会遇到类似的问题。替换MyOrg.MyApp.Startup在下面的示例中,无论 namespace 适合您的 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类来检索您的配置并不理想,因为现在 Controller 的操作方法取决于那里的 Startup 类。这不太适合单元测试。理想情况下,您的 Controller 应该相互隔离。您应该定义某种接口(interface)来保存所需的配置信息,然后让 Controller 依赖于该接口(interface)。当您进入站点时,您将使用特定于站点配置的类进行响应。在单元测试时,您可以通过使用不同的类来严格控制测试值。

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将配置实例注入(inject)到 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类(class)。而且,如果您想更改配置的完成方式,则不必在许多不同的位置替换字符串。您将拥有一个类来执行此操作,其余的类是强类型的并且易于更改,而不会破坏您的应用程序。

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

//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);

关于ASP.NET 5 - 使用配置设置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29061531/

相关文章:

c# - 如何使用 SSH 连接与 linux 服务器连接?

c# - 进程无法访问该文件,因为它正被另一个进程使用

c# - 如何使用 ASP.net C# 将 SQL 选择存储到 gridview?

c# - 混合 ASP.NET 和 MVC 路由

c++ - 打开 C++ 或 MFC 项目的设置属性页时,如何使 VS2017 匹配配置和平台选择?

javascript - 根据下拉选择隐藏/显示控件

java - 无法提取响应 : no suitable HttpMessageConverter with jaxb2marshaller

java - J2EE 配置期间出现错误

java - 使用 Java 属性的 Log4j 手动配置

configuration - Nginx中error_page的绝对路径?