diff --git a/src/Ramstack.HtmxToolkit/Argument.cs b/src/Ramstack.HtmxToolkit/Argument.cs
new file mode 100644
index 0000000..129760b
--- /dev/null
+++ b/src/Ramstack.HtmxToolkit/Argument.cs
@@ -0,0 +1,73 @@
+// ReSharper disable ParameterOnlyUsedForPreconditionCheck.Local
+
+using System.Diagnostics.CodeAnalysis;
+using System.Runtime.CompilerServices;
+
+namespace Ramstack.HtmxToolkit;
+
+///
+/// Provides helper methods to validate arguments and throw exceptions if the arguments do not meet specified conditions.
+///
+internal static class Argument
+{
+ ///
+ /// Throws an if the specified object is .
+ ///
+ /// The object to check.
+ /// The name of the parameter being checked. Automatically supplied by the compiler.
+ public static void ThrowIfNull([NotNull] object? value, [CallerArgumentExpression(nameof(value))] string? paramName = null)
+ {
+ if (value is null)
+ Error_ArgumentNull(paramName);
+ }
+
+ ///
+ /// Throws an if the specified string is ,
+ /// or an if it is empty.
+ ///
+ /// The string to check.
+ /// The name of the parameter being checked. Automatically supplied by the compiler.
+ public static void ThrowIfNullOrEmpty([NotNull] string? value, [CallerArgumentExpression(nameof(value))] string? paramName = null)
+ {
+ if (string.IsNullOrEmpty(value))
+ Error_ArgumentNullOrEmpty(value, paramName);
+ }
+
+ ///
+ /// Throws an if the specified string is ,
+ /// or an if it is empty or consists only of white-space characters.
+ ///
+ /// The string to check.
+ /// The name of the parameter being checked. Automatically supplied by the compiler.
+ public static void ThrowIfNullOrWhiteSpace([NotNull] string? value, [CallerArgumentExpression(nameof(value))] string? paramName = null)
+ {
+ if (string.IsNullOrWhiteSpace(value))
+ Error_ArgumentNullOrWhiteSpace(value, paramName);
+ }
+
+ [DoesNotReturn]
+ private static void Error_ArgumentNull(string? paramName) =>
+ throw new ArgumentNullException(paramName);
+
+ [DoesNotReturn]
+ private static void Error_ArgumentNullOrEmpty(string? value, string? paramName)
+ {
+ if (value is null)
+ throw new ArgumentNullException(paramName);
+
+ throw new ArgumentException(
+ "Argument should not be empty.",
+ paramName);
+ }
+
+ [DoesNotReturn]
+ private static void Error_ArgumentNullOrWhiteSpace(string? value, string? paramName)
+ {
+ if (value is null)
+ throw new ArgumentNullException(paramName);
+
+ throw new ArgumentException(
+ "Argument should not be empty or whitespace.",
+ paramName);
+ }
+}
diff --git a/src/Ramstack.HtmxToolkit/Collections/SmallDictionary.cs b/src/Ramstack.HtmxToolkit/Collections/SmallDictionary.cs
index a43bd72..a112653 100644
--- a/src/Ramstack.HtmxToolkit/Collections/SmallDictionary.cs
+++ b/src/Ramstack.HtmxToolkit/Collections/SmallDictionary.cs
@@ -77,7 +77,7 @@ public TValue this[TKey key]
/// The comparer to use when comparing keys.
public SmallDictionary(IComparer comparer)
{
- ArgumentNullException.ThrowIfNull(comparer);
+ Argument.ThrowIfNull(comparer);
_comparer = comparer;
}
@@ -90,7 +90,7 @@ public SmallDictionary(IComparer comparer)
/// The comparer to use when comparing keys.
public SmallDictionary(IEnumerable> collection, IComparer comparer) : this(comparer)
{
- ArgumentNullException.ThrowIfNull(collection);
+ Argument.ThrowIfNull(collection);
if (collection is Dictionary dictionary)
{
diff --git a/src/Ramstack.HtmxToolkit/HtmxResponse.cs b/src/Ramstack.HtmxToolkit/HtmxResponse.cs
index 301e319..fc2e33b 100644
--- a/src/Ramstack.HtmxToolkit/HtmxResponse.cs
+++ b/src/Ramstack.HtmxToolkit/HtmxResponse.cs
@@ -95,8 +95,7 @@ static HtmxResponse LocationImpl(HtmxResponse response, string path, HtmxLocatio
///
public HtmxResponse PushUrl(string url)
{
- if (string.IsNullOrEmpty(url))
- throw new ArgumentException("URL cannot be null or empty.", nameof(url));
+ Argument.ThrowIfNullOrEmpty(url);
return SetHistoryHeader(this, HtmxResponseHeaderNames.PushUrl, url, HtmxResponseHeaderNames.ReplaceUrl);
}
@@ -127,8 +126,7 @@ public HtmxResponse PushUrl(string url)
///
public HtmxResponse ReplaceUrl(string url)
{
- if (string.IsNullOrEmpty(url))
- throw new ArgumentException("URL cannot be null or empty.", nameof(url));
+ Argument.ThrowIfNullOrEmpty(url);
return SetHistoryHeader(this, HtmxResponseHeaderNames.ReplaceUrl, url, HtmxResponseHeaderNames.PushUrl);
}
@@ -344,7 +342,7 @@ private static HtmxResponse TriggerEventCore(HtmxResponse response, string ev
private static string SerializeEventDetail(T detail, JsonTypeInfo jsonTypeInfo)
{
- ArgumentNullException.ThrowIfNull(jsonTypeInfo);
+ Argument.ThrowIfNull(jsonTypeInfo);
var buffer = new ArrayBufferWriter();
using (var writer = new Utf8JsonWriter(buffer, new JsonWriterOptions { Encoder = JsonOptions.Encoder, SkipValidation = true }))
diff --git a/src/Ramstack.HtmxToolkit/Internal/PendingEvents.cs b/src/Ramstack.HtmxToolkit/Internal/PendingEvents.cs
index 5f02f24..5fa0ac1 100644
--- a/src/Ramstack.HtmxToolkit/Internal/PendingEvents.cs
+++ b/src/Ramstack.HtmxToolkit/Internal/PendingEvents.cs
@@ -49,11 +49,8 @@ private PendingEvents(HttpResponse response) =>
/// The event detail as JSON.
public void AddEvent(HtmxTriggerTiming timing, string eventName, string detailJson)
{
- if (string.IsNullOrWhiteSpace(eventName))
- throw new ArgumentException("Event name cannot be null or whitespace.", nameof(eventName));
-
- if (string.IsNullOrWhiteSpace(detailJson))
- throw new ArgumentException("Event detail JSON cannot be null or whitespace.", nameof(detailJson));
+ Argument.ThrowIfNullOrWhiteSpace(eventName);
+ Argument.ThrowIfNullOrWhiteSpace(detailJson);
if (eventName == ProxyEventName)
throw new ArgumentException(
diff --git a/tests/Ramstack.HtmxToolkit.Tests/HtmxResponseTests.cs b/tests/Ramstack.HtmxToolkit.Tests/HtmxResponseTests.cs
index 4940819..3a4be18 100644
--- a/tests/Ramstack.HtmxToolkit.Tests/HtmxResponseTests.cs
+++ b/tests/Ramstack.HtmxToolkit.Tests/HtmxResponseTests.cs
@@ -353,7 +353,7 @@ public void ReplaceUrl_NullOrEmpty_ThrowsArgumentException(string? url)
{
var context = TestHelper.CreateHtmxRequestContext();
- var exception = Assert.Throws(() =>
+ var exception = Assert.Catch(() =>
context.Response.Htmx(r => r.ReplaceUrl(url!)));
Assert.That(exception?.ParamName, Is.EqualTo("url"));
diff --git a/tests/Ramstack.HtmxToolkit.Tests/Internal/PendingEventsTests.cs b/tests/Ramstack.HtmxToolkit.Tests/Internal/PendingEventsTests.cs
index cdaa9e9..b6dc210 100644
--- a/tests/Ramstack.HtmxToolkit.Tests/Internal/PendingEventsTests.cs
+++ b/tests/Ramstack.HtmxToolkit.Tests/Internal/PendingEventsTests.cs
@@ -357,7 +357,7 @@ public void AddEvent_NullOrWhitespaceDetail_ThrowsArgumentException(string? deta
var context = TestHelper.CreateHttpContext();
var pending = PendingEvents.GetOrCreate(context.Response);
- var exception = Assert.Throws(() =>
+ var exception = Assert.Catch(() =>
pending.AddEvent(HtmxTriggerTiming.Receive, "e", detail!));
Assert.That(exception?.ParamName, Is.EqualTo("detailJson"));
@@ -371,7 +371,7 @@ public void AddEvent_NullOrWhitespaceEventName_ThrowsArgumentException(string? e
var context = TestHelper.CreateHttpContext();
var pending = PendingEvents.GetOrCreate(context.Response);
- var exception = Assert.Throws(() =>
+ var exception = Assert.Catch(() =>
pending.AddEvent(HtmxTriggerTiming.Receive, eventName!, "1"));
Assert.That(exception?.ParamName, Is.EqualTo("eventName"));