diff --git a/src/Ramstack.HtmxToolkit/Configuration/HtmxConfig.cs b/src/Ramstack.HtmxToolkit/Configuration/HtmxConfig.cs
index fd4f6e7..ccd5119 100644
--- a/src/Ramstack.HtmxToolkit/Configuration/HtmxConfig.cs
+++ b/src/Ramstack.HtmxToolkit/Configuration/HtmxConfig.cs
@@ -7,6 +7,11 @@ namespace Ramstack.HtmxToolkit.Configuration;
///
/// Represents configuration for a specific major version of HTMX.
///
+///
+/// Configuration JSON is cached until a configuration property is assigned.
+/// Changes made in place to arrays, collections, or their items do not invalidate the cache;
+/// reassign the containing property after making such changes.
+///
public abstract class HtmxConfig
{
private HtmlString? _json;
@@ -28,7 +33,7 @@ internal HtmxConfig(HtmxTargetVersion version) =>
///
/// Returns this configuration serialized as JSON. The result is
- /// cached and reused until the configuration changes.
+ /// cached and reused until a configuration property is assigned.
///
///
/// An containing the configuration serialized as JSON.
diff --git a/src/Ramstack.HtmxToolkit/HtmxLocationOptions.cs b/src/Ramstack.HtmxToolkit/HtmxLocationOptions.cs
index c5d64df..0a87884 100644
--- a/src/Ramstack.HtmxToolkit/HtmxLocationOptions.cs
+++ b/src/Ramstack.HtmxToolkit/HtmxLocationOptions.cs
@@ -75,10 +75,18 @@ public HtmxSwap? Swap
public string? Select { get; set; }
///
- /// Gets or sets a comma-separated list of selectors, optionally followed by swap styles,
- /// used to select content for out-of-band swaps from the response.
+ /// Gets or sets a comma-separated list of elements, each optionally followed by a colon
+ /// and a swap style, used to select content for out-of-band swaps from the response.
///
- /// Supported in HTMX 2.0.8 and later 2.x releases, and in HTMX 4.x.
+ ///
+ /// Supported in HTMX 2.0.8 and later 2.x releases, and in HTMX 4.x.
+ ///
+ /// HTMX 2.x accepts only element IDs, with or without a leading #,
+ /// for example #alerts,#cart:innerHTML. HTMX 4.x accepts CSS selectors.
+ /// Neither version supports IDs or selectors that contain a comma or a colon,
+ /// such as li:first-child.
+ ///
+ ///
public string? SelectOob { get; set; }
///
diff --git a/src/Ramstack.HtmxToolkit/HtmxRequestAttribute.cs b/src/Ramstack.HtmxToolkit/HtmxRequestAttribute.cs
index 6ee7899..f52b658 100644
--- a/src/Ramstack.HtmxToolkit/HtmxRequestAttribute.cs
+++ b/src/Ramstack.HtmxToolkit/HtmxRequestAttribute.cs
@@ -51,7 +51,7 @@ public bool Accept(ActionConstraintContext context)
if (BoostedFilter == HtmxBoostedFilter.Any)
return true;
- var filter = request.IsHtmxBoosted()
+ var filter = headers.Boosted
? HtmxBoostedFilter.Boosted
: HtmxBoostedFilter.NonBoosted;
diff --git a/src/Ramstack.HtmxToolkit/HtmxRequestCache.cs b/src/Ramstack.HtmxToolkit/HtmxRequestCache.cs
index 7ed96bf..dc32b51 100644
--- a/src/Ramstack.HtmxToolkit/HtmxRequestCache.cs
+++ b/src/Ramstack.HtmxToolkit/HtmxRequestCache.cs
@@ -8,6 +8,7 @@ public enum HtmxRequestCache
{
///
/// Uses the browser's normal HTTP cache behavior.
+ /// This is the Fetch default.
///
Default,
diff --git a/src/Ramstack.HtmxToolkit/HtmxRequestRedirect.cs b/src/Ramstack.HtmxToolkit/HtmxRequestRedirect.cs
index a705a40..1873f82 100644
--- a/src/Ramstack.HtmxToolkit/HtmxRequestRedirect.cs
+++ b/src/Ramstack.HtmxToolkit/HtmxRequestRedirect.cs
@@ -8,6 +8,7 @@ public enum HtmxRequestRedirect
{
///
/// Follows redirects automatically.
+ /// This is the Fetch default.
///
Follow,
diff --git a/src/Ramstack.HtmxToolkit/HttpRequestExtensions.cs b/src/Ramstack.HtmxToolkit/HttpRequestExtensions.cs
index 96cb6ce..371510f 100644
--- a/src/Ramstack.HtmxToolkit/HttpRequestExtensions.cs
+++ b/src/Ramstack.HtmxToolkit/HttpRequestExtensions.cs
@@ -58,6 +58,9 @@ public static bool IsHtmxBoosted(this HttpRequest request) =>
/// including HTMX 1.x and 2.x requests without this header.
///
public static bool IsHtmxFullRequest(this HttpRequest request) =>
+ // PERF: Compare the header directly instead of using GetHtmxHeaders().RequestType.
+ // The parser also recognizes "partial", and the JIT does not reliably eliminate
+ // that extra comparison even when the parser is inlined.
request.Headers.TryGetValue(HtmxRequestHeaderNames.RequestType, out var value) && value is ["full"];
///
@@ -73,6 +76,7 @@ public static bool IsHtmxFullRequest(this HttpRequest request) =>
/// including HTMX 1.x and 2.x requests without this header.
///
public static bool IsHtmxPartialRequest(this HttpRequest request) =>
+ // PERF: See IsHtmxFullRequest.
request.Headers.TryGetValue(HtmxRequestHeaderNames.RequestType, out var value) && value is ["partial"];
///