internal SettingBatch(ConfigurationSetting[] settings, string link, SettingSelector selector)
 {
     _settings = settings;
     _link     = link;
     _selector = selector;
 }
        public async Task GetBatch()
        {
            var response1 = new MockResponse(200);

            response1.SetContent(SerializationHelpers.Serialize(new []
            {
                CreateSetting(0),
                CreateSetting(1),
            }, SerializeBatch));
            response1.AddHeader(new HttpHeader("Link", $"</kv?after=5>;rel=\"next\""));

            var response2 = new MockResponse(200);

            response2.SetContent(SerializationHelpers.Serialize(new []
            {
                CreateSetting(2),
                CreateSetting(3),
                CreateSetting(4),
            }, SerializeBatch));

            var mockTransport           = new MockTransport(response1, response2);
            ConfigurationClient service = CreateTestService(mockTransport);

            var query    = new SettingSelector();
            int keyIndex = 0;

            while (true)
            {
                using (Response <SettingBatch> response = await service.GetBatchAsync(query, CancellationToken.None))
                {
                    SettingBatch batch = response.Value;
                    for (int i = 0; i < batch.Count; i++)
                    {
                        ConfigurationSetting value = batch[i];
                        Assert.AreEqual("key" + keyIndex, value.Key);
                        keyIndex++;
                    }

                    var nextBatch = batch.NextBatch;

                    if (nextBatch == null)
                    {
                        break;
                    }

                    query = nextBatch;
                }
            }

            Assert.AreEqual(2, mockTransport.Requests.Count);

            MockRequest request1 = mockTransport.Requests[0];

            Assert.AreEqual(HttpPipelineMethod.Get, request1.Method);
            Assert.AreEqual("https://contoso.appconfig.io/kv/?key=*&label=*", request1.UriBuilder.ToString());
            AssertRequestCommon(request1);

            MockRequest request2 = mockTransport.Requests[1];

            Assert.AreEqual(HttpPipelineMethod.Get, request2.Method);
            Assert.AreEqual("https://contoso.appconfig.io/kv/?key=*&label=*&after=5", request2.UriBuilder.ToString());
            AssertRequestCommon(request1);
        }
        private async Task <ICollection <KeyValuePair <string, string> > > GetAllValuesAsync(string prefix)
        {
            Dictionary <string, string> data = new Dictionary <string, string>(StringComparer.OrdinalIgnoreCase);

            if (_client == null)
            {
                return(data);
            }

            SettingSelector selector = new SettingSelector();

            if (_keyFilter != null)
            {
                selector.KeyFilter = _keyFilter;
            }
            if (_labelFilter != null)
            {
                selector.LabelFilter = _labelFilter;
            }
            if (_dateTimeFilter > DateTimeOffset.MinValue)
            {
                selector.AcceptDateTime = _dateTimeFilter;
            }
            // TODO: Reduce bandwidth by limiting the fields we retrieve.
            // Currently, content type doesn't get delivered, even if we add it to the selection. This prevents KeyVault recognition.
            //selector.Fields = SettingFields.Key | SettingFields.Value | SettingFields.ContentType;

            // We don't make any guarantees about which kv get precendence when there are multiple of the same key...
            // But the config service does seem to return kvs in a preferred order - no label first, then alphabetical by label.
            // Prefer the first kv we encounter from the config service.
            try
            {
                AsyncPageable <ConfigurationSetting>    settings   = _client.GetConfigurationSettingsAsync(selector);
                IAsyncEnumerator <ConfigurationSetting> enumerator = settings.GetAsyncEnumerator();
                try
                {
                    while (await enumerator.MoveNextAsync())
                    {
                        ConfigurationSetting setting = enumerator.Current;
                        string configValue           = setting.Value;

                        // If it's a key vault reference, go fetch the value from key vault
                        if (_useKeyVault && IsKeyVaultReference(setting))
                        {
                            try
                            {
                                configValue = await GetKeyVaultValue(setting);
                            }
                            catch (Exception)
                            {
                                // 'Optional' plays a double role with this provider. Being optional means it is
                                // ok for us to fail to resolve a keyvault reference. If we are not optional though,
                                // we want to make some noise when a reference fails to resolve.
                                if (!Optional)
                                {
                                    throw;
                                }
                            }
                        }

                        if (!data.ContainsKey(setting.Key))
                        {
                            data[setting.Key] = configValue;
                        }
                    }
                }
                finally
                {
                    await enumerator.DisposeAsync();
                }
            }
            catch (Exception e) when(Optional && ((e.InnerException is System.Net.Http.HttpRequestException) || (e.InnerException is UnauthorizedAccessException)))
            {
            }

            return(data);
        }
        public async Task HelloWorldExtended()
        {
            var connectionString = Environment.GetEnvironmentVariable("APPCONFIGURATION_CONNECTION_STRING");

            #region Snippet:AzConfigSample2_CreateConfigurationClient
            var client = new ConfigurationClient(connectionString);
            #endregion

            #region Snippet:AzConfigSample2_CreateConfigurationSettingAsync
            var betaEndpoint        = new ConfigurationSetting("endpoint", "https://beta.endpoint.com", "beta");
            var betaInstances       = new ConfigurationSetting("instances", "1", "beta");
            var productionEndpoint  = new ConfigurationSetting("endpoint", "https://production.endpoint.com", "production");
            var productionInstances = new ConfigurationSetting("instances", "1", "production");
            #endregion

            #region Snippet:AzConfigSample2_AddConfigurationSettingAsync
            await client.AddConfigurationSettingAsync(betaEndpoint);

            await client.AddConfigurationSettingAsync(betaInstances);

            await client.AddConfigurationSettingAsync(productionEndpoint);

            await client.AddConfigurationSettingAsync(productionInstances);

            #endregion

            #region Snippet:AzConfigSample2_GetConfigurationSettingAsync
            ConfigurationSetting instancesToUpdate = await client.GetConfigurationSettingAsync(productionInstances.Key, productionInstances.Label);

            #endregion

            #region Snippet:AzConfigSample2_SetUpdatedConfigurationSettingAsync
            instancesToUpdate.Value = "5";
            await client.SetConfigurationSettingAsync(instancesToUpdate);

            #endregion


            #region Snippet:AzConfigSample2_GetConfigurationSettingsAsync
            var selector = new SettingSelector {
                LabelFilter = "production"
            };

            Debug.WriteLine("Settings for Production environment:");
            await foreach (ConfigurationSetting setting in client.GetConfigurationSettingsAsync(selector))
            {
                Console.WriteLine(setting);
            }
            #endregion

            // Delete the Configuration Settings from the Configuration Store.
            #region Snippet:AzConfigSample2_DeleteConfigurationSettingAsync
            await client.DeleteConfigurationSettingAsync(betaEndpoint.Key, betaEndpoint.Label);

            await client.DeleteConfigurationSettingAsync(betaInstances.Key, betaInstances.Label);

            await client.DeleteConfigurationSettingAsync(productionEndpoint.Key, productionEndpoint.Label);

            await client.DeleteConfigurationSettingAsync(productionInstances.Key, productionInstances.Label);

            #endregion
        }
        private async Task <string> GetValueAsync(string key)
        {
            if (_client == null)
            {
                return(null);
            }

            SettingSelector selector = new SettingSelector();

            selector.KeyFilter = key;
            if (_labelFilter != null)
            {
                selector.LabelFilter = _labelFilter;
            }
            if (_dateTimeFilter > DateTimeOffset.MinValue)
            {
                selector.AcceptDateTime = _dateTimeFilter;
            }
            // TODO: Reduce bandwidth by limiting the fields we retrieve.
            // Currently, content type doesn't get delivered, even if we add it to the selection. This prevents KeyVault recognition.
            //selector.Fields = SettingFields.Key | SettingFields.Value | SettingFields.ContentType;

            try
            {
                AsyncPageable <ConfigurationSetting>    settings   = _client.GetConfigurationSettingsAsync(selector);
                IAsyncEnumerator <ConfigurationSetting> enumerator = settings.GetAsyncEnumerator();

                try
                {
                    // There should only be one result. If there's more, we're only returning the fisrt.
                    await enumerator.MoveNextAsync();

                    ConfigurationSetting current = enumerator.Current;
                    if (current == null)
                    {
                        return(null);
                    }

                    if (_useKeyVault && IsKeyVaultReference(current))
                    {
                        try
                        {
                            return(await GetKeyVaultValue(current));
                        }
                        catch (Exception)
                        {
                            // 'Optional' plays a double role with this provider. Being optional means it is
                            // ok for us to fail to resolve a keyvault reference. If we are not optional though,
                            // we want to make some noise when a reference fails to resolve.
                            if (!Optional)
                            {
                                throw;
                            }
                        }
                    }

                    return(current.Value);
                }
                finally
                {
                    await enumerator.DisposeAsync();
                }
            }
            catch (Exception e) when(Optional && ((e.InnerException is System.Net.Http.HttpRequestException) || (e.InnerException is UnauthorizedAccessException)))
            {
            }

            return(null);
        }