配置文件'appsettings.json'未找到且不可选。

109
Azure错误信息如下:
.Net Core:应用程序启动异常: System.IO.FileNotFoundException: 找不到配置文件'appsettings.json',且该文件不是可选的。
所以这有点模糊。我似乎无法确定问题所在。我正在尝试将.Net Core Web API项目部署到Azure上,并且遇到了这个错误:
:( 哎呀,500内部服务器错误 启动应用程序时发生错误。
我已经部署了普通的.Net WebAPI,它们可以正常工作。我已经按照在线教程进行操作,也可以正常工作。但是我的项目出了问题。在Web.config上启用stdoutLogEnabled并查看Azure Streaming日志,会得到以下结果:
2016-08-26T02:55:12  Welcome, you are now connected to log-streaming service.
Application startup exception: System.IO.FileNotFoundException: The configuration file 'appsettings.json' was not found and is not optional.
   at Microsoft.Extensions.Configuration.FileConfigurationProvider.Load(Boolean reload)
   at Microsoft.Extensions.Configuration.FileConfigurationProvider.Load()
   at Microsoft.Extensions.Configuration.ConfigurationRoot..ctor(IList`1 providers)
   at Microsoft.Extensions.Configuration.ConfigurationBuilder.Build()
   at Quanta.API.Startup..ctor(IHostingEnvironment env) in D:\Source\Workspaces\Quanta\src\Quanta.API\Startup.cs:line 50
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at Microsoft.Extensions.Internal.ActivatorUtilities.ConstructorMatcher.CreateInstance(IServiceProvider provider)
   at Microsoft.Extensions.Internal.ActivatorUtilities.CreateInstance(IServiceProvider provider, Type instanceType, Object[] parameters)
   at Microsoft.Extensions.Internal.ActivatorUtilities.GetServiceOrCreateInstance(IServiceProvider provider, Type type)
   at Microsoft.Extensions.DependencyInjection.ActivatorUtilities.GetServiceOrCreateInstance(IServiceProvider provider, Type type)
   at Microsoft.AspNetCore.Hosting.Internal.StartupLoader.LoadMethods(IServiceProvider services, Type startupType, String environmentName)
   at Microsoft.AspNetCore.Hosting.WebHostBuilderExtensions.<>c__DisplayClass1_0.<UseStartup>b__1(IServiceProvider sp)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.FactoryService.Invoke(ServiceProvider provider)
   at Microsoft.Extensions.DependencyInjection.ServiceProvider.ScopedCallSite.Invoke(ServiceProvider provider)
   at Microsoft.Extensions.DependencyInjection.ServiceProvider.SingletonCallSite.Invoke(ServiceProvider provider)
   at Microsoft.Extensions.DependencyInjection.ServiceProvider.<>c__DisplayClass12_0.<RealizeService>b__0(ServiceProvider provider)
   at Microsoft.Extensions.DependencyInjection.ServiceProvider.GetService(Type serviceType)
   at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType)
   at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService[T](IServiceProvider provider)
   at Microsoft.AspNetCore.Hosting.Internal.WebHost.EnsureStartup()
   at Microsoft.AspNetCore.Hosting.Internal.WebHost.EnsureApplicationServices()
   at Microsoft.AspNetCore.Hosting.Internal.WebHost.BuildApplication()
Hosting environment: Production
Content root path: D:\home\site\wwwroot
Now listening on: http://localhost:30261
Application started. Press Ctrl+C to shut down.

好的,这似乎很简单。它找不到appsettings.json文件。查看我的配置(startup.cs),它看起来非常清晰定义。我的启动代码如下:

public class Startup
{
    private static string _applicationPath = string.Empty;
    private static string _contentRootPath = string.Empty;
    public IConfigurationRoot Configuration { get; set; }
    public Startup(IHostingEnvironment env)
    {
        _applicationPath = env.WebRootPath;
        _contentRootPath = env.ContentRootPath;
        // Setup configuration sources.

        var builder = new ConfigurationBuilder()
            .SetBasePath(_contentRootPath)
            .AddJsonFile("appsettings.json")
            .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true);

        if (env.IsDevelopment())
        {
            // This reads the configuration keys from the secret store.
            // For more details on using the user secret store see http://go.microsoft.com/fwlink/?LinkID=532709
            builder.AddUserSecrets();
        }

        builder.AddEnvironmentVariables();
        Configuration = builder.Build();
    }
    private string GetXmlCommentsPath()
    {
        var app = PlatformServices.Default.Application;
        return System.IO.Path.Combine(app.ApplicationBasePath, "Quanta.API.xml");
    }

    // This method gets called by the runtime. Use this method to add services to the container.
    // For more information on how to configure your application, visit http://go.microsoft.com/fwlink/?LinkID=398940
    public void ConfigureServices(IServiceCollection services)
    {
        var pathToDoc = GetXmlCommentsPath();


        services.AddDbContext<QuantaContext>(options =>
            options.UseSqlServer(Configuration["Data:DefaultConnection:ConnectionString"],
            b => b.MigrationsAssembly("Quanta.API")));

        //Swagger
        services.AddSwaggerGen();
        services.ConfigureSwaggerGen(options =>
        {
            options.SingleApiVersion(new Info
            {
                Version = "v1",
                Title = "Project Quanta API",
                Description = "Quant.API",
                TermsOfService = "None"
            });
            options.IncludeXmlComments(pathToDoc);
            options.DescribeAllEnumsAsStrings();
        });

        // Repositories
        services.AddScoped<ICheckListRepository, CheckListRepository>();
        services.AddScoped<ICheckListItemRepository, CheckListItemRepository>();
        services.AddScoped<IClientRepository, ClientRepository>();
        services.AddScoped<IDocumentRepository, DocumentRepository>();
        services.AddScoped<IDocumentTypeRepository, DocumentTypeRepository>();
        services.AddScoped<IProjectRepository, ProjectRepository>();
        services.AddScoped<IProtocolRepository, ProtocolRepository>();
        services.AddScoped<IReviewRecordRepository, ReviewRecordRepository>();
        services.AddScoped<IReviewSetRepository, ReviewSetRepository>();
        services.AddScoped<ISiteRepository, SiteRepository>();

        // Automapper Configuration
        AutoMapperConfiguration.Configure();

        // Enable Cors
        services.AddCors();

        // Add MVC services to the services container.
        services.AddMvc()
            .AddJsonOptions(opts =>
            {
                // Force Camel Case to JSON
                opts.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
            });
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app)
    {
        app.UseStaticFiles();
        // Add MVC to the request pipeline.
        app.UseCors(builder =>
            builder.AllowAnyOrigin()
            .AllowAnyHeader()
            .AllowAnyMethod());

        app.UseExceptionHandler(
          builder =>
          {
              builder.Run(
                async context =>
                {
                    context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
                    context.Response.Headers.Add("Access-Control-Allow-Origin", "*");

                    var error = context.Features.Get<IExceptionHandlerFeature>();
                    if (error != null)
                    {
                        context.Response.AddApplicationError(error.Error.Message);
                        await context.Response.WriteAsync(error.Error.Message).ConfigureAwait(false);
                    }
                });
          });

        app.UseMvc(routes =>
        {
            routes.MapRoute(
                name: "default",
                template: "{controller=Home}/{action=Index}/{id?}");

            // Uncomment the following line to add a route for porting Web API 2 controllers.
            //routes.MapWebApiRoute("DefaultApi", "api/{controller}/{id?}");
        });


        //Ensure DB is created, and latest migration applied. Then seed.
        using (var serviceScope = app.ApplicationServices
          .GetRequiredService<IServiceScopeFactory>()
          .CreateScope())
        {
            QuantaContext dbContext = serviceScope.ServiceProvider.GetService<QuantaContext>();
            dbContext.Database.Migrate();
            QuantaDbInitializer.Initialize(dbContext);
        }


        app.UseSwagger();
        app.UseSwaggerUi();


    }
}

这段代码在本地运行良好,但一旦发布到Azure上就会失败。我很迷惑。我创建了一个新的 .Net Core 项目,并成功部署到Azure。但是这个项目花费了我所有的时间,似乎无法运行。我准备将无法运行的项目中的代码复制并粘贴到一个新项目中,但我真的很好奇是什么导致了错误。

有任何想法吗?

编辑: 我的Program.cs如下:

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Hosting;

namespace Quanta.API
{
    public class Program
    {
        public static void Main(string[] args)
        {
            var host = new WebHostBuilder()
                .UseKestrel()
                .UseContentRoot(Directory.GetCurrentDirectory())
                .UseIISIntegration()
                .UseStartup<Startup>()
                .Build();

            host.Run();
        }
    }
}

编辑2: 根据Frans的建议,我检查了publishOptions。它是:

"publishOptions": {
"include": [
  "wwwroot",
  "web.config"
]

我从一个正常工作的项目中获取了publishOptions,并进行了如下更改:

 "publishOptions": {
  "include": [
    "wwwroot",
    "Views",
    "Areas/**/Views",
    "appsettings.json",
    "web.config"
  ]
  },

虽然出现了500错误,但没有出现堆栈跟踪,指出无法加载appsettings.json文件。现在它抱怨连接到SQL的问题。我注意到我的SQL连接字符串代码在许多RC1博客文章中都提到了。.Net Core的RC2对此进行了更改。因此,我将其更新为:

  "Data": {
    "ConnectionStrings": {
      "DefaultConnection": "Server=(localdb)\\MSSQLLocalDB;Database=QuantaDb;Trusted_Connection=True;MultipleActiveResultSets=true"
    }
  },

我将启动项更改为:

 services.AddDbContext<QuantaContext>(options =>
        options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"),
        b => b.MigrationsAssembly("Quanta.API")));

最终,它起作用了。 我一定是按照旧的RC1示例操作,没有意识到这一点。

错误信息中有 Content root path: D:\home\site\wwwroot。这是预期的吗?appsettings.json 文件在文件夹中吗? - adem caglin
16个回答

104
在我的情况下,文件appsettings.json存在于项目文件夹中,但它被设置为不复制,我将设置更改为始终复制(请参见下面的图像)。这对我起作用了。
它将自动向您的project.csproj文件添加以下XML:
<ItemGroup>
    <Content Update="appsettings.json">
      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
    </Content>
</ItemGroup>

我已经查看了其他答案,正如此答案所说,project.json已经死亡。

enter image description here enter image description here


将“Build Action”设置为“Content”的目的是什么?如果将其设置为“None”,似乎也可以工作。 - JoePC
1
@JoePC,实际上在我的回答中,我没有提到任何有关构建操作设置的内容,也不记得为什么当时我的设置被设置为内容。有一个很好的答案涵盖了这部分,请查看https://dev59.com/xHVC5IYBdhLWcg3w7Vtq - Maytham Fahmi
对我来说这有效(我必须将其重新设置为Copy Always才能包含它); 然后我通过声明路径来包含json文件,就像这样:APP_SETTINGS = Path.Combine(AppContext.BaseDirectory, "appsettings.json"); builder.AddJsonFile(APP_SETTINGS, optional: false); - gl3yn

99
在较新的 .net core 版本中,使用 *.csproj 文件代替 project.json 文件。
您可以通过添加以下内容修改文件以获得所需的结果:
   <ItemGroup>
      <Content Update="appsettings.json">
        <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
      </Content>
   </ItemGroup>

28
在Visual Studio 2019中,通过“解决方案资源管理器”访问“appsettings.json”的“属性”窗格会在**.csproj中生成Include**而不是_Update_: <ItemGroup> <Content Include="appsettings.json"> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> </Content> </ItemGroup> - JoePC
这就是答案,伙计们! - Gicu Mironica

54

更新:

来自评论中的@bunjeeb。对于.NET 5 <=,使用System.AppContext.BaseDirectory代替Assembly.GetEntryAssembly().Location,并设置<PublishSingleFile>true</PublishSingleFile>

原始内容:

我遇到了使用Directory.GetCurrentDirectory()时出错的情况。在本地运行时一切都很好,但在生产服务器上从Powershell启动程序时失败了。将其替换为Assembly.GetEntryAssembly().Location,一切都正常工作。

完整代码:

var builder = new ConfigurationBuilder()
        .SetBasePath(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location))
        .AddJsonFile("appsettings.json");

var configuration = builder.Build();

15
在.net5中,如果你设置了<PublishSingleFile>true</PublishSingleFile>,你将会收到来自VS的警告,告诉你Assembly.GetEntryAssembly().Location总是为空。相反地,请使用System.AppContext.BaseDirectory - bunjeeb
3
+100。哦,老兄,你救了我的一天。这终于对我起作用了。 - VivekDev
1
这对于创建Windows服务时的HostedService也非常有用。 - undefined
当创建Windows服务时,这对HostedService也非常有用。 - elfico
我正在使用.NET 7,有一天,我的Program.cs文件无法再看到appsettings.json文件了。我的Azure数据库登录因此失败了。之前一切都正常工作。我花了一整天的时间进行故障排除,最后找到了解决方法。在构建器中添加新的一行".AddJsonFile("appsettings.json");"就解决了问题。不过,我完全不知道为什么之前没有那行代码也能正常工作。 - undefined
现在它可以找到我的 appsettings.json 文件,但是某些部分却找不到 "Section 'XYZ' not found in configuration." 真是太痛苦了,哈哈。 - undefined

36

请确保在你的project.json文件中,将appsettings.json添加到copyToOutput中。

"buildOptions": {
   "emitEntryPoint": true,
   "preserveCompilationContext": true,
   "copyToOutput": {
     "include": [ "appsettings.json" ]
   }
 },

感谢您的评论。问题已解决。 - sebastian.roibu

22

请检查project.json中的publishOptions,并确保“include”部分中包含“appsettings.json”。

他们在RTM中更改了发布模型,要求您指定要从编译目录复制到web文件夹的所有内容。

编辑:请参阅下面Jensdc的答案,了解如何在project.json被删除后使用.csproj完成此操作。


3
我认为你想说的是 appsettings.json,它不是 publishOptions 的一部分。我从一个正常工作的项目中复制了一个 publishOptions: - Frank
1
哎呀,是的 :) 这就是我用手机回答时发生的事情 :) - flytzen

14

对我而言,解决问题的方法是通过界面将 appsettings.json 包含在输出目录(构建目录)中,具体操作如下:

输入图片说明


12

您不需要将您的 .json 文件添加到发布选项中。 只是它正在错误的路径查找文件。

设置基本路径,然后添加 json 文件,它就会工作。

 public Startup(IHostingEnvironment environment)
    {
        var builder = new ConfigurationBuilder()
            .SetBasePath(environment.ContentRootPath)
            .AddJsonFile("TestJson.json");

        Configuration = builder.Build();
    }

在这里,启动构造函数使用HostingEnviornment创建,并将基本路径设置为当前根路径。然后它将正常工作!


4
对我有效的方法是将 appsettings.json 上的 Copy to Output Directory 属性 更改为 Copy if newer

3

我在从网络共享中运行应用程序时遇到了同样的错误。它甚至尝试在用户桌面上查找appsettings.json文件。

最终,我将路径与可执行文件位置组合起来,如下所示:

configuration
  .AddJsonFile(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "appsettings.json"), optional: false, reloadOnChange: false)
  .AddJsonFile(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, $"appsettings.{env.EnvironmentName}.json"), optional: true, reloadOnChange: false);

这对于DotNet 5及以下版本非常好,但是对于DotNet 6,我感到困惑,因为不再有startup.cs文件。 - MC9000

3

当我从Visual Studio 2019发布我的Azure函数时,出现了以下问题。当我尝试使用appSettings.json文件将我的函数发布到门户网站时,出现了这个错误。它将appSettings.json复制到output目录,但没有复制到publish目录中。我不得不在Azure函数项目的.csproj文件中添加以下行。

<CopyToPublishDirectory>Always</CopyToPublishDirectory>

所以我的.csproj文件应该长这样:
<ItemGroup>
<None Update="host.json">
  <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="appsettings.json">
  <CopyToOutputDirectory>Always</CopyToOutputDirectory>
  <CopyToPublishDirectory>Always</CopyToPublishDirectory>
</None>
<None Update="local.settings.json">
  <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>


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