From 6e1bc878745fdb43951dc63d7aa549dc50f42acd Mon Sep 17 00:00:00 2001 From: Dan Inden Date: Mon, 7 Oct 2024 13:41:58 +0200 Subject: [PATCH] Allow extension of models (remove sealed): - ContentItemCreateModel - AssetWithRenditionsReference Allow settable Id (for unittests): - ElementMetadataBase Return null for content not found instead of an exception: - ActionInvoker - ManagementHttpClient Allow injection of HttpClient - ManagementClient - HttpClient --- Kontent.Ai.Management.Tests/CodeSamples/Readme.cs | 3 ++- Kontent.Ai.Management/ManagementClient.cs | 15 ++++++++------- .../Models/Items/ContentItemCreateModel.cs | 4 ++-- .../Models/Shared/AssetWithRenditionsReference.cs | 8 ++++---- .../Models/Types/Elements/ElementMetadataBase.cs | 6 +++--- .../Modules/ActionInvoker/ActionInvoker.cs | 14 +++++++++----- .../Modules/HttpClient/HttpClient.cs | 9 +++++++++ .../Modules/HttpClient/ManagementHttpClient.cs | 5 +++++ 8 files changed, 42 insertions(+), 22 deletions(-) diff --git a/Kontent.Ai.Management.Tests/CodeSamples/Readme.cs b/Kontent.Ai.Management.Tests/CodeSamples/Readme.cs index fb4aeedc..a9e9cc7b 100644 --- a/Kontent.Ai.Management.Tests/CodeSamples/Readme.cs +++ b/Kontent.Ai.Management.Tests/CodeSamples/Readme.cs @@ -12,6 +12,7 @@ using System; using System.IO; using System.Linq; +using System.Net.Http; using System.Text; using Xunit; @@ -73,7 +74,7 @@ public void CreateManagementClient() { EnvironmentId = "cbbe2d5c-17c6-0128-be26-e997ba7c1619", ApiKey = "ew0...1eo" - }); + }, new HttpClient()); } [Fact] diff --git a/Kontent.Ai.Management/ManagementClient.cs b/Kontent.Ai.Management/ManagementClient.cs index a7b1e479..9b56b3d0 100644 --- a/Kontent.Ai.Management/ManagementClient.cs +++ b/Kontent.Ai.Management/ManagementClient.cs @@ -1,14 +1,14 @@ -using Kontent.Ai.Management.Configuration; +using System; +using System.Collections.Generic; +using System.Net.Http; +using System.Threading.Tasks; +using Kontent.Ai.Management.Configuration; using Kontent.Ai.Management.Models.Shared; using Kontent.Ai.Management.Modules.ActionInvoker; using Kontent.Ai.Management.Modules.HttpClient; using Kontent.Ai.Management.Modules.ModelBuilders; using Kontent.Ai.Management.Modules.ResiliencePolicy; using Kontent.Ai.Management.Modules.UrlBuilder; -using System; -using System.Collections.Generic; -using System.Net.Http; -using System.Threading.Tasks; namespace Kontent.Ai.Management; @@ -27,7 +27,8 @@ public sealed partial class ManagementClient : IManagementClient /// Initializes a new instance of the class for managing content of the specified environment. /// /// The settings of the Kontent.ai environment. - public ManagementClient(ManagementOptions ManagementOptions) + /// + public ManagementClient(ManagementOptions ManagementOptions, System.Net.Http.HttpClient httpClient) { ArgumentNullException.ThrowIfNull(ManagementOptions); @@ -49,7 +50,7 @@ public ManagementClient(ManagementOptions ManagementOptions) _urlBuilder = new EndpointUrlBuilder(ManagementOptions); _actionInvoker = new ActionInvoker( - new ManagementHttpClient(new DefaultResiliencePolicyProvider(ManagementOptions.MaxRetryAttempts), ManagementOptions.EnableResilienceLogic), + new ManagementHttpClient(new Modules.HttpClient.HttpClient(httpClient), new DefaultResiliencePolicyProvider(ManagementOptions.MaxRetryAttempts), ManagementOptions.EnableResilienceLogic), new MessageCreator(ManagementOptions.ApiKey)); _modelProvider = ManagementOptions.ModelProvider ?? new ModelProvider(); } diff --git a/Kontent.Ai.Management/Models/Items/ContentItemCreateModel.cs b/Kontent.Ai.Management/Models/Items/ContentItemCreateModel.cs index cc875f4a..db18342d 100644 --- a/Kontent.Ai.Management/Models/Items/ContentItemCreateModel.cs +++ b/Kontent.Ai.Management/Models/Items/ContentItemCreateModel.cs @@ -1,4 +1,4 @@ -using Kontent.Ai.Management.Models.Shared; +using Kontent.Ai.Management.Models.Shared; using Newtonsoft.Json; namespace Kontent.Ai.Management.Models.Items; @@ -6,7 +6,7 @@ namespace Kontent.Ai.Management.Models.Items; /// /// Represents the content item create model. /// -public sealed class ContentItemCreateModel +public class ContentItemCreateModel { /// /// Gets or sets the name of the content item. diff --git a/Kontent.Ai.Management/Models/Shared/AssetWithRenditionsReference.cs b/Kontent.Ai.Management/Models/Shared/AssetWithRenditionsReference.cs index b96702f1..d7760bdc 100644 --- a/Kontent.Ai.Management/Models/Shared/AssetWithRenditionsReference.cs +++ b/Kontent.Ai.Management/Models/Shared/AssetWithRenditionsReference.cs @@ -1,8 +1,8 @@ -using Kontent.Ai.Management.Modules.ActionInvoker; -using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Linq; +using Kontent.Ai.Management.Modules.ActionInvoker; +using Newtonsoft.Json; namespace Kontent.Ai.Management.Models.Shared; @@ -10,7 +10,7 @@ namespace Kontent.Ai.Management.Models.Shared; /// Represents identifier of asset with renditions. /// [JsonConverter(typeof(AssetWithRenditionsReferenceConverter))] -public sealed class AssetWithRenditionsReference +public class AssetWithRenditionsReference { private readonly IList _renditions; @@ -60,4 +60,4 @@ public AssetWithRenditionsReference(Reference assetReference, IEnumerable(); } -} \ No newline at end of file +} diff --git a/Kontent.Ai.Management/Models/Types/Elements/ElementMetadataBase.cs b/Kontent.Ai.Management/Models/Types/Elements/ElementMetadataBase.cs index b89aa88f..80a1ec59 100644 --- a/Kontent.Ai.Management/Models/Types/Elements/ElementMetadataBase.cs +++ b/Kontent.Ai.Management/Models/Types/Elements/ElementMetadataBase.cs @@ -1,7 +1,7 @@ -using Kontent.Ai.Management.Models.Shared; +using System; +using Kontent.Ai.Management.Models.Shared; using Kontent.Ai.Management.Modules.ActionInvoker; using Newtonsoft.Json; -using System; namespace Kontent.Ai.Management.Models.Types.Elements; @@ -27,7 +27,7 @@ public abstract class ElementMetadataBase /// Gets or sets the element's internal ID. /// [JsonProperty("id")] - public Guid Id { get; private set; } + public Guid Id { get; set; } /// /// Gets or sets the element's codename. diff --git a/Kontent.Ai.Management/Modules/ActionInvoker/ActionInvoker.cs b/Kontent.Ai.Management/Modules/ActionInvoker/ActionInvoker.cs index 787b49bc..3e60122d 100644 --- a/Kontent.Ai.Management/Modules/ActionInvoker/ActionInvoker.cs +++ b/Kontent.Ai.Management/Modules/ActionInvoker/ActionInvoker.cs @@ -1,6 +1,3 @@ -using Kontent.Ai.Management.Modules.HttpClient; -using Newtonsoft.Json; -using Newtonsoft.Json.Converters; using System; using System.Collections.Generic; using System.IO; @@ -8,6 +5,9 @@ using System.Net.Http.Headers; using System.Text; using System.Threading.Tasks; +using Kontent.Ai.Management.Modules.HttpClient; +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; namespace Kontent.Ai.Management.Modules.ActionInvoker; @@ -19,12 +19,12 @@ internal class ActionInvoker : IActionInvoker private readonly JsonSerializerSettings _serializeSettings = new() { NullValueHandling = NullValueHandling.Ignore, - Converters = new List { new DecimalObjectConverter(), new StringEnumConverter() } + Converters = [new DecimalObjectConverter(), new StringEnumConverter()] }; private readonly JsonSerializerSettings _deserializeSettings = new() { - Converters = new List { new DynamicObjectJsonConverter() } + Converters = [new DynamicObjectJsonConverter()] }; @@ -60,6 +60,10 @@ public async Task InvokeMethodAsync(string endpo public async Task InvokeReadOnlyMethodAsync(string endpointUrl, HttpMethod method, Dictionary headers = null) { var response = await _cmHttpClient.SendAsync(_messageCreator, endpointUrl, method, null, headers); + if (response == null) + { + return default; + } return await ReadResultAsync(response); } diff --git a/Kontent.Ai.Management/Modules/HttpClient/HttpClient.cs b/Kontent.Ai.Management/Modules/HttpClient/HttpClient.cs index 27ffb5df..e199006b 100644 --- a/Kontent.Ai.Management/Modules/HttpClient/HttpClient.cs +++ b/Kontent.Ai.Management/Modules/HttpClient/HttpClient.cs @@ -5,6 +5,15 @@ namespace Kontent.Ai.Management.Modules.HttpClient; internal class HttpClient : IHttpClient { + public HttpClient() + { + + } + public HttpClient(System.Net.Http.HttpClient httpClient) + { + _baseClient = httpClient; + } + private readonly System.Net.Http.HttpClient _baseClient = new(); public async Task SendAsync(HttpRequestMessage request) => await _baseClient.SendAsync(request); diff --git a/Kontent.Ai.Management/Modules/HttpClient/ManagementHttpClient.cs b/Kontent.Ai.Management/Modules/HttpClient/ManagementHttpClient.cs index 0b811014..2cdec3e1 100644 --- a/Kontent.Ai.Management/Modules/HttpClient/ManagementHttpClient.cs +++ b/Kontent.Ai.Management/Modules/HttpClient/ManagementHttpClient.cs @@ -73,6 +73,11 @@ public async Task SendAsync( return response; } + if (response.StatusCode == System.Net.HttpStatusCode.NotFound) + { + return null; + } + var responseContent = response.Content; throw responseContent != null ?