skip to Main Content

I am encountering an error when configuring a SQL Server connection string in my Azure Function App using KeyVault to retrieve the connection string. The error message I receive is:

Message
Error configuring services in an external startup class.
Details
Microsoft.Azure.WebJobs.Script.ExternalStartupException : Error configuring services in an external startup class. —> System.ArgumentException : Keyword not supported: ‘@microsoft.keyvault(secreturi’. at Microsoft.Data.SqlClient.SqlConnectionStringBuilder.GetIndex(String keyword) at Microsoft.Data.SqlClient.SqlConnectionStringBuilder.set_Item(String keyword,Object value) at System.Data.Common.DbConnectionStringBuilder.set_ConnectionString(String value) at Microsoft.Data.SqlClient.SqlConnectionStringBuilder..ctor(String connectionString) at Serilog.Sinks.MSSqlServer.Platform.SqlClient.SqlConnectionStringBuilderWrapper..ctor(String connectionString,Boolean enlist) at Serilog.Sinks.MSSqlServer.Dependencies.SinkDependenciesFactory.Create(String connectionString,MSSqlServerSinkOptions sinkOptions,IFormatProvider formatProvider,ColumnOptions columnOptions,ITextFormatter logEventFormatter) at Serilog.Sinks.MSSqlServer.Configuration.Factories.MSSqlServerSinkFactory.Create(String connectionString,MSSqlServerSinkOptions sinkOptions,IFormatProvider formatProvider,ColumnOptions columnOptions,ITextFormatter logEventFormatter) at Serilog.LoggerConfigurationMSSqlServerExtensions.MSSqlServerInternal(LoggerSinkConfiguration loggerConfiguration,String connectionString,MSSqlServerSinkOptions sinkOptions,IConfigurationSection sinkOptionsSection,IConfiguration appConfiguration,LogEventLevel restrictedToMinimumLevel,IFormatProvider formatProvider,ColumnOptions columnOptions,IConfigurationSection columnOptionsSection,ITextFormatter logEventFormatter,IApplySystemConfiguration applySystemConfiguration,IApplyMicrosoftExtensionsConfiguration applyMicrosoftExtensionsConfiguration,IMSSqlServerSinkFactory sinkFactory,IPeriodicBatchingSinkFactory batchingSinkFactory) at MG.TRUNK.FunctionApp.Startup.ConfigureLogging(IFunctionsHostBuilder builder,IConfiguration configuration) at D:a1ssrcMG.TRUNK.FunctionAppStartup.cs : 46 at MG.TRUNK.FunctionApp.Startup.Configure(IFunctionsHostBuilder builder) at D:a1ssrcMG.TRUNK.FunctionAppStartup.cs : 25 at Microsoft.Azure.Functions.Extensions.DependencyInjection.FunctionsStartup.Configure(WebJobsBuilderContext context,IWebJobsBuilder builder) at Microsoft.Azure.WebJobs.WebJobsBuilderExtensions.ConfigureStartup(IWebJobsStartup startup,WebJobsBuilderContext context,IWebJobsBuilder builder) at D:a_work1ssrcMicrosoft.Azure.WebJobs.HostHostingWebJobsBuilderExtensions.cs : 162 at Microsoft.Azure.WebJobs.WebJobsBuilderExtensions.ConfigureAndLogUserConfiguredServices(IWebJobsStartup startup,WebJobsBuilderContext context,IWebJobsBuilder builder,ILoggerFactory loggerFactory) at D:a_work1ssrcMicrosoft.Azure.WebJobs.HostHostingWebJobsBuilderExtensions.cs : 130 at Microsoft.Azure.WebJobs.WebJobsBuilderExtensions.UseWebJobsStartup(IWebJobsBuilder builder,Type startupType,WebJobsBuilderContext context,ILoggerFactory loggerFactory) at D:a_work1ssrcMicrosoft.Azure.WebJobs.HostHostingWebJobsBuilderExtensions.cs : 115 at Microsoft.Azure.WebJobs.WebJobsBuilderExtensions.UseExternalStartup(IWebJobsBuilder builder,IWebJobsStartupTypeLocator startupTypeLocator,WebJobsBuilderContext context,ILoggerFactory loggerFactory) at D:a_work1ssrcMicrosoft.Azure.WebJobs.HostHostingWebJobsBuilderExtensions.cs : 213 at Microsoft.Azure.WebJobs.Script.ScriptHostBuilderExtensions.<>c__DisplayClass7_0.b__1(HostBuilderContext context,IWebJobsBuilder webJobsBuilder) at /_/src/WebJobs.Script/ScriptHostBuilderExtensions.cs : 235 End of inner exception


What is weird is that the azure functions get the connection strings correctly and i see logs in database

Azure portal warning

2

Answers


  1. Chosen as BEST ANSWER
    public class Startup : FunctionsStartup
    {
        public override void Configure(IFunctionsHostBuilder builder)
        {
            var configuration = builder.GetContext().Configuration;
    
            builder.Services.AddSingleton(configuration).ConfigureServicesForDependencyInjection(configuration);
            ConfigureLogging(builder, configuration);
        }
    
        /// <summary>
        /// Configures logging for the Azure Functions
        /// </summary>
        /// <param name="builder"></param>
        /// <param name="configuration"></param>
        private static void ConfigureLogging(IFunctionsHostBuilder builder, IConfiguration configuration)
        {
            string version = Assembly.GetExecutingAssembly().GetName().Version.ToString();
    
            var columnOptions = new ColumnOptions();
            columnOptions.Store.Remove(StandardColumn.Properties);
            columnOptions.Store.Remove(StandardColumn.MessageTemplate);
            columnOptions.AdditionalColumns = new List<SqlColumn>
            {
                new SqlColumn { DataType = SqlDbType.NVarChar, ColumnName = "CorrelationID" },
                new SqlColumn { DataType = SqlDbType.NVarChar, ColumnName = "Details" }
            };
    
            var logger = new LoggerConfiguration()
                .MinimumLevel.Information()
                .MinimumLevel.Override("Microsoft", LogEventLevel.Warning)
                .MinimumLevel.Override("System", LogEventLevel.Warning)
                .MinimumLevel.Override("Microsoft.Azure.WebJobs", LogEventLevel.Error)
                .MinimumLevel.Override("Microsoft.Azure.WebJobs.Host", LogEventLevel.Error)
                .Enrich.FromLogContext()
                .Enrich.WithProperty("Version", version)
                .WriteTo.Console(outputTemplate: "[v{Version}]t[{Timestamp:u}]t[{Level:u3}]t[{SourceContext}]t{Message}{NewLine}{Exception}")
                .WriteTo.MSSqlServer(
                    connectionString: configuration.GetSection("AzureSqlConnectionString").Value,
                    sinkOptions: new MSSqlServerSinkOptions
                    {
                        TableName = configuration.GetSection("LogTable").Value,
                    },
                    restrictedToMinimumLevel: LogEventLevel.Information,
                    columnOptions: columnOptions)
                .Filter.ByExcluding(logEvent =>
                logEvent.Properties.ContainsKey("SourceContext") &&
                (logEvent.Properties["SourceContext"].ToString().Contains("FunctionExecutor") ||
                logEvent.Properties["SourceContext"].ToString().Contains("Host.Results") ||
                logEvent.Properties["SourceContext"].ToString().Contains("Host.Aggregator") ||
                logEvent.MessageTemplate.Text.Contains("Executing") || logEvent.MessageTemplate.Text.Contains("Executed")))
                .CreateLogger();
    
            builder.Services.AddLogging(loggingBuilder =>
            {
                loggingBuilder.AddSerilog(logger, dispose: true);
            });
        }
    }
    

  2. Regarding the following error message:

    System.ArgumentException : Keyword not supported: ‘@microsoft.keyvault(secreturi’.

    Double-check your Azure Keyvault reference has the right format – example:

    @Microsoft.KeyVault(SecretUri=https://myvault.vault.azure.net/secrets/mysecret)
    

    Including a version:

    @Microsoft.KeyVault(SecretUri=https://myvault.vault.azure.net/secrets/mysecret/ec96f02080254f109c51a1f14cdb1931)
    

    Alternatively:

    @Microsoft.KeyVault(VaultName=myvault;SecretName=mysecret)
    

    Also, I’m not sure if the keyvault reference is case-sensitive so instead of:

    @microsoft.keyvault(secreturi=...)
    

    Try:

    @Microsoft.KeyVault(SecretUri=...)
    

    Finally, remember you need to grant your Azure function access to the key vault.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search