31 Commits

Author SHA1 Message Date
Developer 02
65c64a3f9a chore(API): Aktualisiert auf 2.0.1 2024-12-02 11:35:33 +01:00
Developer 02
1d600aa453 refactor: Nullbarkeitsannotation zu ControllerExtensions-Methoden hinzugefügt 2024-12-02 11:33:52 +01:00
Developer 02
816d5835f1 fix(BaseHttpClientService): Die Kodierung der Abfrageparameter wurde entfernt, da UriBuilder dies bereits tut.
- Hochgestuft auf 2.0.3
2024-11-26 23:45:06 +01:00
Developer 02
4a64a31d47 refactor(Abstraction): Hochgestuft auf 2.2.1. 2024-11-25 14:30:20 +01:00
Developer 02
e9b2ba788f refactor(IHttpClientOptions): Konvertiert Typ der Header von Key Value Pair Liste zu Dictionary. 2024-11-25 14:29:21 +01:00
Developer 02
e53813500a chore(Core.Client): aufgerüstet auf 2.0.1 2024-11-25 14:05:17 +01:00
Developer 02
25e3855de2 refactor(DIExtensions): BaseHttpClientService-Injektion entfernen 2024-11-25 14:02:54 +01:00
Developer 02
dd3d6e70cc chore(Client): hochgestuft auf 2.2.0 2024-11-25 11:49:41 +01:00
Developer 02
02a87309df chore(Abstraktionen): hochgestuft auf 2.2.0 2024-11-25 11:47:45 +01:00
Developer 02
0f7bdc9d0e refactor: Vereinfachung der Logik zur Zusammenführung von Headern und Abfrageparametern in BaseHttpClientService
- Verbesserung der Zusammenführung von Standard-Headern und Abfrageparametern durch Null-Prüfung und übersichtlichere Handhabung.
- Sicherstellung, dass die Logik einfacher zu verstehen und zu warten ist.
2024-11-25 11:46:08 +01:00
Developer 02
f9df2fb29e feat: DI-Erweiterung für HttpClient-Services verbessert
- `AddHttpClientService` refaktoriert, um `AddHttpClientServiceDefaults` für gemeinsame Setup-Logik einzuführen.
- Überladungen für `AddHttpClientService` hinzugefügt, um sowohl `IConfigurationSection` als auch direkte Options-Instanz zu unterstützen.
- Bessere Erweiterbarkeit und sauberere Service-Konfiguration sichergestellt.
2024-11-25 11:35:46 +01:00
Developer 02
ef7da0e52c refactor(HttpClientOptions): entfernt und durch IHttpClientOptions mit Klasseneinschränkung ersetzt 2024-11-25 11:19:41 +01:00
Developer 02
f602a842be revert: IHttpClientOptions entfernen 2024-11-25 11:03:15 +01:00
Developer 02
52a7664e57 fix(Client.DIExtensions): Generischer Typ zur Injektion mehrerer Client-Dienste hinzugefügt 2024-11-25 10:58:45 +01:00
Developer 02
ea3d1312b8 refactor(BaseHttpClientService): aktualisiert, um den Pfad zu initialisieren emty string, wenn es null ist und HttpClientOptions ohne IOptions hinzugefügt 2024-11-25 10:54:34 +01:00
Developer 02
3b8b315fea refactor(IHttpClientOptions): removed 2024-11-25 10:42:22 +01:00
Developer 02
c65eefb954 feat(IHttpClientOptions): Abfrage-Parameter und Header hinzugefügt.
- Geordnete DI-Erweiterungen.
2024-11-25 10:30:33 +01:00
Developer 02
997fd533ac feat(BaseHttpClientService): Path getter und intter entfernt und geschützte readonly _path Variable hinzugefügt. 2024-11-25 10:11:13 +01:00
Developer 02
bcfb5a8a70 feat(BaseHttpClientService): Uri Getter und Setter entfernt und geschützte readonly _uri Variable hinzugefügt. 2024-11-25 10:09:05 +01:00
Developer 02
049e9977f4 feat(BaseHttpClientService): Optionale Standard-Header und QueryParams hinzugefügt 2024-11-25 10:05:42 +01:00
Developer 02
0334fc4cdf refactor(BaseHttpClientService): Verwendung von IEnumerable<KeyValuePair<string, object>> anstelle von Dictionary<string, string> in queryParams, form und headers inputs der FetchAsync Methode 2024-11-25 09:28:47 +01:00
Developer 02
0c2334cefb refactor(BaseHttpClientService): Der Wert von query params wurde zum nullbaren Objekt, um Flag-Parameter hinzuzufügen.
- Aktualisierte Schnittstelle und Logik unter Berücksichtigung dieser Situation
2024-11-22 14:35:22 +01:00
Developer 02
dd7f1c1ea0 fix(BaseHttpClientService): Null-Kontrolle zum Pfad hinzugefügt 2024-11-22 13:19:42 +01:00
Developer 02
4bb242a4cc feat(Tests.Client.BaseHttpClientServiceTests): Test für Abfrageparameter hinzugefügt 2024-11-22 12:48:36 +01:00
Developer 02
b577067379 chore: gitignore aktualisieren 2024-11-22 12:47:24 +01:00
Developer 02
bd4d4856ea feat(IHttpClientOptions):
Basispfad zu http-Client-Optionen hinzugefügt
2024-11-22 12:05:13 +01:00
Developer 02
c3a12ba5b7 chore: hochgestuft auf 1.1.0 2024-11-22 10:30:26 +01:00
Developer 02
478bf13a4a Revert "chore(Client): hochgestuft auf 2,1"
This reverts commit d8849f48da.
2024-11-22 10:29:03 +01:00
Developer 02
d8849f48da chore(Client): hochgestuft auf 2,1 2024-11-22 10:26:49 +01:00
Developer 02
c466c553dc chore: hochgestuft auf 2.1 2024-11-22 10:25:32 +01:00
Developer 02
48afa6b433 feat(BaseHttpClientService.FetchAsync): Schema-, Port-, Pfad- und Query-Parameter-Optionen hinzugefügt 2024-11-22 10:12:40 +01:00
14 changed files with 166 additions and 58 deletions

1
.gitignore vendored
View File

@@ -409,3 +409,4 @@ FodyWeavers.xsd
/DigitalData.Core.ConsoleApp/Program.cs /DigitalData.Core.ConsoleApp/Program.cs
/DigitalData.Core.ConsoleApp/FooHttpOptions.cs /DigitalData.Core.ConsoleApp/FooHttpOptions.cs
/DigitalData.Core.Tests/obj/ /DigitalData.Core.Tests/obj/
/DigitalData.Core.Terminal

View File

@@ -19,7 +19,7 @@ namespace DigitalData.Core.API
/// <param name="index">The key in the ViewData dictionary where the value will be stored.</param> /// <param name="index">The key in the ViewData dictionary where the value will be stored.</param>
/// <param name="value">The value to be stored in the ViewData dictionary.</param> /// <param name="value">The value to be stored in the ViewData dictionary.</param>
/// <returns>The same ViewResult object with updated ViewData, allowing for additional chained operations.</returns> /// <returns>The same ViewResult object with updated ViewData, allowing for additional chained operations.</returns>
public static ViewResult WithData(this ViewResult viewResult, string index, object value) public static ViewResult WithData(this ViewResult viewResult, string index, object? value)
{ {
viewResult.ViewData[index] = value; viewResult.ViewData[index] = value;
return viewResult; return viewResult;

View File

@@ -8,7 +8,7 @@
<OutputType>Library</OutputType> <OutputType>Library</OutputType>
<Description>This package provides a comprehensive set of API controllers and related utilities for the DigitalData.Core library. It includes generic CRUD controllers, localization extensions, middleware for security policies, and application model conventions.</Description> <Description>This package provides a comprehensive set of API controllers and related utilities for the DigitalData.Core library. It includes generic CRUD controllers, localization extensions, middleware for security policies, and application model conventions.</Description>
<PackageId>DigitalData.Core.API</PackageId> <PackageId>DigitalData.Core.API</PackageId>
<Version>2.0.0.0</Version> <Version>2.0.1</Version>
<Authors>Digital Data GmbH</Authors> <Authors>Digital Data GmbH</Authors>
<Company>Digital Data GmbH</Company> <Company>Digital Data GmbH</Company>
<Product>DigitalData.Core.API</Product> <Product>DigitalData.Core.API</Product>
@@ -16,6 +16,8 @@
<RepositoryUrl>http://git.dd:3000/AppStd/WebCoreModules.git</RepositoryUrl> <RepositoryUrl>http://git.dd:3000/AppStd/WebCoreModules.git</RepositoryUrl>
<PackageTags>digital data core api</PackageTags> <PackageTags>digital data core api</PackageTags>
<PackageIcon>core_icon.png</PackageIcon> <PackageIcon>core_icon.png</PackageIcon>
<AssemblyVersion>2.0.1</AssemblyVersion>
<FileVersion>2.0.1</FileVersion>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@@ -4,16 +4,17 @@ namespace DigitalData.Core.Abstractions.Client
{ {
public interface IBaseHttpClientService public interface IBaseHttpClientService
{ {
public string Uri { get; init; } CookieCollection GetCookies(string path = "");
public CookieCollection GetCookies(string route = "");
Task<HttpResponseMessage> FetchAsync( Task<HttpResponseMessage> FetchAsync(
string route = "", string? scheme = null,
int? port = null,
string path = "",
IEnumerable<KeyValuePair<string, object?>>? queryParams = null,
HttpMethod? method = null, HttpMethod? method = null,
HttpContent? body = null, HttpContent? body = null,
Dictionary<string, string>? form = null, IEnumerable<KeyValuePair<string, object>>? form = null,
Dictionary<string, string>? headers = null, IEnumerable<KeyValuePair<string, object>>? headers = null,
bool sendWithCookie = true, bool sendWithCookie = true,
bool saveCookie = true bool saveCookie = true
); );

View File

@@ -2,6 +2,12 @@
{ {
public interface IHttpClientOptions public interface IHttpClientOptions
{ {
public string Uri { get; init; } string Uri { get; init; }
string? Path { get; init; }
Dictionary<string, object>? Headers { get; init; }
Dictionary<string, object?>? QueryParams { get; init; }
} }
} }

View File

@@ -16,9 +16,10 @@
<PackageProjectUrl></PackageProjectUrl> <PackageProjectUrl></PackageProjectUrl>
<RepositoryUrl>http://git.dd:3000/AppStd/WebCoreModules.git</RepositoryUrl> <RepositoryUrl>http://git.dd:3000/AppStd/WebCoreModules.git</RepositoryUrl>
<PackAsTool>False</PackAsTool> <PackAsTool>False</PackAsTool>
<NeutralLanguage>aa-DJ</NeutralLanguage>
<PackageIcon>core_icon.png</PackageIcon> <PackageIcon>core_icon.png</PackageIcon>
<Version>2.0.0.0</Version> <Version>2.2.1</Version>
<AssemblyVersion>2.2.1</AssemblyVersion>
<FileVersion>2.2.1</FileVersion>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@@ -1,7 +1,7 @@
using DigitalData.Core.Abstractions.Client; using DigitalData.Core.Abstractions.Client;
using Microsoft.Extensions.Options;
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using System.Net; using System.Net;
using System.Web;
namespace DigitalData.Core.Client namespace DigitalData.Core.Client
{ {
@@ -11,38 +11,103 @@ namespace DigitalData.Core.Client
protected readonly CookieContainer _cookies; protected readonly CookieContainer _cookies;
[StringSyntax("Uri")] [StringSyntax("Uri")]
public string Uri { get; init; } protected readonly string _uri;
public BaseHttpClientService(HttpClient client, CookieContainer cookieContainer, IOptions<HttpClientOptions> clientOptions) protected readonly string _path;
protected IEnumerable<KeyValuePair<string, object>>? _headers;
protected IEnumerable<KeyValuePair<string, object?>>? _queryParams;
internal BaseHttpClientService(HttpClient client, CookieContainer cookieContainer, IHttpClientOptions clientOptions)
{ {
_client = client; _client = client;
_cookies = cookieContainer; _cookies = cookieContainer;
Uri = clientOptions.Value.Uri; _uri = clientOptions.Uri.Trim(URI_TRIM_CHARS);
_path = clientOptions.Path?.Trim(URI_TRIM_CHARS) ?? string.Empty;
_headers = clientOptions.Headers;
_queryParams = clientOptions.QueryParams;
} }
public CookieCollection GetCookies(string route = "") => _cookies.GetCookies(uri: new Uri(Uri + route)); public CookieCollection GetCookies(string path = "") => _cookies.GetCookies(uri: new Uri(UriCombine(_uri, path, path.Trim(URI_TRIM_CHARS))));
public async Task<HttpResponseMessage> FetchAsync( public async Task<HttpResponseMessage> FetchAsync(
string route = "", string? scheme = null,
int? port = null,
string path = "",
IEnumerable<KeyValuePair<string, object?>>? queryParams = null,
HttpMethod? method = null, HttpMethod? method = null,
HttpContent? body = null, HttpContent? body = null,
Dictionary<string, string>? form = null, IEnumerable<KeyValuePair<string, object>>? form = null,
Dictionary<string, string>? headers = null, IEnumerable<KeyValuePair<string, object>>? headers = null,
bool sendWithCookie = true, bool sendWithCookie = true,
bool saveCookie = true bool saveCookie = true
) )
{ {
// merge with default headers
if(_headers is not null)
{
if (headers is null)
headers = _headers;
else
{
var mergedHeaders = headers.ToList();
mergedHeaders.AddRange(_headers);
headers = mergedHeaders;
}
}
// Add default query parameters
if(_queryParams is not null)
{
if (queryParams is null)
queryParams = _queryParams;
else
{
var mergedQueryParams = queryParams.ToList();
mergedQueryParams.AddRange(_queryParams);
queryParams = mergedQueryParams;
}
}
// set default HTTP method as GET // set default HTTP method as GET
method ??= HttpMethod.Get; method ??= HttpMethod.Get;
// create URL // create URL
var requestUriStr = Uri + route; var uriBuilder = new UriBuilder(_uri);
var requestUri = new Uri(requestUriStr); if (scheme is not null)
uriBuilder.Scheme = scheme;
if (port is int portInt)
uriBuilder.Port = portInt;
uriBuilder.Path = UriCombine(_path, path?.Trim(URI_TRIM_CHARS) ?? string.Empty);
var requestMessage = new HttpRequestMessage(method, requestUriStr); // Add query parameters if provided
if (queryParams?.Any() ?? false)
{
var query = HttpUtility.ParseQueryString(uriBuilder.Query);
var flagParams = queryParams.Where(param => param.Value is null).Select(param => param.Key);
var valueParams = queryParams.Where(param => param.Value is not null);
foreach (var param in valueParams)
query[param.Key] = param.Value switch
{
bool b => b.ToString().ToLower(),
_ => param.Value.ToString()
};
if (flagParams.Any())
uriBuilder.Query = string.Join(QUERY_SEPARATOR, query.ToString(), string.Join(QUERY_SEPARATOR, flagParams));
else uriBuilder.Query = query.ToString();
}
var requestUri = uriBuilder.Uri;
var requestMessage = new HttpRequestMessage(method, requestUri);
// Add headers if provided // Add headers if provided
headers?.ForEach(header => requestMessage.Headers.Add(header.Key, header.Value)); headers?.ForEach(header => requestMessage.Headers.Add(header.Key, header.Value.ToString()));
// Add cookie to request // Add cookie to request
if (sendWithCookie) if (sendWithCookie)
@@ -60,7 +125,7 @@ namespace DigitalData.Core.Client
else if (body != null) else if (body != null)
requestMessage.Content = body; requestMessage.Content = body;
else if (form != null) else if (form != null)
requestMessage.Content = new FormUrlEncodedContent(form); requestMessage.Content = new FormUrlEncodedContent(form.Select(e => KeyValuePair.Create(e.Key, e.Value.ToString())));
var response = await _client.SendAsync(requestMessage); var response = await _client.SendAsync(requestMessage);
@@ -72,5 +137,11 @@ namespace DigitalData.Core.Client
return response; return response;
} }
internal static readonly char[] URI_TRIM_CHARS = { '\\', '/', ' ' };
internal static string UriCombine(params string[] paths) => System.IO.Path.Combine(paths).Replace("\\", "/");
internal static readonly char QUERY_SEPARATOR = '&';
} }
} }

View File

@@ -1,33 +1,35 @@
using DigitalData.Core.Abstractions.Client; using DigitalData.Core.Abstractions.Client;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Options;
using System.Net; using System.Net;
namespace DigitalData.Core.Client namespace DigitalData.Core.Client
{ {
public static class DIExtensions public static class DIExtensions
{ {
public static IServiceCollection AddHttpClientService(this IServiceCollection services, string uri) internal static IServiceCollection AddHttpClientServiceDefaults(this IServiceCollection services)
{ {
services.TryAddSingleton<HttpClient>(); services.TryAddSingleton<HttpClient>();
services.TryAddSingleton<CookieContainer>(); services.TryAddSingleton<CookieContainer>();
services.AddSingleton<IBaseHttpClientService, BaseHttpClientService>();
services.Configure<HttpClientOptions>(opt => opt.Uri = uri);
return services; return services;
} }
public static IServiceCollection AddHttpClientService<TClientOptions>(this IServiceCollection services, Action<TClientOptions>? clientOptions = null, bool setAsDefaultBase = false) public static IServiceCollection AddHttpClientService<THttpClientOptions>(this IServiceCollection services, IConfigurationSection section)
where TClientOptions : HttpClientOptions where THttpClientOptions : class, IHttpClientOptions
{ {
services.TryAddSingleton<HttpClient>(); services.AddHttpClientServiceDefaults();
services.TryAddSingleton<CookieContainer>(); services.TryAddSingleton<IHttpClientService<THttpClientOptions>, HttpClientService<THttpClientOptions>>();
services.AddSingleton<IHttpClientService<TClientOptions>, HttpClientService<TClientOptions>>(); return services.Configure<THttpClientOptions>(section);
services.Configure(clientOptions ?? (_ => { })); }
if (setAsDefaultBase)
services.AddSingleton<IBaseHttpClientService, HttpClientService<TClientOptions>>();
public static IServiceCollection AddHttpClientService<THttpClientOptions>(this IServiceCollection services, THttpClientOptions options)
where THttpClientOptions : class, IHttpClientOptions
{
services.AddHttpClientServiceDefaults();
services.TryAddSingleton<IHttpClientService<THttpClientOptions>, HttpClientService<THttpClientOptions>>();
services.TryAddSingleton(Options.Create(options));
return services; return services;
} }
} }

View File

@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFrameworks>net7.0;net8.0</TargetFrameworks> <TargetFrameworks>net7.0;net8.0</TargetFrameworks>
@@ -6,7 +6,7 @@
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<Description>This package provides HTTP client extension methods for the DigitalData.Core library, offering simplified and asynchronous methods for fetching and handling HTTP responses. It includes utility methods for sending GET requests, reading response content as text or JSON, and deserializing JSON into dynamic or strongly-typed objects using Newtonsoft.Json. These extensions facilitate efficient and easy-to-read HTTP interactions in client applications.</Description> <Description>This package provides HTTP client extension methods for the DigitalData.Core library, offering simplified and asynchronous methods for fetching and handling HTTP responses. It includes utility methods for sending GET requests, reading response content as text or JSON, and deserializing JSON into dynamic or strongly-typed objects using Newtonsoft.Json. These extensions facilitate efficient and easy-to-read HTTP interactions in client applications.</Description>
<PackageId>DigitalData.Core.Client</PackageId> <PackageId>DigitalData.Core.Client</PackageId>
<Version>1.0.1.1</Version> <Version>2.0.3</Version>
<Authors>Digital Data GmbH</Authors> <Authors>Digital Data GmbH</Authors>
<Company>Digital Data GmbH</Company> <Company>Digital Data GmbH</Company>
<Product>Digital Data GmbH</Product> <Product>Digital Data GmbH</Product>
@@ -15,6 +15,8 @@
<PackageIcon>core_icon.png</PackageIcon> <PackageIcon>core_icon.png</PackageIcon>
<RepositoryUrl>http://git.dd:3000/AppStd/WebCoreModules.git</RepositoryUrl> <RepositoryUrl>http://git.dd:3000/AppStd/WebCoreModules.git</RepositoryUrl>
<PackageTags>digital data core http client json serilization</PackageTags> <PackageTags>digital data core http client json serilization</PackageTags>
<AssemblyVersion>2.0.3</AssemblyVersion>
<FileVersion>2.0.3</FileVersion>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
@@ -27,6 +29,7 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="7.0.0" /> <PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="7.0.0" />
<PackageReference Include="Microsoft.Extensions.Options" Version="7.0.0" /> <PackageReference Include="Microsoft.Extensions.Options" Version="7.0.0" />
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="7.0.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" /> <PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
</ItemGroup> </ItemGroup>

View File

@@ -1,9 +0,0 @@
using DigitalData.Core.Abstractions.Client;
namespace DigitalData.Core.Client
{
public class HttpClientOptions : IHttpClientOptions
{
public string Uri { get; init; } = string.Empty;
}
}

View File

@@ -5,9 +5,9 @@ using System.Net;
namespace DigitalData.Core.Client namespace DigitalData.Core.Client
{ {
public class HttpClientService<TClientOptions> : BaseHttpClientService, IHttpClientService<TClientOptions>, IBaseHttpClientService public class HttpClientService<TClientOptions> : BaseHttpClientService, IHttpClientService<TClientOptions>, IBaseHttpClientService
where TClientOptions : HttpClientOptions where TClientOptions : class, IHttpClientOptions
{ {
public HttpClientService(HttpClient client, CookieContainer cookieContainer, IOptions<TClientOptions> clientOptions) : base(client, cookieContainer, clientOptions) public HttpClientService(HttpClient client, CookieContainer cookieContainer, IOptions<TClientOptions> clientOptions) : base(client, cookieContainer, clientOptions.Value)
{ {
} }
} }

View File

@@ -19,7 +19,7 @@ namespace DigitalData.Core.Client
public static T Provide<T>() where T : notnull => _lazyProvider.Value.GetRequiredService<T>(); public static T Provide<T>() where T : notnull => _lazyProvider.Value.GetRequiredService<T>();
public static IHttpClientService<TOptions> ProvideHttpClientService<TOptions>() where TOptions : notnull public static IHttpClientService<TOptions> ProvideHttpClientService<TOptions>() where TOptions : IHttpClientOptions
=> _lazyProvider.Value.GetRequiredService<IHttpClientService<TOptions>>(); => _lazyProvider.Value.GetRequiredService<IHttpClientService<TOptions>>();
} }
} }

View File

@@ -14,22 +14,46 @@ namespace DigitalData.Core.Tests.Client
public void SetUp() public void SetUp()
{ {
_serviceProvider = new ServiceCollection() _serviceProvider = new ServiceCollection()
.AddHttpClientService("https://jsonplaceholder.typicode.com/todos") .AddHttpClientService("https://jsonplaceholder.typicode.com", "todos")
.BuildServiceProvider(); .BuildServiceProvider();
_service = _serviceProvider.GetRequiredService<IBaseHttpClientService>(); _service = _serviceProvider.GetRequiredService<IBaseHttpClientService>();
} }
[Test] [Test]
public async Task FetchJsonAsync_ShouldReturnJsonResponse() public async Task FetchJsonAsync_ShouldReturnJsonResponse_WithCorrectWithPath()
{ {
// Act // Act
var expectedUserId = (int) await _service.FetchAsync("/1", sendWithCookie: false, saveCookie: false) var expectedUserId = (int) await _service.FetchAsync(path: "/1", sendWithCookie: false, saveCookie: false)
.ThenAsync(res => res.Json()) .ThenAsync(res => res.Json())
.ThenAsync(todo => todo.userId); .ThenAsync(todo => todo.userId);
// Assert // Assert
Assert.That(expectedUserId, Is.EqualTo(1), "The userId of the fetched JSON object should be 1."); Assert.That(expectedUserId, Is.EqualTo(1), "The userId of the fetched JSON object should be 1.");
} }
[Test]
public async Task FetchJsonAsync_ShouldReturnJsonResponse_WithQueryParams()
{
var queryParams = new Dictionary<string, object?>
{
{ "id", "1" }
};
// Act
var dyn_id = await _service.FetchAsync(queryParams: queryParams, sendWithCookie: false, saveCookie: false)
.ThenAsync(res => res.JsonList())
.ThenAsync(todo => todo.FirstOrDefault()?.userId);
try
{
Assert.That((int)dyn_id, Is.EqualTo(1), "The userId of the fetched JSON object should be 1.");
}
catch (InvalidCastException)
{
// Handle the case where the cast is not possible
Assert.Fail("The id could not be cast to an integer.");
}
}
} }
} }

View File

@@ -23,7 +23,9 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DigitalData.Core.Legacy.Cli
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DigitalData.Core.Security", "DigitalData.Core.Security\DigitalData.Core.Security.csproj", "{47D80C65-74A2-4EB8-96A5-D571A9108FB3}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DigitalData.Core.Security", "DigitalData.Core.Security\DigitalData.Core.Security.csproj", "{47D80C65-74A2-4EB8-96A5-D571A9108FB3}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DigitalData.Core.Security.Extensions", "DigitalData.Core.Security.Extensions\DigitalData.Core.Security.Extensions.csproj", "{D740182D-82DA-480A-9F87-BFB4A8620A00}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DigitalData.Core.Security.Extensions", "DigitalData.Core.Security.Extensions\DigitalData.Core.Security.Extensions.csproj", "{D740182D-82DA-480A-9F87-BFB4A8620A00}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DigitalData.Core.Terminal", "DigitalData.Core.Terminal\DigitalData.Core.Terminal.csproj", "{0FA93730-8084-4907-B172-87D610323796}"
EndProject EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -51,8 +53,8 @@ Global
{0B051A5F-BD38-47D1-BAFF-D44BA30D3FB7}.Debug|Any CPU.Build.0 = Release|Any CPU {0B051A5F-BD38-47D1-BAFF-D44BA30D3FB7}.Debug|Any CPU.Build.0 = Release|Any CPU
{0B051A5F-BD38-47D1-BAFF-D44BA30D3FB7}.Release|Any CPU.ActiveCfg = Release|Any CPU {0B051A5F-BD38-47D1-BAFF-D44BA30D3FB7}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0B051A5F-BD38-47D1-BAFF-D44BA30D3FB7}.Release|Any CPU.Build.0 = Release|Any CPU {0B051A5F-BD38-47D1-BAFF-D44BA30D3FB7}.Release|Any CPU.Build.0 = Release|Any CPU
{6A80FFEC-9B83-40A7-8C78-124440B48B33}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {6A80FFEC-9B83-40A7-8C78-124440B48B33}.Debug|Any CPU.ActiveCfg = Release|Any CPU
{6A80FFEC-9B83-40A7-8C78-124440B48B33}.Debug|Any CPU.Build.0 = Debug|Any CPU {6A80FFEC-9B83-40A7-8C78-124440B48B33}.Debug|Any CPU.Build.0 = Release|Any CPU
{6A80FFEC-9B83-40A7-8C78-124440B48B33}.Release|Any CPU.ActiveCfg = Release|Any CPU {6A80FFEC-9B83-40A7-8C78-124440B48B33}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6A80FFEC-9B83-40A7-8C78-124440B48B33}.Release|Any CPU.Build.0 = Release|Any CPU {6A80FFEC-9B83-40A7-8C78-124440B48B33}.Release|Any CPU.Build.0 = Release|Any CPU
{13E40DF1-6123-4838-9BF8-086C94E6ADF6}.Debug|Any CPU.ActiveCfg = Release|Any CPU {13E40DF1-6123-4838-9BF8-086C94E6ADF6}.Debug|Any CPU.ActiveCfg = Release|Any CPU
@@ -74,6 +76,10 @@ Global
{D740182D-82DA-480A-9F87-BFB4A8620A00}.Debug|Any CPU.Build.0 = Debug|Any CPU {D740182D-82DA-480A-9F87-BFB4A8620A00}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D740182D-82DA-480A-9F87-BFB4A8620A00}.Release|Any CPU.ActiveCfg = Release|Any CPU {D740182D-82DA-480A-9F87-BFB4A8620A00}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D740182D-82DA-480A-9F87-BFB4A8620A00}.Release|Any CPU.Build.0 = Release|Any CPU {D740182D-82DA-480A-9F87-BFB4A8620A00}.Release|Any CPU.Build.0 = Release|Any CPU
{0FA93730-8084-4907-B172-87D610323796}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0FA93730-8084-4907-B172-87D610323796}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0FA93730-8084-4907-B172-87D610323796}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0FA93730-8084-4907-B172-87D610323796}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE