21 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
11 changed files with 90 additions and 67 deletions

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="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>
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;
return viewResult;

View File

@@ -8,7 +8,7 @@
<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>
<PackageId>DigitalData.Core.API</PackageId>
<Version>2.0.0.0</Version>
<Version>2.0.1</Version>
<Authors>Digital Data GmbH</Authors>
<Company>Digital Data GmbH</Company>
<Product>DigitalData.Core.API</Product>
@@ -16,6 +16,8 @@
<RepositoryUrl>http://git.dd:3000/AppStd/WebCoreModules.git</RepositoryUrl>
<PackageTags>digital data core api</PackageTags>
<PackageIcon>core_icon.png</PackageIcon>
<AssemblyVersion>2.0.1</AssemblyVersion>
<FileVersion>2.0.1</FileVersion>
</PropertyGroup>
<ItemGroup>

View File

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

View File

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

View File

@@ -17,9 +17,9 @@
<RepositoryUrl>http://git.dd:3000/AppStd/WebCoreModules.git</RepositoryUrl>
<PackAsTool>False</PackAsTool>
<PackageIcon>core_icon.png</PackageIcon>
<Version>2.1.0.0</Version>
<AssemblyVersion>2.1.0.0</AssemblyVersion>
<FileVersion>2.1.0.0</FileVersion>
<Version>2.2.1</Version>
<AssemblyVersion>2.2.1</AssemblyVersion>
<FileVersion>2.2.1</FileVersion>
</PropertyGroup>
<ItemGroup>

View File

@@ -1,5 +1,4 @@
using DigitalData.Core.Abstractions.Client;
using Microsoft.Extensions.Options;
using System.Diagnostics.CodeAnalysis;
using System.Net;
using System.Web;
@@ -12,50 +11,82 @@ namespace DigitalData.Core.Client
protected readonly CookieContainer _cookies;
[StringSyntax("Uri")]
public string Uri { get; init; }
protected readonly string _uri;
public string Path { get; init; } = string.Empty;
protected readonly string _path;
public BaseHttpClientService(HttpClient client, CookieContainer cookieContainer, IOptions<HttpClientOptions> clientOptions)
protected IEnumerable<KeyValuePair<string, object>>? _headers;
protected IEnumerable<KeyValuePair<string, object?>>? _queryParams;
internal BaseHttpClientService(HttpClient client, CookieContainer cookieContainer, IHttpClientOptions clientOptions)
{
_client = client;
_cookies = cookieContainer;
Uri = clientOptions.Value.Uri.Trim(URI_TRIM_CHARS);
Path = clientOptions.Value.Path.Trim(URI_TRIM_CHARS);
_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 path = "") => _cookies.GetCookies(uri: new Uri(UriCombine(Uri, path, path.Trim(URI_TRIM_CHARS))));
public CookieCollection GetCookies(string path = "") => _cookies.GetCookies(uri: new Uri(UriCombine(_uri, path, path.Trim(URI_TRIM_CHARS))));
public async Task<HttpResponseMessage> FetchAsync(
string? scheme = null,
int? port = null,
string path = "",
Dictionary<string, object?>? queryParams = null,
IEnumerable<KeyValuePair<string, object?>>? queryParams = null,
HttpMethod? method = null,
HttpContent? body = null,
Dictionary<string, string>? form = null,
Dictionary<string, string>? headers = null,
IEnumerable<KeyValuePair<string, object>>? form = null,
IEnumerable<KeyValuePair<string, object>>? headers = null,
bool sendWithCookie = 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
method ??= HttpMethod.Get;
// create URL
var uriBuilder = new UriBuilder(Uri);
var uriBuilder = new UriBuilder(_uri);
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);
uriBuilder.Path = UriCombine(_path, path?.Trim(URI_TRIM_CHARS) ?? string.Empty);
// 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 => HttpUtility.UrlEncode(param.Key));
var flagParams = queryParams.Where(param => param.Value is null).Select(param => param.Key);
var valueParams = queryParams.Where(param => param.Value is not null);
@@ -63,20 +94,20 @@ namespace DigitalData.Core.Client
query[param.Key] = param.Value switch
{
bool b => b.ToString().ToLower(),
_ => HttpUtility.UrlEncode(param.Value.ToString())
_ => param.Value.ToString()
};
var flagQuery = string.Join(QUERY_SEPARATOR, flagParams);
uriBuilder.Query = string.Join(QUERY_SEPARATOR, query.ToString(), flagQuery);
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;
Console.WriteLine(requestUri);
var requestMessage = new HttpRequestMessage(method, requestUri);
// 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
if (sendWithCookie)
@@ -94,7 +125,7 @@ namespace DigitalData.Core.Client
else if (body != null)
requestMessage.Content = body;
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);

View File

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

View File

@@ -6,7 +6,7 @@
<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>
<PackageId>DigitalData.Core.Client</PackageId>
<Version>1.1.0</Version>
<Version>2.0.3</Version>
<Authors>Digital Data GmbH</Authors>
<Company>Digital Data GmbH</Company>
<Product>Digital Data GmbH</Product>
@@ -15,8 +15,8 @@
<PackageIcon>core_icon.png</PackageIcon>
<RepositoryUrl>http://git.dd:3000/AppStd/WebCoreModules.git</RepositoryUrl>
<PackageTags>digital data core http client json serilization</PackageTags>
<AssemblyVersion>1.1.0</AssemblyVersion>
<FileVersion>1.1.0</FileVersion>
<AssemblyVersion>2.0.3</AssemblyVersion>
<FileVersion>2.0.3</FileVersion>
</PropertyGroup>
<ItemGroup>
@@ -29,6 +29,7 @@
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.DependencyInjection" 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" />
</ItemGroup>

View File

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

View File

@@ -5,9 +5,9 @@ using System.Net;
namespace DigitalData.Core.Client
{
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

@@ -53,8 +53,8 @@ Global
{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.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.Build.0 = 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 = 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
{13E40DF1-6123-4838-9BF8-086C94E6ADF6}.Debug|Any CPU.ActiveCfg = Release|Any CPU