【问题标题】:Injecting my settings in the controller works in debug, but not in release在控制器中注入我的设置在调试中有效,但在发布中无效
【发布时间】:2019-02-21 17:55:08
【问题描述】:

我对 Asp.Net Core 很陌生,所以我很确定我在做一些愚蠢的事情,但我不知道问题出在哪里。所以我在我的 appsetting.json 中写了几个我需要在运行时检索的变量。在documentation 之后,我在ConfigureService 的Startup 中写过

services.AddOptions();
services.Configure<AppConfig>(Configuration.GetSection("AppConfig"));

在哪里AppConfig

是下面的类

public class AppConfig
{
    public bool NeedToCheckSession { get; set; }
    public string ConnectionString { get; set; }
}

我的控制器的构造函数如下:

public MyController(IOptions<AppConfig> config)
{
    this.config = config;
}

现在,当我在 Visual Studio 中通过 IIS Express 在调试中运行我的 api 时,当我向我的控制器发送请求时,我可以在构造函数中点击断点并且配置设置正确。如果然后我在 Release 我的项目中构建,执行 webapi.exe 并使用 Visual Studio 附加到进程,我看到当我发送相同的请求时,我直接点击方法内的断点,跳过构造函数中的断点,使用未设置配置变量的结果。问题出在哪里?

我添加了用于检查 config 变量是否设置正确的调用

        [Route("start")]
        [HttpPost]
        public HttpResponseMessage MyMethod([FromBody]UserSessionModel userSession)
        {
            HttpResponseMessage resp;


            MyWorker newSession = new MyWorker (config.Value.ConnectionString)
            {
                SessionFolder = sessionFolder
            };


            if (config.Value.NeedToCheckSession == true)
            {
               // i can't enter inside this if, cause even if in the appsetting.json the value is set to true, config is not passed to the controller
            }

同时添加 json 文件

{
  "AppConfig": {
    "NeedToCheckSession": "true",
    "ConnectionString": "myconnstring;"
  },
  "Logging": {
    "LogLevel": {
      "Default": "Warning"
    }
  },
  "AllowedHosts": "*"
}

编辑

回答一些问题:

  • 不,我不使用无参数构造函数,我只有上面发布的那个

  • 我尝试直接在 VS 2017 中以发布模式运行 api,将其托管在 IIS Express 上,但是,当我发送我的发布请求时,断点未在构造函数内命中,config 变量为未设置。如果我在调试中运行 api 它可以工作

  • 要创建 exe,我只需在发布模式下构建 api,然后尝试从项目中的 Release 文件夹运行它。我也尝试发布api,但问题仍然存在

EDIT2

进一步调查,发现由于某种原因,在下面ConfigureService

   // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
        services.AddOptions();
        services.Configure<AppConfig>(Configuration.GetSection("AppConfig"));
        services.AddHostedService<QueuedHostedService>();
        services.AddSingleton<IBackgroundTaskQueue, BackgroundTaskQueue>();
        // Register the Swagger generator, defining 1 or more Swagger documents
        services.AddSwaggerGen(c =>
        {
            c.SwaggerDoc("v1", new Microsoft.OpenApi.Models.OpenApiInfo { Title = "My Web Api", Version = "v1" });
            // Set the comments path for the Swagger JSON and UI.
            var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
            var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
            c.IncludeXmlComments(xmlPath);
        });
    }

在 release 中运行 api 时,以下指令将被完全忽略(即跳过)。

        services.Configure<AppConfig>(Configuration.GetSection("AppConfig"));
        services.AddHostedService<QueuedHostedService>();
        services.AddSingleton<IBackgroundTaskQueue, BackgroundTaskQueue>();

虽然这在调试中不会发生

【问题讨论】:

  • 1) 您在开发和生产中在哪里设置这些配置值? 2)假设你没有无参数的构造函数,那么它肯定是在调用这个构造函数。否则,将无法访问 action 方法,并且会抛出某种异常。远程调试可能只是自动跳过它。
  • @ChrisPratt 我不知道如何回答您的第一个问题。我的项目文件夹中有我的 appsettings.json,我没有在发布版本和调试版本之间进行任何更改。唯一的区别是,为了调试,我直接使用带有 IIS Express 的 Visual Studio,而为了测试版本,我直接启动 .exe 文件
  • @ChrisPratt 也是,我没有任何无参数构造函数,所以可能由于某种我不知道的原因跳过了断点。调试文件夹和发布文件夹的内容是一样的,所以我真的不知道为什么它在调试模式下工作。这可能与 Visual Studio 使用 IIS Express 托管我的 api 的事实有关吗?
  • 不确定,但是当您需要注入依赖项时,无参数构造函数是一个很大的禁忌。 DI 容器总是在无参数版本之后。
  • 如果您从 VS 以 Release Mode 运行项目,您会收到任何错误吗?你是如何生成webapi.exeattach to the VS process 的?与我们分享重现问题的详细步骤。

标签: c# asp.net-core


【解决方案1】:

使用 ConfigurationBuilder:

 private static IConfigurationRoot Get(string path, string[] args = null, string environmentName = null)
        {
            var builder = new ConfigurationBuilder()
                .SetBasePath(path)
                .AddJsonFile("appsettings.json", true, true)
                .AddCommandLine(args ?? new string[0]);

            if (!environmentName.IsNullOrWhiteSpace()) builder = builder.AddJsonFile($"appsettings.{environmentName}.json", true, true);

            builder = builder.AddEnvironmentVariables();

            return builder.Build();
        }

和:

   var host = new WebHostBuilder()
                    ...

                    .UseConfiguration(AppConfigurations.Get(root, args, Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT")))
                    .UseEnvironment(Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT"))
                    .Build();

【讨论】:

  • 我应该在哪里使用这个?这与我遇到的问题无关,因为我解决了它,但我很想知道这样做有什么好处
  • 1.请为我们所有人写下你的答案
  • 2.上面的解决方案让您为不同的环境拥有不同的配置文件,这取决于 ASPNETCORE_ENVIRONMENT 环境。 Appsettings.json 将与特定环境 appsettings.Test.json 或 appsettings.Production.json 合并
  • 谢谢。我会确保使用这种方法。至于答案我已经贴出来了,和代码无关,而是VS做了优化
【解决方案2】:

结果证明这不是与代码严格相关的问题,但我发现我必须在项目属性的构建选项卡中禁用“优化代码”选项,因为这弄乱了我的调试器

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-01-19
    • 2012-11-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-29
    • 1970-01-01
    • 2019-03-18
    相关资源
    最近更新 更多