Add BuildQueryFromObject<T> method for query strings

Enhanced ReCClientHelpers.cs with a new utility method:
- Added `BuildQueryFromObject<T>` to serialize objects into query strings.
- Skips `null` properties and escapes names/values for safety.
- Added `System.Collections` and `System.Reflection` namespaces to support reflection and collection operations.

This improves HTTP request handling by enabling dynamic query string generation from object payloads.
This commit is contained in:
2026-05-20 09:19:18 +02:00
parent 6d8e51ad70
commit 5239c2f071

View File

@@ -1,8 +1,10 @@
using System;
using System.Collections;
using System.Globalization;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Json;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
@@ -46,6 +48,30 @@ namespace ReC.Client
/// <returns>A <see cref="JsonContent"/> instance ready for HTTP requests.</returns>
public static JsonContent ToJsonContent<T>(T payload) => JsonContent.Create(payload);
/// <summary>
/// Builds a query string from the public readable properties of <paramref name="payload"/>,
/// skipping properties whose values are <see langword="null"/>.
/// </summary>
/// <typeparam name="T">The payload type.</typeparam>
/// <param name="payload">The payload to serialize into a query string.</param>
/// <returns>A query string beginning with '?', or an empty string if no values are provided.</returns>
public static string BuildQueryFromObject<T>(T payload)
{
if (payload == null)
return string.Empty;
var props = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance)
.Where(p => p.CanRead && p.GetIndexParameters().Length == 0);
var parts = props
.Select(p => new { p.Name, Value = p.GetValue(payload) })
.Where(p => p.Value != null)
.Select(p => $"{Uri.EscapeDataString(p.Name)}={Uri.EscapeDataString(Convert.ToString(p.Value, CultureInfo.InvariantCulture) ?? string.Empty)}");
var query = string.Join("&", parts);
return string.IsNullOrWhiteSpace(query) ? string.Empty : $"?{query}";
}
/// <summary>
/// Logs the outcome of an HTTP response. Throws a <see cref="ReCApiException"/> when the
/// response indicates a non-success status code; otherwise (optionally) writes an informational