Я создаю приложение-функцию 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 не работает в Azure. Та же ошибка: файл конфигурации config.json не найден и не является обязательным. Физический путь - /config.json. Работает хоть и локально.
Тебе удалось с этим разобраться? Я сейчас нахожусь в той же лодке в отношении необходимости базового пути для appsettings.json.
Попробуйте использовать Environment.CurrentDirectory
Нет, не работает. Получена ошибка: файл конфигурации config.json не найден и не является обязательным. Физический путь - /config.json.
Могу подтвердить, что это неверно, это похоже на D:\Program Files (x86)\SiteExtensions\Functions\2.0.12493\64bit
, а не на wwwroot
Единственный обходной путь, который я нашел для построителя конфигурации в методе 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;
Твердый. Спасибо! (фальшивые интернет-точки для вас!;)
Я сослался на ваш ответ здесь: stackoverflow.com/questions/57360238/… И добавил несколько дополнительных примеров кода и свое мнение о том, почему это имеет место в дополнение к использованию переменных среды. Еще раз спасибо за хороший ответ.
Вы можете ввести IOptions<ExecutionContextOptions>
прямо в ctor любого класса, зарегистрированного в контейнере DI, и он отлично работает.
Вы можете использовать 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;
// ...
}
}
}
Я думаю, что System.Environment.CurrentDirectory даст вам то, что вам нужно.