如何将AppSettings转移到使用ASP.NET Core 7的依赖注入?

huangapple go评论79阅读模式
英文:

How to transfer AppSettings to use ASP.NET Core 7's dependency injection?

问题

In ASP.NET Core 7, the approach to reading configuration settings has indeed shifted away from ConfigurationManager.AppSettings to use the built-in dependency injection and configuration system. You can still access configuration values directly, but the way to do it has changed. Here's how you can access configuration values in ASP.NET Core 7:

  1. Startup Configuration: In your application's Startup.cs file, you can configure your application's settings using appsettings.json or other configuration sources. You typically do this in the ConfigureServices method.
public void ConfigureServices(IServiceCollection services)
{
    // Add configuration to the services collection
    var configuration = new ConfigurationBuilder()
        .SetBasePath(Directory.GetCurrentDirectory())
        .AddJsonFile("appsettings.json")
        .Build();

    services.AddSingleton(configuration);
}
  1. Accessing Configuration in Services: Now, you can access configuration values in your services by injecting IConfiguration into your classes or methods.
public class MyService
{
    private readonly IConfiguration _configuration;

    public MyService(IConfiguration configuration)
    {
        _configuration = configuration;
    }

    public void SomeMethod()
    {
        // Access a configuration value
        var myValue = _configuration["MyKey"];
    }
}
  1. appsettings.json: In your appsettings.json file, you can define your configuration settings like this:
{
    "MyKey": "MyValue"
}

This approach offers more flexibility and better integration with ASP.NET Core's dependency injection system. It also allows you to manage configuration values for different environments more easily using JSON files like appsettings.Development.json, appsettings.Production.json, etc.

Regarding your question about whether every class needs to be changed to work with an interface for clients like this, it's not necessary to change every class. You typically use interfaces when you want to implement dependency injection for certain services or components. You can gradually update your code to utilize dependency injection as needed, especially for services where you find it beneficial.

So, to summarize, in ASP.NET Core 7, you can still access configuration values directly, but it's recommended to embrace the built-in configuration and dependency injection system for better maintainability and testability of your application.

英文:

I'm trying to understand how to use the code we have in ASP.NET MVC 5 with the newer ASP.NET Core 7.

From what I can tell, Core 7 no longer uses the AppSettings approach. Instead, Microsoft wants developers to use dependency injection. This is the article I am trying to follow:

https://learn.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection?view=aspnetcore-7.0

I see where objects are declared and used in the file Program.cs:

using DIsample2.Services;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();

builder.Services.AddScoped<Service1>();
builder.Services.AddSingleton<Service2>();

var myKey = builder.Configuration["MyKey"];
builder.Services.AddSingleton<IService3>(sp => new Service3(myKey));

var app = builder.Build();

And then the class is built differently to include the interface:

public class IndexModel : PageModel
{
    private readonly Service1 _service1;
    private readonly Service2 _service2;
    private readonly IService3 _service3;

    public IndexModel(Service1 service1, Service2 service2, IService3 service3)
    {
        _service1 = service1;
        _service2 = service2;
        _service3 = service3;
    }

    public void OnGet()
    {
        _service1.Write("IndexModel.OnGet");
        _service2.Write("IndexModel.OnGet");
        _service3.Write("IndexModel.OnGet");
    }
}

In Core 7, is this the correct way to read from a configuration file like AppSettings?

In the code above, the instantiation of PageModel is handled by the Visual Studio 2022 IDE. If I were to attempt to create a class that used services like that, I would need instances of the services to pass in. Where do I get those? It looks like Microsoft gets the services and configuration settings from var builder = WebApplication.CreateBuilder(args), but that is not something I should be accessing from classes in our code.

Here is a sample piece of code from what we have now:


public static void GetResources(SheetModel sheet)
{
    const string FMT = "No {0} File For SQL: SELECT FilePath FROM ResourceManager WHERE Category1='{1}' AND Category2='{2}' AND Category3='{3}' AND IsActive=1;";
    using (var db = new SqlEntities())
    {
        var request = new GetPreSignedUrlRequest()
        {
            BucketName = $"{ConfigurationManager.AppSettings["BucketName"]}",
            Expires = DateTime.UtcNow.AddMinutes(30),
        };
        var client = new AmazonS3Client(
            $"{ConfigurationManager.AppSettings["PublicKey"]}", 
            $"{ConfigurationManager.AppSettings["PrivateKey"]}", 
            RegionEndpoint.USEast);
        var row = db.AssetManagers.FirstOrDefault(m =>
                m.Category1 == "Sticker" &&
                m.Category2 == "Data" &&
                m.Category3 == sheet.DAMDLN &&
                m.IsActive);
        if (row != null)
        {
            request.Key = $"{row.FilePath}".Trim();
            sheet.Href = client.GetPreSignedURL(request);
        } else
        {
            Console.WriteLine(String.Format(FMT, "Data", "Sticker", "Data", sheet.DAMDLN));
        }
        row = db.AssetManagers.FirstOrDefault(m => 
            m.Category1 == "Sticker" && 
            m.Category2 == "Image" && 
            m.Category3 == sheet.DADLRN && 
            m.IsActive);
        if (row != null)
        {
            request.Key = $"{row.FilePath}".Trim();
            sheet.Image = client.GetPreSignedURL(request);
        }
        else
        {
            Console.WriteLine(String.Format(FMT, "Image", "Window Sticker", "Image", sheet.DADLRN));
        }
        row = db.AssetManagers.FirstOrDefault(m => 
            m.Category1 == "Sticker" && 
            m.Category2 == "Image" && 
            m.Category3 == "c_wreath" && 
            m.IsActive);
        if (row != null)
        {
            request.Key = $"{row.FilePath}".Trim();
            sheet.Wreath = client.GetPreSignedURL(request);
        }
        else
        {
            Console.WriteLine(String.Format(FMT, "Wreath", "Sticker", "Image", "c_wreath"));
        }
        request.Key = (row != null) ? $"{row.FilePath}".Trim() : string.Empty;
        sheet.Wreath = client.GetPreSignedURL(request);
    }
}

Would every class need to be changed to work with an interface for clients like this?

Reading from ConfigurationManager.AppSettings["SomeKey"] seemed simpler and more direct.

Can I still get to values directly, or has that door been closed?

答案1

得分: 1

使用以下代码示例:

using (var db = new SqlEntities())

现代 ASP.NET Core 高度依赖于依赖注入,我强烈建议遵循这种模式,以便您不必在实现中进行实例化或读取配置。

快速而不太规范的方法是将您的静态方法移到某个服务中,将 IConfiguration 注入其中,用注入配置的调用替代 ConfigurationManager.AppSettings。例如:

appsettings.json

{
   // ....,
   "AmazonS3Client":{
      "PublicKey": "...",
      "PrivateKey": "..."
   }
}

然后在服务中:

public class MyService // 可以考虑使用接口
{
    // 需要引用 Microsoft.Extensions.Configuration;
    private readonly IConfiguration Configuration;

    public MyService (IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public ... GetResources(...)
    {
        var publicKey = Configuration["AmazonS3Client:PublicKey"];
        var privateKey = Configuration["AmazonS3Client:PublicKey"];
        // ...
    }
}

请注意,更常见的方法是为设置创建一个专门的类,并将其注册到依赖注入容器中,并通过 Options 模式 解析配置。
了解更多信息:

英文:

using (var db = new SqlEntities()) - modern ASP.NET Core heavily relies on dependency injection and I highly recommend to follow this pattern, so you try not to new up or read configuration in the implementation.

The +/- quick-n-dirty approach would be to move your static method into some service, inject IConfiguration into it substituting ConfigurationManager.AppSettings with call to the injected config. For example:

appsettings.json

{
   // ....,
   "AmazonS3Client":{
      "PublicKey": "...",
      "PrivateKey": "..."
   }
}

And then in the service:

public class MyService // maybe an interface here
{
    // requires using Microsoft.Extensions.Configuration;
    private readonly IConfiguration Configuration;

    public MyService (IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public ... GetResources(...)
    {
        var publicKey = Configuration["AmazonS3Client:PublicKey"];
        var privateKey = Configuration["AmazonS3Client:PublicKey"];
        // ...
    }
}

Note that more common approach is to create a special class for settings and register it the DI and resolve the config, for example via Options pattern.
Read more:

huangapple
  • 本文由 发表于 2023年7月10日 23:13:18
  • 转载请务必保留本文链接:https://go.coder-hub.com/76655114.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定