< Summary - Core.Tests

Information
Class: Common.Core.Classes.DataServiceBase
Assembly: Common.Core
File(s): D:\a\NuGetPackages\NuGetPackages\src\Common\Core\Classes\DataServiceBase.cs
Tag: 3_8508158812
Line coverage
100%
Covered lines: 72
Uncovered lines: 0
Coverable lines: 72
Total lines: 147
Line coverage: 100%
Branch coverage
94%
Covered branches: 17
Total branches: 18
Branch coverage: 94.4%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Coverage history

Coverage history 0 25 50 75 100

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%11100%
DeleteResource(...)100%22100%
GetResource(...)100%11100%
PostResource(...)100%44100%
PutResource(...)100%44100%
CheckUri(...)75%44100%
CreateSharedClient(...)100%44100%
GetResponseAsync()100%11100%

File(s)

D:\a\NuGetPackages\NuGetPackages\src\Common\Core\Classes\DataServiceBase.cs

#LineLine coverage
 1using System.Net.Http.Headers;
 2using System.Text;
 3using System.Text.Json;
 4
 5namespace Common.Core.Classes;
 6
 7/// <summary>Base class for services consuming data from a RESTful API.</summary>
 8public class DataServiceBase
 9{
 10  private readonly HttpClient _httpClient;
 3211  private readonly string _mediaType = "application/json";
 12
 13  #region Constructor and Initialization
 14
 15  /// <summary>Initializes a new instance of the DataServiceBase class.</summary>
 16  /// <param name="baseUri">Base Uniform Resource Identifier.</param>
 17  /// <param name="timeoutSeconds">The number of seconds to wait before a request times out.</param>
 3218  public DataServiceBase( string baseUri, int timeoutSeconds = 100 )
 3219  {
 3220    _httpClient = CreateSharedClient( baseUri, timeoutSeconds );
 3221    _httpClient.DefaultRequestHeaders.Accept.Add( new MediaTypeWithQualityHeaderValue( _mediaType ) );
 3222  }
 23
 24  #endregion
 25
 26  /// <summary>Deletes a resource.</summary>
 27  /// <typeparam name="T">Generic class or interface.</typeparam>
 28  /// <param name="uri">Uniform Resource Identifier.</param>
 29  /// <param name="options">Json serializer options.</param>
 30  /// <returns>The deleted resource, or <see langword="null"/> if there were errors while processing the JSON.</returns>
 31  /// <exception cref="AggregateException">Represents one or more errors that occur during execution.</exception>
 32  public T? DeleteResource<T>( string uri, JsonSerializerOptions? options = null ) where T : class
 333  {
 334    CheckUri( ref uri );
 35    try
 336    {
 337      HttpRequestMessage rq = new( HttpMethod.Delete, uri );
 338      string json = GetResponseAsync( rq ).Result;
 239      return !string.IsNullOrEmpty( json ) ?
 240        JsonHelper.DeserializeJson<T>( ref json, options ) : null;
 41    }
 342    catch( AggregateException ) { throw; }
 243  }
 44
 45  /// <summary>Gets a resource.</summary>
 46  /// <param name="uri">Uniform Resource Identifier.</param>
 47  /// <returns>Resource as a JSON string if there were no errors while processing the request.</returns>
 48  /// <exception cref="AggregateException">Represents one or more errors that occur during execution.</exception>
 49  public string? GetResource( string uri )
 1850  {
 1851    CheckUri( ref uri );
 52    try
 1853    {
 1854      HttpRequestMessage rq = new( HttpMethod.Get, uri );
 1855      return GetResponseAsync( rq ).Result;
 56    }
 357    catch( AggregateException ) { throw; }
 1758  }
 59
 60  /// <summary>Creates a resource.</summary>
 61  /// <typeparam name="T">Generic class or interface.</typeparam>
 62  /// <param name="uri">Uniform Resource Identifier.</param>
 63  /// <param name="obj">Resource to create.</param>
 64  /// <param name="options">Json serializer options.</param>
 65  /// <returns>The created resource, or <see langword="null"/> if there were errors while processing the JSON.</returns>
 66  /// <exception cref="AggregateException">Represents one or more errors that occur during execution.</exception>
 67  public T? PostResource<T>( string uri, T? obj, JsonSerializerOptions? options = null ) where T : class
 468  {
 469    string? json = JsonHelper.Serialize( obj );
 670    if( json is null ) { return null; }
 71
 372    CheckUri( ref uri );
 73    try
 374    {
 375      HttpRequestMessage rq = new( HttpMethod.Post, uri )
 376      {
 377        Content = new StringContent( json, Encoding.UTF8, _mediaType )
 378      };
 379      json = GetResponseAsync( rq ).Result;
 280      return !string.IsNullOrEmpty( json ) ?
 281        JsonHelper.DeserializeJson<T>( ref json, options ) : null;
 82    }
 383    catch( AggregateException ) { throw; }
 384  }
 85
 86  /// <summary>Updates a resource.</summary>
 87  /// <typeparam name="T">Generic class or interface.</typeparam>
 88  /// <param name="uri">Uniform Resource Identifier.</param>
 89  /// <param name="obj">Resource to update.</param>
 90  /// <param name="options">Json serializer options.</param>
 91  /// <returns>The updated resource, or <see langword="null"/> if there were errors while processing the JSON.</returns>
 92  /// <exception cref="AggregateException">Represents one or more errors that occur during execution.</exception>
 93  public T? PutResource<T>( string uri, T? obj, JsonSerializerOptions? options = null ) where T : class
 494  {
 495    string? json = JsonHelper.Serialize( obj, options );
 696    if( json is null ) { return null; }
 97
 398    CheckUri( ref uri );
 99    try
 3100    {
 3101      HttpRequestMessage rq = new( HttpMethod.Put, uri )
 3102      {
 3103        Content = new StringContent( json, Encoding.UTF8, _mediaType )
 3104      };
 3105      json = GetResponseAsync( rq ).Result;
 2106      return !string.IsNullOrEmpty( json ) ?
 2107        JsonHelper.DeserializeJson<T>( ref json, options ) : null;
 108    }
 3109    catch( AggregateException ) { throw; }
 3110  }
 111
 112  #region Private Methods
 113
 114  private void CheckUri( ref string uri )
 27115  {
 27116    if( !uri.StartsWith( Uri.UriSchemeHttp, StringComparison.InvariantCultureIgnoreCase ) )
 26117    {
 26118      uri = _httpClient.BaseAddress?.OriginalString + uri;
 26119    }
 27120  }
 121
 122  private static HttpClient CreateSharedClient( string siteUri, int timeout )
 32123  {
 32124    SocketsHttpHandler handler = new()
 32125    {
 32126      PooledConnectionLifetime = TimeSpan.FromMinutes( 15 ) // Recreate every 15 minutes
 32127    };
 128
 80129    if( siteUri.Contains( '\\' ) ) { siteUri = siteUri.Replace( '\\', '/' ); }
 128130    if( !siteUri.EndsWith( '/' ) ) { siteUri += "/"; }
 32131    TimeSpan timespan = TimeSpan.FromSeconds( timeout );
 132
 32133    return new HttpClient( handler ) { BaseAddress = new Uri( siteUri ), Timeout = timespan };
 32134  }
 135
 136  // https://devblogs.microsoft.com/dotnet/configureawait-faq/
 137  private async Task<string> GetResponseAsync( HttpRequestMessage request )
 27138  {
 27139    HttpResponseMessage response = await _httpClient.SendAsync( request ).ConfigureAwait( false );
 27140    _ = response.EnsureSuccessStatusCode();
 141
 23142    using StreamReader reader = new( response.Content.ReadAsStream() );
 23143    return await reader.ReadToEndAsync().ConfigureAwait( false );
 23144  }
 145
 146  #endregion
 147}