< Summary

Class:Azure.Data.AppConfiguration.ConfigurationClient
Assembly:Azure.Data.AppConfiguration
File(s):C:\Git\azure-sdk-for-net\sdk\appconfiguration\Azure.Data.AppConfiguration\src\ConfigurationClient.cs
C:\Git\azure-sdk-for-net\sdk\appconfiguration\Azure.Data.AppConfiguration\src\ConfigurationClient_private.cs
Covered lines:365
Uncovered lines:37
Coverable lines:402
Total lines:1129
Line coverage:90.7% (365 of 402)
Covered branches:83
Total branches:106
Branch coverage:78.3% (83 of 106)

Metrics

MethodCyclomatic complexity Line coverage Branch coverage
.ctor()-100%100%
.ctor(...)-0%100%
.ctor(...)-77.78%50%
.ctor(...)-0%100%
.ctor(...)-100%100%
CreatePipeline(...)-100%100%
GetDefaultScope(...)-100%100%
AddConfigurationSettingAsync()-100%100%
AddConfigurationSetting(...)-100%100%
AddConfigurationSettingAsync()-92.31%66.67%
AddConfigurationSetting(...)-92.31%66.67%
CreateAddRequest(...)-100%100%
SetConfigurationSettingAsync()-100%100%
SetConfigurationSetting(...)-100%100%
SetConfigurationSettingAsync()-100%83.33%
SetConfigurationSetting(...)-100%83.33%
CreateSetRequest(...)-100%100%
DeleteConfigurationSettingAsync()-100%100%
DeleteConfigurationSetting(...)-100%100%
DeleteConfigurationSettingAsync()-100%100%
DeleteConfigurationSetting(...)-100%100%
DeleteConfigurationSettingAsync()-100%100%
DeleteConfigurationSetting(...)-100%100%
CreateDeleteRequest(...)-100%100%
GetConfigurationSettingAsync()-100%100%
GetConfigurationSetting(...)-100%100%
GetConfigurationSettingAsync()-100%50%
GetConfigurationSetting(...)-100%50%
GetConfigurationSettingAsync()-100%100%
GetConfigurationSetting(...)-100%100%
GetConfigurationSettingAsync()-100%100%
GetConfigurationSetting(...)-100%100%
GetConfigurationSettingsAsync(...)-100%100%
GetConfigurationSettings(...)-100%100%
GetRevisionsAsync(...)-100%100%
GetRevisions(...)-100%100%
GetRevisionsAsync(...)-100%100%
GetRevisions(...)-100%100%
CreateGetRequest(...)-100%100%
GetConfigurationSettingsPageAsync()-66.67%50%
GetConfigurationSettingsPage(...)-66.67%50%
CreateBatchRequest(...)-75%50%
GetRevisionsPageAsync()-66.67%50%
GetRevisionsPage(...)-66.67%50%
CreateGetRevisionsRequest(...)-100%100%
SetReadOnlyAsync(...)-100%100%
SetReadOnly(...)-100%100%
SetReadOnlyAsync()-100%100%
SetReadOnly(...)-100%100%
CreateSetReadOnlyRequest(...)-100%100%
.cctor()-100%100%
CreateResponseAsync()-100%100%
CreateResponse(...)-100%100%
CreateResourceModifiedResponse(...)-100%100%
ParseConnectionString(...)-75%100%
BuildUriForKvRoute(...)-100%100%
BuildUriForKvRoute(...)-100%100%
BuildUriForLocksRoute(...)-100%100%
EscapeReservedCharacters(...)-0%0%
BuildBatchQuery(...)-100%100%
BuildUriForGetBatch(...)-100%100%
BuildUriForRevisions(...)-100%100%
Equals(...)-0%100%
GetHashCode()-0%100%
ToString()-0%100%

File(s)

C:\Git\azure-sdk-for-net\sdk\appconfiguration\Azure.Data.AppConfiguration\src\ConfigurationClient.cs

#LineLine coverage
 1// Copyright (c) Microsoft Corporation. All rights reserved.
 2// Licensed under the MIT License.
 3
 4using System;
 5using System.Collections.Generic;
 6using System.Globalization;
 7using System.Threading;
 8using System.Threading.Tasks;
 9using Azure.Core;
 10using Azure.Core.Pipeline;
 11
 12namespace Azure.Data.AppConfiguration
 13{
 14    /// <summary>
 15    /// The client to use for interacting with the Azure Configuration Store.
 16    /// </summary>
 17    public partial class ConfigurationClient
 18    {
 19        private readonly Uri _endpoint;
 20        private readonly HttpPipeline _pipeline;
 21        private readonly ClientDiagnostics _clientDiagnostics;
 22
 23        /// <summary>
 24        /// Protected constructor to allow mocking.
 25        /// </summary>
 32426        protected ConfigurationClient()
 27        {
 32428        }
 29
 30        /// <summary>
 31        /// Initializes a new instance of the <see cref="ConfigurationClient"/> class.
 32        /// </summary>
 33        /// <param name="connectionString">Connection string with authentication option and related parameters.</param>
 34        public ConfigurationClient(string connectionString)
 035            : this(connectionString, new ConfigurationClientOptions())
 36        {
 037        }
 38
 39        /// <summary>
 40        /// Initializes a new instance of the <see cref="ConfigurationClient"/> class.
 41        /// </summary>
 42        /// <param name="connectionString">Connection string with authentication option and related parameters.</param>
 43        /// <param name="options">Options that allow configuration of requests sent to the configuration store.</param>
 32044        public ConfigurationClient(string connectionString, ConfigurationClientOptions options)
 45        {
 32046            if (connectionString == null)
 047                throw new ArgumentNullException(nameof(connectionString));
 32048            if (options == null)
 049                throw new ArgumentNullException(nameof(options));
 50
 32051            ParseConnectionString(connectionString, out _endpoint, out var credential, out var secret);
 52
 32053            _pipeline = CreatePipeline(options, new AuthenticationPolicy(credential, secret));
 54
 32055            _clientDiagnostics = new ClientDiagnostics(options);
 32056        }
 57
 58        /// <summary>
 59        /// Initializes a new instance of the <see cref="ConfigurationClient"/> class.
 60        /// </summary>
 61        /// <param name="endpoint">The <see cref="Uri"/> referencing the app configuration storage.</param>
 62        /// <param name="credential">The token credential used to sign requests.</param>
 63        public ConfigurationClient(Uri endpoint, TokenCredential credential)
 064            : this(endpoint, credential, new ConfigurationClientOptions())
 65        {
 066        }
 67
 68        /// <summary>
 69        /// Initializes a new instance of the <see cref="ConfigurationClient"/> class.
 70        /// </summary>
 71        /// <param name="endpoint">The <see cref="Uri"/> referencing the app configuration storage.</param>
 72        /// <param name="credential">The token credential used to sign requests.</param>
 73        /// <param name="options">Options that allow configuration of requests sent to the configuration store.</param>
 474        public ConfigurationClient(Uri endpoint, TokenCredential credential, ConfigurationClientOptions options)
 75        {
 476            Argument.AssertNotNull(endpoint, nameof(endpoint));
 477            Argument.AssertNotNull(credential, nameof(credential));
 78
 479            _endpoint = endpoint;
 480            _pipeline = CreatePipeline(options, new BearerTokenAuthenticationPolicy(credential, GetDefaultScope(endpoint
 81
 482            _clientDiagnostics = new ClientDiagnostics(options);
 483        }
 84
 85        private static HttpPipeline CreatePipeline(ConfigurationClientOptions options, HttpPipelinePolicy authentication
 32486            => HttpPipelineBuilder.Build(options,
 32487                new HttpPipelinePolicy[] { new CustomHeadersPolicy(), new ApiVersionPolicy(options.GetVersionString()) }
 32488                new HttpPipelinePolicy[] { authenticationPolicy, new SyncTokenPolicy() },
 32489                new ResponseClassifier());
 90
 91        private static string GetDefaultScope(Uri uri)
 492            => $"{uri.GetComponents(UriComponents.SchemeAndServer, UriFormat.SafeUnescaped)}/.default";
 93
 94        /// <summary>
 95        /// Creates a <see cref="ConfigurationSetting"/> if the setting, uniquely identified by key and label, does not 
 96        /// </summary>
 97        /// <param name="key">The primary identifier of the configuration setting.</param>
 98        /// <param name="value">The configuration setting's value.</param>
 99        /// <param name="label">A label used to group this configuration setting with others.</param>
 100        /// <param name="cancellationToken">A <see cref="CancellationToken"/> controlling the request lifetime.</param>
 101        /// <returns>A response containing the added <see cref="ConfigurationSetting"/>.</returns>
 102        public virtual async Task<Response<ConfigurationSetting>> AddConfigurationSettingAsync(string key, string value,
 103        {
 8104            Argument.AssertNotNullOrEmpty(key, nameof(key));
 8105            return await AddConfigurationSettingAsync(new ConfigurationSetting(key, value, label), cancellationToken).Co
 8106        }
 107
 108        /// <summary>
 109        /// Creates a <see cref="ConfigurationSetting"/> if the setting, uniquely identified by key and label, does not 
 110        /// </summary>
 111        /// <param name="key">The primary identifier of the configuration setting.</param>
 112        /// <param name="value">The configuration setting's value.</param>
 113        /// <param name="label">A label used to group this configuration setting with others.</param>
 114        /// <param name="cancellationToken">A <see cref="CancellationToken"/> controlling the request lifetime.</param>
 115        /// <returns>A response containing the added <see cref="ConfigurationSetting"/>.</returns>
 116        public virtual Response<ConfigurationSetting> AddConfigurationSetting(string key, string value, string label = d
 117        {
 8118            Argument.AssertNotNullOrEmpty(key, nameof(key));
 8119            return AddConfigurationSetting(new ConfigurationSetting(key, value, label), cancellationToken);
 120        }
 121
 122        /// <summary>
 123        /// Creates a <see cref="ConfigurationSetting"/> only if the setting does not already exist in the configuration
 124        /// </summary>
 125        /// <param name="setting">The <see cref="ConfigurationSetting"/> to create.</param>
 126        /// <param name="cancellationToken">A <see cref="CancellationToken"/> controlling the request lifetime.</param>
 127        /// <returns>A response containing the added <see cref="ConfigurationSetting"/>.</returns>
 128        public virtual async Task<Response<ConfigurationSetting>> AddConfigurationSettingAsync(ConfigurationSetting sett
 129        {
 54130            using DiagnosticScope scope = _clientDiagnostics.CreateScope($"{nameof(ConfigurationClient)}.{nameof(AddConf
 54131            scope.AddAttribute("key", setting?.Key);
 54132            scope.Start();
 133
 134            try
 135            {
 54136                using Request request = CreateAddRequest(setting);
 54137                Response response = await _pipeline.SendRequestAsync(request, cancellationToken).ConfigureAwait(false);
 138
 54139                switch (response.Status)
 140                {
 141                    case 200:
 142                    case 201:
 50143                        return await CreateResponseAsync(response, cancellationToken).ConfigureAwait(false);
 144                    case 412:
 4145                        throw await _clientDiagnostics.CreateRequestFailedExceptionAsync(response, "Setting was already 
 146                    default:
 0147                        throw await _clientDiagnostics.CreateRequestFailedExceptionAsync(response).ConfigureAwait(false)
 148                }
 149            }
 4150            catch (Exception e)
 151            {
 4152                scope.Failed(e);
 4153                throw;
 154            }
 50155        }
 156
 157        /// <summary>
 158        /// Creates a <see cref="ConfigurationSetting"/> only if the setting does not already exist in the configuration
 159        /// </summary>
 160        /// <param name="setting">The <see cref="ConfigurationSetting"/> to create.</param>
 161        /// <param name="cancellationToken">A <see cref="CancellationToken"/> controlling the request lifetime.</param>
 162        /// <returns>A response containing the added <see cref="ConfigurationSetting"/>.</returns>
 163        public virtual Response<ConfigurationSetting> AddConfigurationSetting(ConfigurationSetting setting, Cancellation
 164        {
 54165            using DiagnosticScope scope = _clientDiagnostics.CreateScope($"{nameof(ConfigurationClient)}.{nameof(AddConf
 54166            scope.AddAttribute("key", setting?.Key);
 54167            scope.Start();
 168
 169            try
 170            {
 54171                using Request request = CreateAddRequest(setting);
 54172                Response response = _pipeline.SendRequest(request, cancellationToken);
 173
 54174                switch (response.Status)
 175                {
 176                    case 200:
 177                    case 201:
 50178                        return CreateResponse(response);
 179                    case 412:
 4180                        throw _clientDiagnostics.CreateRequestFailedException(response, "Setting was already present.");
 181                    default:
 0182                        throw _clientDiagnostics.CreateRequestFailedException(response);
 183                }
 184            }
 4185            catch (Exception e)
 186            {
 4187                scope.Failed(e);
 4188                throw;
 189            }
 50190        }
 191
 192        private Request CreateAddRequest(ConfigurationSetting setting)
 193        {
 108194            Argument.AssertNotNull(setting, nameof(setting));
 108195            Argument.AssertNotNullOrEmpty(setting.Key, $"{nameof(setting)}.{nameof(setting.Key)}");
 196
 108197            Request request = _pipeline.CreateRequest();
 198
 108199            ReadOnlyMemory<byte> content = ConfigurationServiceSerializer.SerializeRequestBody(setting);
 200
 108201            request.Method = RequestMethod.Put;
 202
 108203            BuildUriForKvRoute(request.Uri, setting);
 204
 108205            MatchConditions requestOptions = new MatchConditions { IfNoneMatch = ETag.All };
 108206            ConditionalRequestOptionsExtensions.ApplyHeaders(request, requestOptions);
 207
 108208            request.Headers.Add(s_mediaTypeKeyValueApplicationHeader);
 108209            request.Headers.Add(HttpHeader.Common.JsonContentType);
 108210            request.Content = RequestContent.Create(content);
 211
 108212            return request;
 213        }
 214
 215        /// <summary>
 216        /// Creates a <see cref="ConfigurationSetting"/>, uniquely identified by key and label, if it doesn't exist or o
 217        /// </summary>
 218        /// <param name="key">The primary identifier of the configuration setting.</param>
 219        /// <param name="value">The configuration setting's value.</param>
 220        /// <param name="label">A label used to group this configuration setting with others.</param>
 221        /// <param name="cancellationToken">A <see cref="CancellationToken"/> controlling the request lifetime.</param>
 222        /// <returns>A response containing the <see cref="ConfigurationSetting"/> written to the configuration store.</r
 223        public virtual async Task<Response<ConfigurationSetting>> SetConfigurationSettingAsync(string key, string value,
 224        {
 6225            Argument.AssertNotNullOrEmpty(key, nameof(key));
 6226            return await SetConfigurationSettingAsync(new ConfigurationSetting(key, value, label), false, cancellationTo
 4227        }
 228
 229        /// <summary>
 230        /// Creates a <see cref="ConfigurationSetting"/>, uniquely identified by key and label, if it doesn't exist or o
 231        /// </summary>
 232        /// <param name="key">The primary identifier of the configuration setting.</param>
 233        /// <param name="value">The configuration setting's value.</param>
 234        /// <param name="label">A label used to group this configuration setting with others.</param>
 235        /// <param name="cancellationToken">A <see cref="CancellationToken"/> controlling the request lifetime.</param>
 236        /// <returns>A response containing the <see cref="ConfigurationSetting"/> written to the configuration store.</r
 237        public virtual Response<ConfigurationSetting> SetConfigurationSetting(string key, string value, string label = d
 238        {
 6239            Argument.AssertNotNullOrEmpty(key, nameof(key));
 6240            return SetConfigurationSetting(new ConfigurationSetting(key, value, label), false, cancellationToken);
 241        }
 242
 243        /// <summary>
 244        /// Creates a <see cref="ConfigurationSetting"/> if it doesn't exist or overwrites the existing setting in the c
 245        /// </summary>
 246        /// <param name="setting">The <see cref="ConfigurationSetting"/> to create.</param>
 247        /// <param name="onlyIfUnchanged">If set to true and the configuration setting exists in the configuration store
 248        /// if the passed-in <see cref="ConfigurationSetting"/> is the same version as the one in the configuration stor
 249        /// are the same if their ETag fields match.  If the two settings are different versions, this method will throw
 250        /// that the setting in the configuration store was modified since it was last obtained by the client.</param>
 251        /// <param name="cancellationToken">A <see cref="CancellationToken"/> controlling the request lifetime.</param>
 252        /// <returns>A response containing the <see cref="ConfigurationSetting"/> written to the configuration store.</r
 253        public virtual async Task<Response<ConfigurationSetting>> SetConfigurationSettingAsync(ConfigurationSetting sett
 254        {
 90255            Argument.AssertNotNull(setting, nameof(setting));
 90256            using DiagnosticScope scope = _clientDiagnostics.CreateScope($"{nameof(ConfigurationClient)}.{nameof(SetConf
 90257            scope.AddAttribute("key", setting?.Key);
 90258            scope.Start();
 259
 260            try
 261            {
 90262                using Request request = CreateSetRequest(setting, onlyIfUnchanged);
 90263                Response response = await _pipeline.SendRequestAsync(request, cancellationToken).ConfigureAwait(false);
 264
 90265                return response.Status switch
 90266                {
 172267                    200 => await CreateResponseAsync(response, cancellationToken).ConfigureAwait(false),
 94268                    409 => throw await _clientDiagnostics.CreateRequestFailedExceptionAsync(response, "The setting is re
 90269
 90270                    // Throws on 412 if resource was modified.
 94271                    _ => throw await _clientDiagnostics.CreateRequestFailedExceptionAsync(response).ConfigureAwait(false
 90272                };
 273            }
 8274            catch (Exception e)
 275            {
 8276                scope.Failed(e);
 8277                throw;
 278            }
 82279        }
 280
 281        /// <summary>
 282        /// Creates a <see cref="ConfigurationSetting"/> if it doesn't exist or overwrites the existing setting in the c
 283        /// </summary>
 284        /// <param name="setting">The <see cref="ConfigurationSetting"/> to create.</param>
 285        /// <param name="onlyIfUnchanged">If set to true and the configuration setting exists in the configuration store
 286        /// if the passed-in <see cref="ConfigurationSetting"/> is the same version as the one in the configuration stor
 287        /// are the same if their ETag fields match.  If the two settings are different versions, this method will throw
 288        /// that the setting in the configuration store was modified since it was last obtained by the client.</param>
 289        /// <param name="cancellationToken">A <see cref="CancellationToken"/> controlling the request lifetime.</param>
 290        /// <returns>A response containing the <see cref="ConfigurationSetting"/> written to the configuration store.</r
 291        public virtual Response<ConfigurationSetting> SetConfigurationSetting(ConfigurationSetting setting, bool onlyIfU
 292        {
 90293            Argument.AssertNotNull(setting, nameof(setting));
 90294            using DiagnosticScope scope = _clientDiagnostics.CreateScope($"{nameof(ConfigurationClient)}.{nameof(SetConf
 90295            scope.AddAttribute("key", setting?.Key);
 90296            scope.Start();
 297
 298            try
 299            {
 90300                using Request request = CreateSetRequest(setting, onlyIfUnchanged);
 90301                Response response = _pipeline.SendRequest(request, cancellationToken);
 302
 90303                return response.Status switch
 90304                {
 172305                    200 => CreateResponse(response),
 94306                    409 => throw _clientDiagnostics.CreateRequestFailedException(response, "The setting is read only"),
 90307
 90308                    // Throws on 412 if resource was modified.
 94309                    _ => throw _clientDiagnostics.CreateRequestFailedException(response),
 90310                };
 311            }
 8312            catch (Exception e)
 313            {
 8314                scope.Failed(e);
 8315                throw;
 316            }
 82317        }
 318
 319        private Request CreateSetRequest(ConfigurationSetting setting, bool onlyIfChanged)
 320        {
 180321            Argument.AssertNotNull(setting, nameof(setting));
 180322            Argument.AssertNotNullOrEmpty(setting.Key, $"{nameof(setting)}.{nameof(setting.Key)}");
 323
 180324            Request request = _pipeline.CreateRequest();
 180325            ReadOnlyMemory<byte> content = ConfigurationServiceSerializer.SerializeRequestBody(setting);
 326
 180327            request.Method = RequestMethod.Put;
 180328            BuildUriForKvRoute(request.Uri, setting);
 180329            request.Headers.Add(s_mediaTypeKeyValueApplicationHeader);
 180330            request.Headers.Add(HttpHeader.Common.JsonContentType);
 331
 180332            if (onlyIfChanged)
 333            {
 16334                ConditionalRequestOptionsExtensions.ApplyHeaders(request, new MatchConditions { IfMatch = setting.ETag }
 335            }
 336
 180337            request.Content = RequestContent.Create(content);
 180338            return request;
 339        }
 340
 341        /// <summary>
 342        /// Delete a <see cref="ConfigurationSetting"/> from the configuration store.
 343        /// </summary>
 344        /// <param name="key">The primary identifier of the configuration setting.</param>
 345        /// <param name="label">A label used to group this configuration setting with others.</param>
 346        /// <param name="cancellationToken">A <see cref="CancellationToken"/> controlling the request lifetime.</param>
 347        /// <returns>A response indicating the success of the operation.</returns>
 348        public virtual async Task<Response> DeleteConfigurationSettingAsync(string key, string label = default, Cancella
 349        {
 104350            Argument.AssertNotNullOrEmpty(key, nameof(key));
 104351            return await DeleteConfigurationSettingAsync(key, label, default, cancellationToken).ConfigureAwait(false);
 100352        }
 353
 354        /// <summary>
 355        /// Delete a <see cref="ConfigurationSetting"/> from the configuration store.
 356        /// </summary>
 357        /// <param name="key">The primary identifier of the configuration setting.</param>
 358        /// <param name="label">A label used to group this configuration setting with others.</param>
 359        /// <param name="cancellationToken">A <see cref="CancellationToken"/> controlling the request lifetime.</param>
 360        /// <returns>A response indicating the success of the operation.</returns>
 361        public virtual Response DeleteConfigurationSetting(string key, string label = default, CancellationToken cancell
 362        {
 104363            Argument.AssertNotNullOrEmpty(key, nameof(key));
 104364            return DeleteConfigurationSetting(key, label, default, cancellationToken);
 365        }
 366
 367        /// <summary>
 368        /// Delete a <see cref="ConfigurationSetting"/> from the configuration store.
 369        /// </summary>
 370        /// <param name="setting">The <see cref="ConfigurationSetting"/> to delete.</param>
 371        /// <param name="onlyIfUnchanged">If set to true and the configuration setting exists in the configuration store
 372        /// if the passed-in <see cref="ConfigurationSetting"/> is the same version as the one in the configuration stor
 373        /// are the same if their ETag fields match.  If the two settings are different versions, this method will throw
 374        /// that the setting in the configuration store was modified since it was last obtained by the client.</param>
 375        /// <param name="cancellationToken">A <see cref="CancellationToken"/> controlling the request lifetime.</param>
 376        /// <returns>A response indicating the success of the operation.</returns>
 377        public virtual async Task<Response> DeleteConfigurationSettingAsync(ConfigurationSetting setting, bool onlyIfUnc
 378        {
 18379            Argument.AssertNotNull(setting, nameof(setting));
 18380            MatchConditions requestOptions = onlyIfUnchanged ? new MatchConditions { IfMatch = setting.ETag } : default;
 18381            return await DeleteConfigurationSettingAsync(setting.Key, setting.Label, requestOptions, cancellationToken).
 12382        }
 383
 384        /// <summary>
 385        /// Delete a <see cref="ConfigurationSetting"/> from the configuration store.
 386        /// </summary>
 387        /// <param name="setting">The <see cref="ConfigurationSetting"/> to delete.</param>
 388        /// <param name="onlyIfUnchanged">If set to true and the configuration setting exists in the configuration store
 389        /// if the passed-in <see cref="ConfigurationSetting"/> is the same version as the one in the configuration stor
 390        /// are the same if their ETag fields match.  If the two settings are different versions, this method will throw
 391        /// that the setting in the configuration store was modified since it was last obtained by the client.</param>
 392        /// <param name="cancellationToken">A <see cref="CancellationToken"/> controlling the request lifetime.</param>
 393        /// <returns>A response indicating the success of the operation.</returns>
 394        public virtual Response DeleteConfigurationSetting(ConfigurationSetting setting, bool onlyIfUnchanged = false, C
 395        {
 18396            Argument.AssertNotNull(setting, nameof(setting));
 18397            MatchConditions requestOptions = onlyIfUnchanged ? new MatchConditions { IfMatch = setting.ETag } : default;
 18398            return DeleteConfigurationSetting(setting.Key, setting.Label, requestOptions, cancellationToken);
 399        }
 400
 401        private async Task<Response> DeleteConfigurationSettingAsync(string key, string label, MatchConditions requestOp
 402        {
 122403            using DiagnosticScope scope = _clientDiagnostics.CreateScope($"{nameof(ConfigurationClient)}.{nameof(DeleteC
 122404            scope.AddAttribute("key", key);
 122405            scope.Start();
 406
 407            try
 408            {
 122409                using Request request = CreateDeleteRequest(key, label, requestOptions);
 122410                Response response = await _pipeline.SendRequestAsync(request, cancellationToken).ConfigureAwait(false);
 411
 122412                return response.Status switch
 122413                {
 232414                    200 => response,
 124415                    204 => response,
 126416                    409 => throw _clientDiagnostics.CreateRequestFailedException(response, "The setting is read only"),
 122417
 122418                    // Throws on 412 if resource was modified.
 128419                    _ => throw _clientDiagnostics.CreateRequestFailedException(response)
 122420                };
 421            }
 10422            catch (Exception e)
 423            {
 10424                scope.Failed(e);
 10425                throw;
 426            }
 112427        }
 428
 429        private Response DeleteConfigurationSetting(string key, string label, MatchConditions requestOptions, Cancellati
 430        {
 122431            using DiagnosticScope scope = _clientDiagnostics.CreateScope($"{nameof(ConfigurationClient)}.{nameof(DeleteC
 122432            scope.AddAttribute("key", key);
 122433            scope.Start();
 434
 435            try
 436            {
 122437                using Request request = CreateDeleteRequest(key, label, requestOptions);
 122438                Response response = _pipeline.SendRequest(request, cancellationToken);
 439
 122440                return response.Status switch
 122441                {
 232442                    200 => response,
 124443                    204 => response,
 126444                    409 => throw _clientDiagnostics.CreateRequestFailedException(response, "The setting is read only."),
 122445
 122446                    // Throws on 412 if resource was modified.
 128447                    _ => throw _clientDiagnostics.CreateRequestFailedException(response)
 122448                };
 449            }
 10450            catch (Exception e)
 451            {
 10452                scope.Failed(e);
 10453                throw;
 454            }
 112455        }
 456
 457        private Request CreateDeleteRequest(string key, string label, MatchConditions requestOptions)
 458        {
 244459            Request request = _pipeline.CreateRequest();
 244460            request.Method = RequestMethod.Delete;
 244461            BuildUriForKvRoute(request.Uri, key, label);
 462
 244463            if (requestOptions != null)
 464            {
 16465                ConditionalRequestOptionsExtensions.ApplyHeaders(request, requestOptions);
 466            }
 467
 244468            return request;
 469        }
 470
 471        /// <summary>
 472        /// Retrieve an existing <see cref="ConfigurationSetting"/>, uniquely identified by key and label, from the conf
 473        /// </summary>
 474        /// <param name="key">The primary identifier of the configuration setting to retrieve.</param>
 475        /// <param name="label">A label used to group this configuration setting with others.</param>
 476        /// <param name="cancellationToken">A <see cref="CancellationToken"/> controlling the request lifetime.</param>
 477        /// <returns>A response containing the retrieved <see cref="ConfigurationSetting"/>.</returns>
 478        public virtual async Task<Response<ConfigurationSetting>> GetConfigurationSettingAsync(string key, string label 
 479        {
 26480            Argument.AssertNotNullOrEmpty(key, nameof(key));
 26481            return await GetConfigurationSettingAsync(key, label, acceptDateTime: default, requestOptions: default, canc
 18482        }
 483
 484        /// <summary>
 485        /// Retrieve an existing <see cref="ConfigurationSetting"/>, uniquely identified by key and label, from the conf
 486        /// </summary>
 487        /// <param name="key">The primary identifier of the configuration setting to retrieve.</param>
 488        /// <param name="label">A label used to group this configuration setting with others.</param>
 489        /// <param name="cancellationToken">A <see cref="CancellationToken"/> controlling the request lifetime.</param>
 490        /// <returns>A response containing the retrieved <see cref="ConfigurationSetting"/>.</returns>
 491        public virtual Response<ConfigurationSetting> GetConfigurationSetting(string key, string label = default, Cancel
 492        {
 26493            Argument.AssertNotNullOrEmpty(key, nameof(key));
 26494            return GetConfigurationSetting(key, label, acceptDateTime: default, requestOptions: default, cancellationTok
 495        }
 496
 497        /// <summary>
 498        /// Retrieve an existing <see cref="ConfigurationSetting"/> from the configuration store.
 499        /// </summary>
 500        /// <param name="setting">The <see cref="ConfigurationSetting"/> to retrieve.</param>
 501        /// <param name="onlyIfChanged">If set to true, only retrieve the setting from the configuration store if it has
 502        /// It is determined to have changed if the ETag field on the passed-in <see cref="ConfigurationSetting"/> is di
 503        /// configuration store.  If it has not changed, the returned response will have have no value, and will throw i
 504        /// check the status code on the response to avoid triggering the exception.</param>
 505        /// <param name="cancellationToken">A <see cref="CancellationToken"/> controlling the request lifetime.</param>
 506        /// <returns>A response containing the retrieved <see cref="ConfigurationSetting"/>.</returns>
 507        public virtual async Task<Response<ConfigurationSetting>> GetConfigurationSettingAsync(ConfigurationSetting sett
 508        {
 8509            Argument.AssertNotNull(setting, nameof(setting));
 8510            MatchConditions requestOptions = onlyIfChanged ? new MatchConditions { IfNoneMatch = setting.ETag } : defaul
 8511            return await GetConfigurationSettingAsync(setting.Key, setting.Label, acceptDateTime: default, requestOption
 8512        }
 513
 514        /// <summary>
 515        /// Retrieve an existing <see cref="ConfigurationSetting"/> from the configuration store.
 516        /// </summary>
 517        /// <param name="setting">The <see cref="ConfigurationSetting"/> to retrieve.</param>
 518        /// <param name="onlyIfChanged">If set to true, only retrieve the setting from the configuration store if it has
 519        /// It is determined to have changed if the ETag field on the passed-in <see cref="ConfigurationSetting"/> is di
 520        /// configuration store.  If it has not changed, the returned response will have have no value, and will throw i
 521        /// check the status code on the response to avoid triggering the exception.</param>
 522        /// <param name="cancellationToken">A <see cref="CancellationToken"/> controlling the request lifetime.</param>
 523        /// <returns>A response containing the retrieved <see cref="ConfigurationSetting"/>.</returns>
 524        public virtual Response<ConfigurationSetting> GetConfigurationSetting(ConfigurationSetting setting, bool onlyIfC
 525        {
 8526            Argument.AssertNotNull(setting, nameof(setting));
 8527            MatchConditions requestOptions = onlyIfChanged ? new MatchConditions { IfNoneMatch = setting.ETag } : defaul
 8528            return GetConfigurationSetting(setting.Key, setting.Label, acceptDateTime: default, requestOptions, cancella
 529        }
 530
 531        /// <summary>
 532        /// Retrieve an existing <see cref="ConfigurationSetting"/> from the configuration store.
 533        /// </summary>
 534        /// <param name="setting">The <see cref="ConfigurationSetting"/> to retrieve.</param>
 535        /// <param name="acceptDateTime">The setting will be retrieved exactly as it existed at the provided time.</para
 536        /// <param name="cancellationToken">A <see cref="CancellationToken"/> controlling the request lifetime.</param>
 537        /// <returns>A response containing the retrieved <see cref="ConfigurationSetting"/>.</returns>
 538        public virtual async Task<Response<ConfigurationSetting>> GetConfigurationSettingAsync(ConfigurationSetting sett
 539        {
 4540            Argument.AssertNotNull(setting, nameof(setting));
 4541            return await GetConfigurationSettingAsync(setting.Key, setting.Label, acceptDateTime, requestOptions: defaul
 4542        }
 543
 544        /// <summary>
 545        /// Retrieve an existing <see cref="ConfigurationSetting"/> from the configuration store.
 546        /// </summary>
 547        /// <param name="setting">The <see cref="ConfigurationSetting"/> to retrieve.</param>
 548        /// <param name="acceptDateTime">The setting will be retrieved exactly as it existed at the provided time.</para
 549        /// <param name="cancellationToken">A <see cref="CancellationToken"/> controlling the request lifetime.</param>
 550        /// <returns>A response containing the retrieved <see cref="ConfigurationSetting"/>.</returns>
 551        public virtual Response<ConfigurationSetting> GetConfigurationSetting(ConfigurationSetting setting, DateTimeOffs
 552        {
 4553            Argument.AssertNotNull(setting, nameof(setting));
 4554            return GetConfigurationSetting(setting.Key, setting.Label, acceptDateTime, requestOptions: default, cancella
 555        }
 556
 557        private async Task<Response<ConfigurationSetting>> GetConfigurationSettingAsync(string key, string label, DateTi
 558        {
 38559            using DiagnosticScope scope = _clientDiagnostics.CreateScope($"{nameof(ConfigurationClient)}.{nameof(GetConf
 38560            scope.AddAttribute(nameof(key), key);
 38561            scope.Start();
 562
 563            try
 564            {
 38565                using Request request = CreateGetRequest(key, label, acceptDateTime, requestOptions);
 38566                Response response = await _pipeline.SendRequestAsync(request, cancellationToken).ConfigureAwait(false);
 567
 38568                return response.Status switch
 38569                {
 64570                    200 => await CreateResponseAsync(response, cancellationToken).ConfigureAwait(false),
 42571                    304 => CreateResourceModifiedResponse(response),
 46572                    _ => throw await _clientDiagnostics.CreateRequestFailedExceptionAsync(response).ConfigureAwait(false
 38573                };
 574            }
 8575            catch (Exception e)
 576            {
 8577                scope.Failed(e);
 8578                throw;
 579            }
 30580        }
 581
 582        private Response<ConfigurationSetting> GetConfigurationSetting(string key, string label, DateTimeOffset acceptDa
 583        {
 38584            using DiagnosticScope scope = _clientDiagnostics.CreateScope($"{nameof(ConfigurationClient)}.{nameof(GetConf
 38585            scope.AddAttribute(nameof(key), key);
 38586            scope.Start();
 587
 588            try
 589            {
 38590                using Request request = CreateGetRequest(key, label, acceptDateTime, requestOptions);
 38591                Response response = _pipeline.SendRequest(request, cancellationToken);
 592
 38593                return response.Status switch
 38594                {
 64595                    200 => CreateResponse(response),
 42596                    304 => CreateResourceModifiedResponse(response),
 46597                    _ => throw _clientDiagnostics.CreateRequestFailedException(response),
 38598                };
 599            }
 8600            catch (Exception e)
 601            {
 8602                scope.Failed(e);
 8603                throw;
 604            }
 30605        }
 606
 607        /// <summary>
 608        /// Retrieves one or more <see cref="ConfigurationSetting"/> entities that match the options specified in the pa
 609        /// </summary>
 610        /// <param name="selector">Options used to select a set of <see cref="ConfigurationSetting"/> entities from the 
 611        /// <param name="cancellationToken">A <see cref="CancellationToken"/> controlling the request lifetime.</param>
 612        /// <returns>An enumerable collection containing the retrieved <see cref="ConfigurationSetting"/> entities.</ret
 613        public virtual AsyncPageable<ConfigurationSetting> GetConfigurationSettingsAsync(SettingSelector selector, Cance
 614        {
 30615            Argument.AssertNotNull(selector, nameof(selector));
 80616            return PageResponseEnumerator.CreateAsyncEnumerable(nextLink => GetConfigurationSettingsPageAsync(selector, 
 617        }
 618
 619        /// <summary>
 620        /// Retrieves one or more <see cref="ConfigurationSetting"/> entities that match the options specified in the pa
 621        /// </summary>
 622        /// <param name="selector">Set of options for selecting <see cref="ConfigurationSetting"/> from the configuratio
 623        /// <param name="cancellationToken">A <see cref="CancellationToken"/> controlling the request lifetime.</param>
 624        public virtual Pageable<ConfigurationSetting> GetConfigurationSettings(SettingSelector selector, CancellationTok
 625        {
 30626            Argument.AssertNotNull(selector, nameof(selector));
 80627            return PageResponseEnumerator.CreateEnumerable(nextLink => GetConfigurationSettingsPage(selector, nextLink, 
 628        }
 629
 630        /// <summary>
 631        /// Retrieves the revisions of one or more <see cref="ConfigurationSetting"/> entities that match the specified 
 632        /// </summary>
 633        /// <param name="keyFilter">Key filter that will be used to select a set of <see cref="ConfigurationSetting"/> e
 634        /// <param name="labelFilter">Label filter that will be used to select a set of <see cref="ConfigurationSetting"
 635        /// <param name="cancellationToken">A <see cref="CancellationToken"/> controlling the request lifetime.</param>
 636        public virtual AsyncPageable<ConfigurationSetting> GetRevisionsAsync(string keyFilter, string labelFilter = defa
 637        {
 2638            Argument.AssertNotNullOrEmpty(keyFilter, nameof(keyFilter));
 2639            return GetRevisionsAsync(new SettingSelector { KeyFilter = keyFilter, LabelFilter = labelFilter }, cancellat
 640        }
 641
 642        /// <summary>
 643        /// Retrieves the revisions of one or more <see cref="ConfigurationSetting"/> entities that match the specified 
 644        /// </summary>
 645        /// <param name="keyFilter">Key filter that will be used to select a set of <see cref="ConfigurationSetting"/> e
 646        /// <param name="labelFilter">Label filter that will be used to select a set of <see cref="ConfigurationSetting"
 647        /// <param name="cancellationToken">A <see cref="CancellationToken"/> controlling the request lifetime.</param>
 648        public virtual Pageable<ConfigurationSetting> GetRevisions(string keyFilter, string labelFilter = default, Cance
 649        {
 2650            Argument.AssertNotNullOrEmpty(keyFilter, nameof(keyFilter));
 2651            return GetRevisions(new SettingSelector { KeyFilter = keyFilter, LabelFilter = labelFilter }, cancellationTo
 652        }
 653
 654        /// <summary>
 655        /// Retrieves the revisions of one or more <see cref="ConfigurationSetting"/> entities that satisfy the options 
 656        /// </summary>
 657        /// <param name="selector">Set of options for selecting <see cref="ConfigurationSetting"/> from the configuratio
 658        /// <param name="cancellationToken">A <see cref="CancellationToken"/> controlling the request lifetime.</param>
 659        public virtual AsyncPageable<ConfigurationSetting> GetRevisionsAsync(SettingSelector selector, CancellationToken
 660        {
 4661            Argument.AssertNotNull(selector, nameof(selector));
 8662            return PageResponseEnumerator.CreateAsyncEnumerable(nextLink => GetRevisionsPageAsync(selector, nextLink, ca
 663        }
 664
 665        /// <summary>
 666        /// Retrieves the revisions of one or more <see cref="ConfigurationSetting"/> entities that satisfy the options 
 667        /// </summary>
 668        /// <param name="selector">Set of options for selecting <see cref="ConfigurationSetting"/> from the configuratio
 669        /// <param name="cancellationToken">A <see cref="CancellationToken"/> controlling the request lifetime.</param>
 670        public virtual Pageable<ConfigurationSetting> GetRevisions(SettingSelector selector, CancellationToken cancellat
 671        {
 4672            Argument.AssertNotNull(selector, nameof(selector));
 8673            return PageResponseEnumerator.CreateEnumerable(nextLink => GetRevisionsPage(selector, nextLink, cancellation
 674        }
 675
 676        private Request CreateGetRequest(string key, string label, DateTimeOffset acceptDateTime, MatchConditions reques
 677        {
 76678            Argument.AssertNotNullOrEmpty(key, nameof(key));
 679
 76680            Request request = _pipeline.CreateRequest();
 76681            request.Method = RequestMethod.Get;
 76682            BuildUriForKvRoute(request.Uri, key, label);
 76683            request.Headers.Add(s_mediaTypeKeyValueApplicationHeader);
 684
 76685            if (acceptDateTime != default)
 686            {
 8687                var dateTime = acceptDateTime.UtcDateTime.ToString(AcceptDateTimeFormat, CultureInfo.InvariantCulture);
 8688                request.Headers.SetValue(AcceptDatetimeHeader, dateTime);
 689            }
 690
 76691            if (requestOptions != null)
 692            {
 16693                ConditionalRequestOptionsExtensions.ApplyHeaders(request, requestOptions);
 694            }
 695
 76696            request.Headers.Add(HttpHeader.Common.JsonContentType);
 76697            return request;
 698        }
 699
 700        /// <summary>
 701        /// Fetches the <see cref="ConfigurationSetting"/> from the configuration store that match the options selected 
 702        /// </summary>
 703        /// <param name="selector">Set of options for selecting settings from the configuration store.</param>
 704        /// <param name="pageLink"></param>
 705        /// <param name="cancellationToken">A <see cref="CancellationToken"/> controlling the request lifetime.</param>
 706        private async Task<Page<ConfigurationSetting>> GetConfigurationSettingsPageAsync(SettingSelector selector, strin
 707        {
 50708            using DiagnosticScope scope = _clientDiagnostics.CreateScope($"{nameof(ConfigurationClient)}.{nameof(GetConf
 50709            scope.Start();
 710
 711            try
 712            {
 50713                using Request request = CreateBatchRequest(selector, pageLink);
 50714                Response response = await _pipeline.SendRequestAsync(request, cancellationToken).ConfigureAwait(false);
 715
 50716                switch (response.Status)
 717                {
 718                    case 200:
 719                    case 206:
 50720                        SettingBatch settingBatch = await ConfigurationServiceSerializer.ParseBatchAsync(response, cance
 50721                        return Page<ConfigurationSetting>.FromValues(settingBatch.Settings, settingBatch.NextBatchLink, 
 722                    default:
 0723                        throw await _clientDiagnostics.CreateRequestFailedExceptionAsync(response).ConfigureAwait(false)
 724                }
 725            }
 0726            catch (Exception e)
 727            {
 0728                scope.Failed(e);
 0729                throw;
 730            }
 50731        }
 732
 733        /// <summary>
 734        /// Fetches the <see cref="ConfigurationSetting"/> from the configuration store that match the options selected 
 735        /// </summary>
 736        /// <param name="selector">Set of options for selecting settings from the configuration store.</param>
 737        /// <param name="pageLink"></param>
 738        /// <param name="cancellationToken">A <see cref="CancellationToken"/> controlling the request lifetime.</param>
 739        private Page<ConfigurationSetting> GetConfigurationSettingsPage(SettingSelector selector, string pageLink, Cance
 740        {
 50741            using DiagnosticScope scope = _clientDiagnostics.CreateScope($"{nameof(ConfigurationClient)}.{nameof(GetConf
 50742            scope.Start();
 743
 744            try
 745            {
 50746                using Request request = CreateBatchRequest(selector, pageLink);
 50747                Response response = _pipeline.SendRequest(request, cancellationToken);
 748
 50749                switch (response.Status)
 750                {
 751                    case 200:
 752                    case 206:
 50753                        SettingBatch settingBatch = ConfigurationServiceSerializer.ParseBatch(response);
 50754                        return Page<ConfigurationSetting>.FromValues(settingBatch.Settings, settingBatch.NextBatchLink, 
 755                    default:
 0756                        throw _clientDiagnostics.CreateRequestFailedException(response);
 757                }
 758            }
 0759            catch (Exception e)
 760            {
 0761                scope.Failed(e);
 0762                throw;
 763            }
 50764        }
 765
 766        private Request CreateBatchRequest(SettingSelector selector, string pageLink)
 767        {
 100768            Request request = _pipeline.CreateRequest();
 100769            request.Method = RequestMethod.Get;
 100770            BuildUriForGetBatch(request.Uri, selector, pageLink);
 100771            request.Headers.Add(s_mediaTypeKeyValueApplicationHeader);
 100772            if (selector.AcceptDateTime.HasValue)
 773            {
 0774                var dateTime = selector.AcceptDateTime.Value.UtcDateTime.ToString(AcceptDateTimeFormat, CultureInfo.Inva
 0775                request.Headers.SetValue(AcceptDatetimeHeader, dateTime);
 776            }
 777
 100778            return request;
 779        }
 780
 781        /// <summary>
 782        /// Lists chronological/historical representation of <see cref="ConfigurationSetting"/> from the configuration s
 783        /// </summary>
 784        /// <remarks>Revisions are provided in descending order from their respective <see cref="ConfigurationSetting.La
 785        /// <param name="selector">Set of options for selecting settings from the configuration store.</param>
 786        /// <param name="pageLink"></param>
 787        /// <param name="cancellationToken">A <see cref="CancellationToken"/> controlling the request lifetime.</param>
 788        private async Task<Page<ConfigurationSetting>> GetRevisionsPageAsync(SettingSelector selector, string pageLink, 
 789        {
 4790            using DiagnosticScope scope = _clientDiagnostics.CreateScope($"{nameof(ConfigurationClient)}.{nameof(GetRevi
 4791            scope.Start();
 792
 793            try
 794            {
 4795                using Request request = CreateGetRevisionsRequest(selector, pageLink);
 4796                Response response = await _pipeline.SendRequestAsync(request, cancellationToken).ConfigureAwait(false);
 4797                switch (response.Status)
 798                {
 799                    case 200:
 800                    case 206:
 4801                        SettingBatch settingBatch = await ConfigurationServiceSerializer.ParseBatchAsync(response, cance
 4802                        return Page<ConfigurationSetting>.FromValues(settingBatch.Settings, settingBatch.NextBatchLink, 
 803                    default:
 0804                        throw await _clientDiagnostics.CreateRequestFailedExceptionAsync(response).ConfigureAwait(false)
 805                }
 806            }
 0807            catch (Exception e)
 808            {
 0809                scope.Failed(e);
 0810                throw;
 811            }
 4812        }
 813
 814        /// <summary>
 815        /// Lists chronological/historical representation of <see cref="ConfigurationSetting"/> from the configuration s
 816        /// </summary>
 817        /// <remarks>Revisions are provided in descending order from their respective <see cref="ConfigurationSetting.La
 818        /// <param name="selector">Set of options for selecting settings from the configuration store.</param>
 819        /// <param name="pageLink"></param>
 820        /// <param name="cancellationToken">A <see cref="CancellationToken"/> controlling the request lifetime.</param>
 821        private Page<ConfigurationSetting> GetRevisionsPage(SettingSelector selector, string pageLink, CancellationToken
 822        {
 4823            using DiagnosticScope scope = _clientDiagnostics.CreateScope($"{nameof(ConfigurationClient)}.{nameof(GetRevi
 4824            scope.Start();
 825
 826            try
 827            {
 4828                using Request request = CreateGetRevisionsRequest(selector, pageLink);
 4829                Response response = _pipeline.SendRequest(request, cancellationToken);
 4830                switch (response.Status)
 831                {
 832                    case 200:
 833                    case 206:
 4834                        SettingBatch settingBatch = ConfigurationServiceSerializer.ParseBatch(response);
 4835                        return Page<ConfigurationSetting>.FromValues(settingBatch.Settings, settingBatch.NextBatchLink, 
 836                    default:
 0837                        throw _clientDiagnostics.CreateRequestFailedException(response);
 838                }
 839            }
 0840            catch (Exception e)
 841            {
 0842                scope.Failed(e);
 0843                throw;
 844            }
 4845        }
 846
 847        private Request CreateGetRevisionsRequest(SettingSelector selector, string pageLink)
 848        {
 8849            Request request = _pipeline.CreateRequest();
 8850            request.Method = RequestMethod.Get;
 8851            BuildUriForRevisions(request.Uri, selector, pageLink);
 8852            request.Headers.Add(s_mediaTypeKeyValueApplicationHeader);
 8853            if (selector.AcceptDateTime.HasValue)
 854            {
 4855                var dateTime = selector.AcceptDateTime.Value.UtcDateTime.ToString(AcceptDateTimeFormat, CultureInfo.Inva
 4856                request.Headers.SetValue(AcceptDatetimeHeader, dateTime);
 857            }
 858
 8859            return request;
 860        }
 861
 862        /// <summary>
 863        /// Sets an existing <see cref="ConfigurationSetting"/> to read only or read write state in the configuration st
 864        /// </summary>
 865        /// <param name="key">The primary identifier of the configuration setting.</param>
 866        /// <param name="isReadOnly">If true, the <see cref="ConfigurationSetting"/> will be set to read only in the con
 867        /// <param name="cancellationToken">A <see cref="CancellationToken"/> controlling the request lifetime.</param>
 868        public virtual Task<Response<ConfigurationSetting>> SetReadOnlyAsync(string key, bool isReadOnly, CancellationTo
 12869            => SetReadOnlyAsync(key, label: default, isReadOnly, cancellationToken);
 870
 871        /// <summary>
 872        /// Sets an existing <see cref="ConfigurationSetting"/> to read only or read write state in the configuration st
 873        /// </summary>
 874        /// <param name="key">The primary identifier of the configuration setting.</param>
 875        /// <param name="isReadOnly">If true, the <see cref="ConfigurationSetting"/> will be set to read only in the con
 876        /// <param name="cancellationToken">A <see cref="CancellationToken"/> controlling the request lifetime.</param>
 877        public virtual Response<ConfigurationSetting> SetReadOnly(string key, bool isReadOnly, CancellationToken cancell
 12878            => SetReadOnly(key, label: default, isReadOnly, cancellationToken);
 879
 880        /// <summary>
 881        /// Sets an existing <see cref="ConfigurationSetting"/> to read only or read write state in the configuration st
 882        /// </summary>
 883        /// <param name="key">The primary identifier of the configuration setting.</param>
 884        /// <param name="label">A label used to group this configuration setting with others.</param>
 885        /// <param name="isReadOnly">If true, the <see cref="ConfigurationSetting"/> will be set to read only in the con
 886        /// <param name="cancellationToken">A <see cref="CancellationToken"/> controlling the request lifetime.</param>
 887        public virtual async Task<Response<ConfigurationSetting>> SetReadOnlyAsync(string key, string label, bool isRead
 888        {
 30889            Argument.AssertNotNullOrEmpty(key, nameof(key));
 890
 30891            using DiagnosticScope scope = _clientDiagnostics.CreateScope($"{nameof(ConfigurationClient)}.{nameof(SetRead
 30892            scope.AddAttribute("key", key);
 30893            scope.Start();
 894
 895            try
 896            {
 30897                using Request request = CreateSetReadOnlyRequest(key, label, isReadOnly);
 30898                Response response = await _pipeline.SendRequestAsync(request, cancellationToken).ConfigureAwait(false);
 899
 30900                switch (response.Status)
 901                {
 902                    case 200:
 22903                        return CreateResponse(response);
 904                    default:
 8905                        throw await _clientDiagnostics.CreateRequestFailedExceptionAsync(response).ConfigureAwait(false)
 906                }
 907            }
 8908            catch (Exception e)
 909            {
 8910                scope.Failed(e);
 8911                throw;
 912            }
 22913        }
 914
 915        /// <summary>
 916        /// Sets an existing <see cref="ConfigurationSetting"/> to read only or read write state in the configuration st
 917        /// </summary>
 918        /// <param name="key">The primary identifier of the configuration setting.</param>
 919        /// <param name="label">A label used to group this configuration setting with others.</param>
 920        /// <param name="isReadOnly">If true, the <see cref="ConfigurationSetting"/> will be set to read only in the con
 921        /// <param name="cancellationToken">A <see cref="CancellationToken"/> controlling the request lifetime.</param>
 922        public virtual Response<ConfigurationSetting> SetReadOnly(string key, string label, bool isReadOnly, Cancellatio
 923        {
 30924            Argument.AssertNotNullOrEmpty(key, nameof(key));
 925
 30926            using DiagnosticScope scope = _clientDiagnostics.CreateScope($"{nameof(ConfigurationClient)}.{nameof(SetRead
 30927            scope.AddAttribute("key", key);
 30928            scope.Start();
 929
 930            try
 931            {
 30932                using Request request = CreateSetReadOnlyRequest(key, label, isReadOnly);
 30933                Response response = _pipeline.SendRequest(request, cancellationToken);
 934
 30935                switch (response.Status)
 936                {
 937                    case 200:
 22938                        return CreateResponse(response);
 939                    default:
 8940                        throw _clientDiagnostics.CreateRequestFailedException(response);
 941                }
 942            }
 8943            catch (Exception e)
 944            {
 8945                scope.Failed(e);
 8946                throw;
 947            }
 22948        }
 949
 950        private Request CreateSetReadOnlyRequest(string key, string label, bool isReadOnly)
 951        {
 60952            Request request = _pipeline.CreateRequest();
 60953            request.Method = isReadOnly ? RequestMethod.Put : RequestMethod.Delete;
 60954            BuildUriForLocksRoute(request.Uri, key, label);
 955
 60956            return request;
 957        }
 958    }
 959}

C:\Git\azure-sdk-for-net\sdk\appconfiguration\Azure.Data.AppConfiguration\src\ConfigurationClient_private.cs

#LineLine coverage
 1// Copyright (c) Microsoft Corporation. All rights reserved.
 2// Licensed under the MIT License.
 3
 4using System;
 5using System.Collections.Generic;
 6using System.ComponentModel;
 7using System.Diagnostics;
 8using System.Linq;
 9using System.Threading;
 10using System.Threading.Tasks;
 11using Azure.Core;
 12
 13namespace Azure.Data.AppConfiguration
 14{
 15    public partial class ConfigurationClient
 16    {
 17        private const string AcceptDateTimeFormat = "R";
 18        private const string AcceptDatetimeHeader = "Accept-Datetime";
 19        private const string KvRoute = "/kv/";
 20        private const string RevisionsRoute = "/revisions/";
 21        private const string LocksRoute = "/locks/";
 22        private const string KeyQueryFilter = "key";
 23        private const string LabelQueryFilter = "label";
 24        private const string FieldsQueryFilter = "$select";
 25
 226        private static readonly char[] s_reservedCharacters = new char[] { ',', '\\' };
 27
 228        private static readonly HttpHeader s_mediaTypeKeyValueApplicationHeader = new HttpHeader(
 229            HttpHeader.Names.Accept,
 230            "application/vnd.microsoft.appconfig.kv+json"
 231        );
 32
 33        private static async Task<Response<ConfigurationSetting>> CreateResponseAsync(Response response, CancellationTok
 34        {
 15835            ConfigurationSetting result = await ConfigurationServiceSerializer.DeserializeSettingAsync(response.ContentS
 15836            return Response.FromValue(result, response);
 15837        }
 38
 39        private static Response<ConfigurationSetting> CreateResponse(Response response)
 40        {
 20241            return Response.FromValue(ConfigurationServiceSerializer.DeserializeSetting(response.ContentStream), respons
 42        }
 43
 44        private static Response<ConfigurationSetting> CreateResourceModifiedResponse(Response response)
 45        {
 846            return new NoBodyResponse<ConfigurationSetting>(response);
 47        }
 48
 49        private static void ParseConnectionString(string connectionString, out Uri uri, out string credential, out byte[
 50        {
 51            Debug.Assert(connectionString != null); // callers check this
 52
 32053            var parsed = ConnectionString.Parse(connectionString);
 54
 32055            uri = new Uri(parsed.GetRequired("Endpoint"));
 32056            credential = parsed.GetRequired("Id");
 57            try
 58            {
 32059                secret = Convert.FromBase64String(parsed.GetRequired("Secret"));
 32060            }
 061            catch (FormatException)
 62            {
 063                throw new InvalidOperationException("Specified Secret value isn't a valid base64 string");
 64            }
 32065        }
 66
 67        private void BuildUriForKvRoute(RequestUriBuilder builder, ConfigurationSetting keyValue)
 28868            => BuildUriForKvRoute(builder, keyValue.Key, keyValue.Label); // TODO (pri 2) : does this need to filter ETa
 69
 70        private void BuildUriForKvRoute(RequestUriBuilder builder, string key, string label)
 71        {
 60872            builder.Reset(_endpoint);
 60873            builder.AppendPath(KvRoute, escape: false);
 60874            builder.AppendPath(key);
 75
 60876            if (label != null)
 77            {
 46078                builder.AppendQuery(LabelQueryFilter, label);
 79            }
 60880        }
 81
 82        private void BuildUriForLocksRoute(RequestUriBuilder builder, string key, string label)
 83        {
 6084            builder.Reset(_endpoint);
 6085            builder.AppendPath(LocksRoute, escape: false);
 6086            builder.AppendPath(key);
 87
 6088            if (label != null)
 89            {
 3690                builder.AppendQuery(LabelQueryFilter, label);
 91            }
 6092        }
 93
 94        private static string EscapeReservedCharacters(string input)
 95        {
 096            string resp = string.Empty;
 097            for (int i = 0; i < input.Length; i++)
 98            {
 099                if (s_reservedCharacters.Contains(input[i]))
 100                {
 0101                    resp += $"\\{input[i]}";
 102                }
 103                else
 104                {
 0105                    resp += input[i];
 106                }
 107            }
 0108            return resp;
 109        }
 110
 111        internal static void BuildBatchQuery(RequestUriBuilder builder, SettingSelector selector, string pageLink)
 112        {
 122113            if (!string.IsNullOrEmpty(selector.KeyFilter))
 114            {
 66115                builder.AppendQuery(KeyQueryFilter, selector.KeyFilter);
 116            }
 117
 122118            if (!string.IsNullOrEmpty(selector.LabelFilter))
 119            {
 24120                builder.AppendQuery(LabelQueryFilter, selector.LabelFilter);
 121            }
 122
 122123            if (selector.Fields != SettingFields.All)
 124            {
 10125                var filter = selector.Fields.ToString().ToLowerInvariant().Replace("isreadonly", "locked");
 10126                builder.AppendQuery(FieldsQueryFilter, filter);
 127            }
 128
 122129            if (!string.IsNullOrEmpty(pageLink))
 130            {
 40131                builder.AppendQuery("after", pageLink, escapeValue: false);
 132            }
 122133        }
 134
 135        private void BuildUriForGetBatch(RequestUriBuilder builder, SettingSelector selector, string pageLink)
 136        {
 100137            builder.Reset(_endpoint);
 100138            builder.AppendPath(KvRoute, escape: false);
 100139            BuildBatchQuery(builder, selector, pageLink);
 100140        }
 141
 142        private void BuildUriForRevisions(RequestUriBuilder builder, SettingSelector selector, string pageLink)
 143        {
 8144            builder.Reset(_endpoint);
 8145            builder.AppendPath(RevisionsRoute, escape: false);
 8146            BuildBatchQuery(builder, selector, pageLink);
 8147        }
 148
 149        #region nobody wants to see these
 150        /// <summary>
 151        /// Check if two ConfigurationSetting instances are equal.
 152        /// </summary>
 153        /// <param name="obj">The instance to compare to.</param>
 154        [EditorBrowsable(EditorBrowsableState.Never)]
 0155        public override bool Equals(object obj) => base.Equals(obj);
 156
 157        /// <summary>
 158        /// Get a hash code for the ConfigurationSetting.
 159        /// </summary>
 160        [EditorBrowsable(EditorBrowsableState.Never)]
 0161        public override int GetHashCode() => base.GetHashCode();
 162
 163        /// <summary>
 164        /// Creates a Key Value string in reference to the ConfigurationSetting.
 165        /// </summary>
 166        [EditorBrowsable(EditorBrowsableState.Never)]
 0167        public override string ToString() => base.ToString();
 168        #endregion
 169    }
 170}

Methods/Properties

.ctor()
.ctor(...)
.ctor(...)
.ctor(...)
.ctor(...)
CreatePipeline(...)
GetDefaultScope(...)
AddConfigurationSettingAsync()
AddConfigurationSetting(...)
AddConfigurationSettingAsync()
AddConfigurationSetting(...)
CreateAddRequest(...)
SetConfigurationSettingAsync()
SetConfigurationSetting(...)
SetConfigurationSettingAsync()
SetConfigurationSetting(...)
CreateSetRequest(...)
DeleteConfigurationSettingAsync()
DeleteConfigurationSetting(...)
DeleteConfigurationSettingAsync()
DeleteConfigurationSetting(...)
DeleteConfigurationSettingAsync()
DeleteConfigurationSetting(...)
CreateDeleteRequest(...)
GetConfigurationSettingAsync()
GetConfigurationSetting(...)
GetConfigurationSettingAsync()
GetConfigurationSetting(...)
GetConfigurationSettingAsync()
GetConfigurationSetting(...)
GetConfigurationSettingAsync()
GetConfigurationSetting(...)
GetConfigurationSettingsAsync(...)
GetConfigurationSettings(...)
GetRevisionsAsync(...)
GetRevisions(...)
GetRevisionsAsync(...)
GetRevisions(...)
CreateGetRequest(...)
GetConfigurationSettingsPageAsync()
GetConfigurationSettingsPage(...)
CreateBatchRequest(...)
GetRevisionsPageAsync()
GetRevisionsPage(...)
CreateGetRevisionsRequest(...)
SetReadOnlyAsync(...)
SetReadOnly(...)
SetReadOnlyAsync()
SetReadOnly(...)
CreateSetReadOnlyRequest(...)
.cctor()
CreateResponseAsync()
CreateResponse(...)
CreateResourceModifiedResponse(...)
ParseConnectionString(...)
BuildUriForKvRoute(...)
BuildUriForKvRoute(...)
BuildUriForLocksRoute(...)
EscapeReservedCharacters(...)
BuildBatchQuery(...)
BuildUriForGetBatch(...)
BuildUriForRevisions(...)
Equals(...)
GetHashCode()
ToString()