The configuration file 'appsettings.json' was not found and is not optional

101,741

Solution 1

Check the publishOptions in project.json and make sure the "include" section has "appsettings.json" in it. They changed the publish model in RTM to require you to specify everything you want copied from the compile directory to the web folder.

EDIT: See Jensdc answer below for how to do this with .csproj after project.json was killed.

Solution 2

In later .net core versions a *.csproj file is used instead of the project.json file.

You can modify the file to get the desired result by adding:

   <ItemGroup>
      <Content Update="appsettings.json">
        <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
      </Content>
   </ItemGroup>

Solution 3

In My case the file appsettings.json existed in project folder, but it was set to Do not copy, I changed the setting to Copy always (see images below). And it worked for me.

It will automatically added following XML to your project.csproj file:

<ItemGroup>
    <Content Update="appsettings.json">
      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
    </Content>
</ItemGroup>

I have looked at other answer, project.json is dead as this answer says.

enter image description here enter image description here

Solution 4

In your project.json

ensure you have inlcuded appsettings.json as a copyToOutput

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

Solution 5

For me the error was using Directory.GetCurrentDirectory(). This worked fine running locally but on a production server it failed when the program was started from Powershell. Replaced with Assembly.GetEntryAssembly().Location and everything worked.

Complete code:

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

var configuration = builder.Build();
Share:
101,741
Frank
Author by

Frank

Updated on July 08, 2022

Comments

  • Frank
    Frank almost 2 years

    The Azure error is:

    .Net Core: Application startup exception: System.IO.FileNotFoundException: The configuration file 'appsettings.json' was not found and is not optional.

    So this is a bit vague. I can't seem to nail this down. I'm trying to deploy a .Net Core Web API project to Azure, and I'm getting this error:

    :( Oops. 500 Internal Server Error An error occurred while starting the application.

    I've deployed plain old .Net WebAPI's and they have worked. I've followed online tutorials and they have worked. But somehow my project is broke. Enabling stdoutLogEnabled on Web.config and looking at the Azure Streaming Logs gives me this:

    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.
    

    Ok, that seems simple. It can't find appsettings.json. Looking at my config ( startup.cs ) it seems very well defined. My Startup looks like this:

    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();
    
    
        }
    }
    

    This works fine locally. But once we publish to Azure, this fails. I'm at a loss. I've created new .Net core project that deploy to Azure just find. But this one project, that I put all my time into to, seems to fail. I'm about ready to copy and paste code out of the project that fails to run and into a new project, but i'm really curious on what's breaking this.

    Any ideas?

    EDIT: So my Program.cs was:

    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();
            }
        }
    }
    

    Edit2: Per Frans, I checked the publishOptions. It was:

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

    I took a publishOptions from a working project and changed it to:

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

    It still gave a 500 error, but it didn't give a stack trace saying it coulding load appsettings.json. Now it was complaining about a connection to SQL. I noticed that my SQL connection string code is mentioned in a lot of RC1 blog posts. RC2 of .Net Core changed it. So I updated it to:

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

    And changed my startup to:

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

    Finally, it worked.

    I must have followed an older RC1 example and not realized it.

  • Frank
    Frank over 7 years
    I think you meant appsettings.json, and it was not part of the publishOptions. I copied a publishOptions from a working project:
  • flytzen
    flytzen over 7 years
    Oops, yes :) that's what happens when I answer on my phone :)
  • sebastian.roibu
    sebastian.roibu over 7 years
    Thanks for your comment. Solved my problem.
  • JoePC
    JoePC almost 5 years
    What is the purpose of setting "Build Action" to "Content"? It seems to work if this is set to "None."
  • JoePC
    JoePC almost 5 years
    In Visual Studio 2019, accessing the Properties pane of appsettings.json via the Solution Explorer generates Include rather than Update in .csproj: <ItemGroup> <Content Include="appsettings.json"> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory‌​> </Content> </ItemGroup>
  • Maytham Fahmi
    Maytham Fahmi almost 5 years
    @JoePC actually in my answer I do not mention any thing about build action setting and I do not remember why my setting was set to content at that time I made the answer. There is a nice answer that cover this part, please check stackoverflow.com/questions/145752/…
  • Gicu Mironica
    Gicu Mironica about 3 years
    This is the answer guys!
  • bunjeeb
    bunjeeb over 2 years
    In .net5, if you set <PublishSingleFile>true</PublishSingleFile> you will get a warning from VS telling you that Assembly.GetEntryAssembly().Location is always null. Instead use System.AppContext.BaseDirectory
  • VivekDev
    VivekDev over 2 years
    +100. Oh man, you saved my day. This finally worked for me.