Конфигурационный файл 'appsettings.json' не найден и не является необязательным

Ошибка Azure:

.Net Core: исключение при запуске приложения: System.IO.FileNotFoundException: файл конфигурации 'appsettings.json' не найден и не является обязательным.

Так что это немного расплывчато. Я не могу пригвоздить это. Я пытаюсь развернуть проект .Net Core Web API в Azure и получаю следующую ошибку:

:( Упс. 500 Internal Server Error Произошла ошибка при запуске приложения.

Я развернул старый добрый .Net WebAPI, и они сработали. Я следовал онлайн-урокам, и они сработали. Но так или иначе мой проект не работает. Включение stdoutLogEnabled в Web.config и просмотр потоковых журналов Azure дает мне следующее:

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, который развертывается в 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();
        }
    }
}

Edit2: Per Frans, я проверил опцию publishOptions. Это было:

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

Я взял publishOptions из рабочего проекта и изменил его на:

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

Он по-прежнему выдавал ошибку 500, но не давал трассировки стека, говоря, что он может загрузить appsettings.json. Теперь он жаловался на подключение к SQL. Я заметил, что мой код строки соединения SQL упоминается во многих сообщениях блога RC1. RC2.Net Core изменил его. Поэтому я обновил его до:

  "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 и не понял этого.

Ответ 1

Проверьте publishOptions в project.json и убедитесь, что в разделе "include" есть "appsettings.json". Они изменили модель публикации в RTM, чтобы потребовать от вас указать все, что вы хотите скопировать из каталога компиляции в веб-папку.

РЕДАКТИРОВАТЬ: Смотрите ответ Jensdc ниже, чтобы узнать, как сделать это с .csproj после того, как project.json был убит.

Ответ 2

В более поздних версиях ядра .net вместо файла project.json используется *.csproj.

Вы можете изменить файл, чтобы получить желаемый результат, добавив:

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

Ответ 3

В project.json

убедитесь, что вы указали appsettings.json как copyToOutput

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

Ответ 4

В моем случае файл appsettings.json в папке проекта, но он не был помечен Do not copy, я изменил настройку на Copy always (см. изображения ниже). И это сработало для меня.

Он автоматически добавит следующий XML в ваш файл project.csproj:

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

Я посмотрел другой ответ, project.json мертв, как говорится в этом ответе.

enter image description here enter image description here

Ответ 5

Для меня было решено включить appsettings.json через интерфейс в выходной каталог (Build directory), например так:

enter image description here

Ответ 6

Вам не нужно добавлять файл .json для публикации параметров. это просто, что он ищет файл по неправильному пути.

установите базовый путь, а затем добавьте json файл, и он будет работать.

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

        Configuration = builder.Build();
    }

здесь, конструктор запуска сконструирован с помощью HostingEnviornment, а базовый путь устанавливается на текущий корневой путь. и он будет работать!

Ответ 7

Для меня ошибка была использовать Directory.GetCurrentDirectory(). Это работало нормально, работая локально, но на рабочем сервере не получалось при запуске программы из Powershell. Заменил на Assembly.GetEntryAssembly().Location и все заработало.

Полный код:

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

var configuration = builder.Build();

Ответ 8

Для меня, я получил эту ошибку из-за синтаксической ошибки файла Json (опечатка: удаленная запятая) По умолчанию свойство "Копировать в выходной каталог" файла appsettings.json имеет значение "Не копировать", что я считаю правильным.

Ответ 9

Я попал сюда при публикации своей функции Azure из Visual Studio 2019. Я получил эту ошибку при попытке опубликовать свою функцию на портале с файлом appSettings.json. Он копировал appSettings.json в каталог вывода, но не в каталог публикации. Мне пришлось добавить строку ниже в .csproj проекта функции azure.

<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>

Ответ 10

Я решил эту проблему следующим образом, просто переместил файл appsettings.json из основного каталога в.. \bin\Debug\netcoreapp3.0