Получение корневого каталога приложения-функции Azure версии 2

Я создаю приложение-функцию Azure (v2). Задачи настройки, необходимые для всех функций, выполняются в классе Setup, который имеет следующую структуру:

[assembly: WebJobsStartup(typeof(Startup))]

internal class Startup : IWebJobsStartup
{
  public void Configure(IWebJobsBuilder builder)
  {
    Configuration = new ConfigurationBuilder()
                      .SetBasePath(<functionAppDirectory>)
                      .AddJsonFile("local.settings.json")
                      .Build();
    builder.AddDependencyInjection(ConfigureServices);  
  }

  public IConfiguration Configuration { get; set; }

  private void ConfigureServices(IServiceCollection services)
  {
    var connection = Configuration.GetConnectionString("<myconnection-string>");
    ...
  }
}

В ConfigureServices я хочу прочитать строку подключения из файла конфигурации. Для этого в SetBasePath указана базовая папка приложения-функции. Но я не нашел способа получить доступ к этому пути. Согласно https://github.com/Azure/azure-functions-host/wiki/Retrieving-information-about-the-currently-running-function, ExecutionContext может быть введен в функцию, которая содержит необходимый путь. Но как мне получить доступ к ExecutionContext в моем классе Startup?

Я думаю, что System.Environment.CurrentDirectory даст вам то, что вам нужно.

Tim Heikell 02.01.2019 20:44

Нет System.Environment.CurrentDirectory не работает в Azure. Та же ошибка: файл конфигурации config.json не найден и не является обязательным. Физический путь - /config.json. Работает хоть и локально.

Michael Chudinov 20.03.2019 21:24

Тебе удалось с этим разобраться? Я сейчас нахожусь в той же лодке в отношении необходимости базового пути для appsettings.json.

nagrom97 11.04.2019 17:30
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
20
3
12 180
6

Ответы 6

Попробуйте использовать Environment.CurrentDirectory

Нет, не работает. Получена ошибка: файл конфигурации config.json не найден и не является обязательным. Физический путь - /config.json.

Michael Chudinov 20.03.2019 21:19

Могу подтвердить, что это неверно, это похоже на D:\Program Files (x86)\SiteExtensions\Functions\2.0.12493\64bit, а не на wwwroot

Glenn Watson 03.06.2019 11:47

Единственный обходной путь, который я нашел для построителя конфигурации в методе Startup (), - это использовать жестко заданный путь "/ home / site / wwwroot /".

var config = new ConfigurationBuilder()
                .SetBasePath("/home/site/wwwroot/")
                .AddJsonFile("config.json", optional: false)
                .Build();

System.Environment.CurrentDirectory не работает в Azure. Хотя локально работает. Но в Azure выдает ошибку: Файл конфигурации config.json не найден и не является обязательным. Физический путь - /config.json. И функция не запускается.

TL; DR: просто используйте Environment.GetEnvironmentVariable.

Подход ConfigurationBuilder обнаруживается во многих сообщениях в блогах и работал до тех пор, пока мы не начали выполнять DI. Но параметра контекста нет, поэтому ConfigurationBuilder сразу начинает доставлять некоторую нагрузку.

Я думаю, что люди пошли в этом направлении, потому что в Azure Functions 2 мы перешли на конфигурацию ASP.NET Core, из-за чего ConfigurationManager перестал работать. ConfigurationBuilder был подходящим местом для приземления. Он казался совместимым с MVC и отлично работал до появления DI.

Но теперь, когда мы выполняем DI, становится ясно, что Environment.GetEnvironmentVariable, возможно, был лучшим выбором для этой платформы ... Здесь меньше накладных расходов на код, и он полностью соответствует модели конфигурации Функций Azure: в dev это подбирает элементы в массиве local.settings.json> Values, а при производстве он подбирает переменные среды и просто работает.

Это отличается от того, что мы делаем в MVC. Однако до тех пор, пока эти платформы не станут более сбалансированными, мы должны делать то, что имеет смысл в функциях, а не пытаться форсировать решения из MVC.

Так:

[assembly: WebJobsStartup(typeof(StartUp))]
namespace Keystone.AzureFunctions
{

    public class StartUp : IWebJobsStartup
    {
        public void Configure(IWebJobsBuilder builder)
        {           
            var connectionString = Environment.GetEnvironmentVariable("KeystoneDB");

            // Configure EF
            builder.Services.AddDbContext<KeystoneDB>(options => options.UseSqlServer(connectionString));
        }
    }
}

И ваш local.settings.json может выглядеть так:

{
    "IsEncrypted": false,
    "Values": {
        "KeystoneDB": "[CONNECTION STRING HERE]"
        "FUNCTIONS_WORKER_RUNTIME": "dotnet"
    }
}

Вы также можете использовать Key Vault с Environment. Отлично работает.

Приветствие,
Нашел решение, которое работает в автозагрузке:

var fileInfo = new FileInfo(Assembly.GetExecutingAssembly().Location);
string path = fileInfo.Directory.Parent.FullName;
var configuration = new ConfigurationBuilder()
    .SetBasePath(Environment.CurrentDirectory)
    .SetBasePath(path)
    .AddJsonFile("appsettings.json", false)
    .Build();

Вы можете использовать этот фрагмент кода в своем файле запуска. Я только что протестировал его сегодня для своего проекта, и он работает как в облаке, так и локально.

var executioncontextoptions = builder.Services.BuildServiceProvider()
    .GetService<IOptions<ExecutionContextOptions>>().Value;
var currentDirectory = executioncontextoptions.AppDirectory;

Твердый. Спасибо! (фальшивые интернет-точки для вас!;)

Jim Speaker 19.10.2020 01:46

Я сослался на ваш ответ здесь: stackoverflow.com/questions/57360238/… И добавил несколько дополнительных примеров кода и свое мнение о том, почему это имеет место в дополнение к использованию переменных среды. Еще раз спасибо за хороший ответ.

Jim Speaker 19.10.2020 02:52

Вы можете ввести IOptions<ExecutionContextOptions> прямо в ctor любого класса, зарегистрированного в контейнере DI, и он отлично работает.

Mx.Wolf 07.02.2021 14:44

Вы можете использовать FunctionsStartupAttribute и IFunctionsHostBuilder из Microsoft.Azure.Functions.Extensions, например:

[assembly:FunctionsStartup(typeof(SampleFunction.FunctionsAppStartup))]

namespace SampleFunction
{
  public class FunctionsAppStartup : FunctionsStartup
  {
    public override void Configure(IFunctionsHostBuilder builder)
    {
      string appRootPath = builder.GetContext().ApplicationRootPath;

      // ...
    }
  }
}

Другие вопросы по теме