我正在使用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)
我做错了什么?我觉得我已经按照我见过的例子。然而,我可以弄清楚我做错了什么。
答案 0 :(得分:4)
显然,您希望访问Configuration
课程中的Startup
媒体资源。错误方法说它不知道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();
在您的控制器中,您可能遇到类似的问题。将以下示例中的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();
}