问:
ASP.NET CORE MVC 如何在Filter中使用依赖注入来读取AppSettings
答:
Dependency injection is possible in filters as well.
Here is a simple way to get connection string
public class EBisUserAuthResourceFilter : Attribute, IResourceFilter { private readonly string connectionString; public EBisUserAuthResourceFilter(IConfiguration configuration) { this.connectionString = configuration .GetSection("ConnectionStrings:DefaultConnection").Value; } public void OnResourceExecuted(ResourceExecutedContext context) { // use this.connectionString } public void OnResourceExecuting(ResourceExecutingContext context) { // use this.connectionString } }
Now you can use this filter
[ServiceFilter(typeof(EBisUserAuthResourceFilter))] public class HomeController : Controller { }
You also need to add this Filter to the service collection
public void ConfigureServices(IServiceCollection services) { services.AddScoped<EBisUserAuthResourceFilter>(); // your existing code to add other services }
Another solution is to have a class representing the structure of the content of AppSettings.json
file or a sub section and load that in your Startup classes' ConfigureServices
method
services.Configure<SiteSettings>(Configuration);
and now you can inject IOptions<SiteSettings>
in the constructor of your filter and use the needed property values. I prefer this as it is less magic strings in my code.
public class EBisUserAuthResourceFilter : Attribute, IResourceFilter { private readonly string connectionString; public EBisUserAuthResourceFilter(IOptions<SiteSettings> settings) { this.connectionString = settings.Value.connectionString ; } public void OnResourceExecuted(ResourceExecutedContext context) { // use this.connectionString } public void OnResourceExecuting(ResourceExecutingContext context) { // use this.connectionString } }
补充:
当然还有个更简单的办法,就是在Filter里面直接通过.Net Core App的方式来读取AppSettings的值,这个方法是最灵活的:
appsettings.json
{ "Logging": { "IncludeScopes": false, "LogLevel": { "Default": "Warning" } }, "AppSettings": { "CacheTimeSpan": 1200, "MD5PrivateKey": "KOPX&VDtt!890912hjk", "Auth_UserName": "Username", "Auth_Token": "Token" } }
构造一个AppSettings类来反序列化appsettings.json文件中AppSettings节点下的内容:
public class AppSettings { public int CacheTimeSpan { get; set; } public string MD5PrivateKey { get; set; } public string Auth_UserName { get; set; } public string Auth_Token { get; set; } }
在Filter的构造函数中,构造AppSettings并读取其值:
public class AuthenticationFilterAttribute : Attribute, IAuthorizationFilter { public AuthenticationFilterAttribute() { var builder = new ConfigurationBuilder() .SetBasePath(Directory.GetCurrentDirectory()) .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true); IConfigurationRoot configuration = builder.Build(); var appSettings=configuration.GetSection("AppSettings").Get<AppSettings>(); int cacheTimeSpanValue = appSettings.CacheTimeSpan; } public void OnAuthorization(AuthorizationFilterContext context) { } }
.NET Core控制台项目读取AppSettings
其实在.NET Core控制台项目中也可以创建和读取AppSettings
首先你需要在.NET Core控制台项目中确保引用了下面四个Nuget包:
- Microsoft.Extensions.Configuration
- Microsoft.Extensions.Configuration.Binder
- Microsoft.Extensions.Configuration.FileExtensions
- Microsoft.Extensions.Configuration.Json
接下来,我们就可以在.NET Core控制台项目中创建一个appsettings.json文件如下:
{ "AppSettings": { "CacheTimeSpan": 1200, "MD5PrivateKey": "YUIOOASSA!@!##", "Auth_UserName": "Username", "Auth_Token": "Token" } }
注意要将appsettings.json文件的属性做修改,将"Copy to Output Directory"选项设置为"Copy if newer",如下:
然后同样定义一个AppSettings类来反序列化appsettings.json文件中AppSettings节点下的内容:
public class AppSettings { public int CacheTimeSpan { get; set; } public string MD5PrivateKey { get; set; } public string Auth_UserName { get; set; } public string Auth_Token { get; set; } }
然后在.NET Core控制台项目的Main方法中,按照如下代码读取AppSettings的值即可:
using Microsoft.Extensions.Configuration; using System; using System.IO; namespace NetCoreEnvironmentVariable { class Program { static void Main(string[] args) { var builder = new ConfigurationBuilder() .SetBasePath(Directory.GetCurrentDirectory()) .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true); IConfigurationRoot configuration = builder.Build(); var appSettings = configuration.GetSection("AppSettings").Get<AppSettings>(); int cacheTimeSpanValue = appSettings.CacheTimeSpan; string authUserName = appSettings.Auth_UserName; Console.WriteLine($"CacheTimeSpan={cacheTimeSpanValue}"); Console.WriteLine($"Auth_UserName={authUserName}"); Console.WriteLine("Press any key to end..."); Console.ReadKey(); } } }
执行结果如下:
使用AddEnvironmentVariables方法配置读取操作系统的环境变量
我们还可以配置IConfigurationBuilder去加载操作系统环境变量的值,为此我们需要在.NET Core控制台项目中再引用一个Nuget包:
接下来我们在Windows操作系统中,添加两个环境变量:
AppSettings:CacheTimeSpan为5000
AppSettings:Password为abc123456
如下图所示:
之后,最好重启一下计算机,因为AddEnvironmentVariables方法使用类似于EnvironmentVariableTarget.Process参数的机制,来加载操作系统环境变量,所以需要重启计算机后才能够读取到操作系统环境变量的值。
然后我们将.NET Core控制台项目的Main方法改为如下:
using Microsoft.Extensions.Configuration; using System; using System.IO; namespace NetCoreEnvironmentVariable { class Program { static void Main(string[] args) { var builder = new ConfigurationBuilder() .SetBasePath(Directory.GetCurrentDirectory()) .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true) .AddEnvironmentVariables();//使用AddEnvironmentVariables方法,配置让IConfigurationBuilder加载操作系统中的环境变量,由于这里AddEnvironmentVariables方法在上面的AddJsonFile方法的后面,所以在"appsettings.json"文件中与操作系统环境变量同名的键值,会被操作系统环境变量的值所覆盖 IConfigurationRoot configuration = builder.Build(); var appSettings = configuration.GetSection("AppSettings").Get<AppSettings>(); int cacheTimeSpanValue = appSettings.CacheTimeSpan;//由于在操作系统环境变量中,我们定义了AppSettings:CacheTimeSpan为5000,所以"appsettings.json"文件中CacheTimeSpan为1200的值会被覆盖,所以这里实际上得到的是操作系统环境变量AppSettings:CacheTimeSpan的值5000 string authUserName = appSettings.Auth_UserName;//由于在操作系统环境变量中,没有定义AppSettings:Auth_UserName,所以这里得到的还是"appsettings.json"文件中Auth_UserName的值Username string password = configuration["AppSettings:Password"];//获取操作系统环境变量AppSettings:Password的值abc123456 Console.WriteLine($"CacheTimeSpan={cacheTimeSpanValue}"); Console.WriteLine($"Auth_UserName={authUserName}"); Console.WriteLine($"Password={password}"); Console.WriteLine("Press any key to end..."); Console.ReadKey(); } } }
注意"appsettings.json"文件中的json类型层次结构,可以用冒号":"来进行表达,所以我们可以看到,上面代码中操作系统环境变量AppSettings:CacheTimeSpan,等同于"appsettings.json"文件中AppSettings属性下的CacheTimeSpan属性。
运行上面代码,执行结果如下:
可以看到,我们成功地读出了操作系统环境变量AppSettings:CacheTimeSpan和AppSettings:Password的值。