diff --git a/src/ReC.Client/ReCClientHelpers.cs b/src/ReC.Client/ReCClientHelpers.cs
index a7c5595..0bf1ab3 100644
--- a/src/ReC.Client/ReCClientHelpers.cs
+++ b/src/ReC.Client/ReCClientHelpers.cs
@@ -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
/// A instance ready for HTTP requests.
public static JsonContent ToJsonContent(T payload) => JsonContent.Create(payload);
+ ///
+ /// Builds a query string from the public readable properties of ,
+ /// skipping properties whose values are .
+ ///
+ /// The payload type.
+ /// The payload to serialize into a query string.
+ /// A query string beginning with '?', or an empty string if no values are provided.
+ public static string BuildQueryFromObject(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}";
+ }
+
///
/// Logs the outcome of an HTTP response. Throws a when the
/// response indicates a non-success status code; otherwise (optionally) writes an informational