如何在Asp.Net Core 6中从Secrets.json获取ConnectionString?

5

我是Asp.Net Core和EF的新手。 我正在从数据库端开发一个简单的CRUD,使用Secrets.json文件来隐藏我的连接字符串凭据。

但我不知道如何在AddDbContext()中引用该文件。

到目前为止,我的代码如下:

 public class Startup
    {
        public Startup(IConfigurationRoot configuration)
        {
            Configuration = configuration;
        }
        public IConfigurationRoot Configuration { get; }
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc();
            services.AddDbContext<POTS.myDBContext>(options => 
                options.UseSqlServer(Configuration.GetConnectionString("myConxStr")));
            services.AddControllers();
        }

代码运行时,在AddDbContext<>一行出现以下错误:

System.ArgumentNullException HResult=0x80004003 Message=Value cannot be null. (Parameter 'connectionString')
Source=Microsoft.EntityFrameworkCore.SqlServer StackTrace: etc etc

我认为这是因为代码在appsettings.json文件中寻找该参数,但我不想将连接字符串放在其中。

我错过了什么?


1
你确定是 ASP.NET Core 6 而不是 5 吗?你在项目中使用了 Startup.cs。 - Rena
@Rena,根据教程,我自己手动添加了setup.cs。我知道这不是必需的。我还在学习中。 - Fandango68
1
嗨@Fandango68,收到了。无论如何,我分享了下面两种情况。你可以检查一下。 - Rena
2个回答

10

ASP.NET 6之前:

你可以像下面这样在Startup.cs中的配置参数中添加额外的Secrets.json文件:

public class Startup
{
    public Startup(IConfiguration configuration, IWebHostEnvironment env)
    {
        configuration = new ConfigurationBuilder().SetBasePath(env.ContentRootPath)
        .AddJsonFile("Secrets.json")
        .Build();

        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }
    //...
}

或者在 Program.cs 中添加:

public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
    .ConfigureAppConfiguration((hostingContext, config) =>
    {
        var env = hostingContext.HostingEnvironment;

        config.SetBasePath(env.ContentRootPath)
            .AddJsonFile("Secrets.json", optional: true, reloadOnChange: true);

    })
    .ConfigureWebHostDefaults(webBuilder =>
    {
        webBuilder.UseStartup<Startup>();
    });

在 ASP.NET 6 中,您可以像下面这样在 Program.cs 中添加它:
var builder = WebApplication.CreateBuilder(args);
builder.Configuration
    .SetBasePath(Directory.GetCurrentDirectory()).AddJsonFile("Secrets.json");

builder.Services.AddDbContext<POTS.myDBContext>(options =>
        options.UseSqlServer(builder.Configuration.GetConnectionString("myConxStr")));

// Add services to the container....
var app = builder.Build();
//....

那么请确保您的json文件(Secrets.json)必须像下面这样

{
  "ConnectionStrings": {
    "myConxStr": "xxxxxxx"
  }
}

实际上,除了您最后的建议将单词“ConnectionString”放在secrets.json文件中,我不需要做任何其他事情。所以,仅凭那个方法就可以解决我的问题。谢谢! - Fandango68
不用谢! :) - Rena
Rena,我又回来了,因为在部署到IIS时,它无法正常工作。我没有看到任何数据显示。 - Fandango68
由于我在使用EF,我已经了解到SQL Server数据库登录必须具有管理员访问权限并能够创建表,因为EF尝试创建与连接相关的资源表格。很奇怪,我知道。我正尝试使用只读SQL登录部署,因为我不会向数据库写回任何内容。 - Fandango68
另外,通过直接引用secrets.json失败了,因为它是一个Connected Services资源。在项目的根文件夹中没有实际的secrets.json文件。这将败坏隐藏连接字符串的目的。 - Fandango68

3
在 MS 文档中,有一个完整的应用程序机密演练。值得注意的是,即使是 MS 也建议这仅用于非生产环境。如果您需要 Startup.cs,在左上角有一个下拉菜单可选择 v5 或更早版本。
ASP.NET Core 6.0 的基本步骤(参见上面的链接):
  1. 通过 cli 在项目目录中初始化机密,将在 projectName.csproj 文件的 PropertyGroup 中创建“UserSecretsId”:
    dotnet user-secrets init
  2. 创建新机密:
    dotnet user-secrets set "MyDbPassword" "SuperSecretPassword123"
  3. 将创建 secrets.json 文件:
    • Windows: %APPDATA%\Microsoft\UserSecrets<user_secrets_id>\secrets.json
    • Mac/Linux: ~/.microsoft/usersecrets/<user_secrets_id>/secrets.json
在你的情况下,在 Program.cs 中使用 ConnectionStrings,请在文档中向下滚动到“带机密的字符串替换”一节。
var conStrBuilder = new SqlConnectionStringBuilder(
    builder.Configuration.GetConnectionString("MyDbConnectionWithoutPassword"));
conStrBuilder.Password = builder.Configuration["MyDbPassword"];
var connection = conStrBuilder.ConnectionString;

谢谢。那么我可以在生产部署中使用secrets吗?我以为它只适用于开发环境。 - Fandango68
2
不,这是用于非生产环境的。我有一个仅限内部使用的应用程序,它对此很有效 ;) 微软建议使用Azure密钥保管库(当然)。 - DenverDave

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接