Table of Contents

Struct HtmxResponse

Namespace
Ramstack.HtmxToolkit
Assembly
Ramstack.HtmxToolkit.dll

Represents an HTTP response whose HTMX response headers can be configured.

public readonly struct HtmxResponse
Inherited Members

Remarks

Like HttpContext and HttpResponse themselves, this type is not thread-safe. Its members should not be called concurrently from multiple threads for the same request.

Properties

Headers

Gets the strongly typed HTMX response headers.

public HtmxResponseHeaders Headers { get; }

Property Value

HtmxResponseHeaders

Methods

Location(string)

Sets the HX-Location header to perform a client-side redirect without a full-page reload.

public HtmxResponse Location(string value)

Parameters

value string

The path or serialized JSON options to assign to the header.

Returns

HtmxResponse

The current HtmxResponse instance.

Location(string, HtmxLocationOptions)

Sets the HX-Location header to perform a client-side redirect without a full-page reload.

public HtmxResponse Location(string path, HtmxLocationOptions options)

Parameters

path string

The path to request.

options HtmxLocationOptions

The options used to issue the request.

Returns

HtmxResponse

The current HtmxResponse instance.

Examples

[HttpPost]
public IActionResult Save(ProductInput input)
{
    var product = catalog.Update(input);

    // Load the details fragment into the page, but show the product page URL
    // in the address bar so that a reload or a shared link opens the full page.
    Response.Htmx(htmx => htmx.Location(
        Url.Action(nameof(Details), new { id = product.Id })!,
        new HtmxLocationOptions
        {
            Target = "#product-details",
            Swap = HtmxSwap.OuterHtml,
            HistoryUrl = Url.Action(nameof(Show), new { id = product.Id })
        }));

    return NoContent();
}

PreventHistoryUpdate()

Sets the HX-Push-Url header to "false" to prevent the browser's history from being updated.

public HtmxResponse PreventHistoryUpdate()

Returns

HtmxResponse

The current HtmxResponse instance.

Examples

[HttpPost("/orders")]
public IActionResult Create(OrderInput input)
{
    if (!ModelState.IsValid)
    {
        // The boosted form on /orders/new would push /orders, the POST URL,
        // into the history. Keep /orders/new so that a reload shows the form again.
        Response.Htmx(htmx => htmx.PreventHistoryUpdate());
        return View("New", input);
    }

    var order = orders.Create(input);
    return RedirectToAction(nameof(Details), new { id = order.Id });
}

Remarks

Also removes the HX-Replace-Url header and the legacy HX-Push header, which HTMX 1.9.x and 2.x would otherwise prefer. When PushUrl(string), ReplaceUrl(string), and PreventHistoryUpdate() are combined, the last call takes effect.

The history is not updated even when the hx-push-url or hx-replace-url attribute or boosted navigation requests it.

PushUrl(string)

Sets the HX-Push-Url header to push a new URL onto the browser's history stack.

public HtmxResponse PushUrl(string url)

Parameters

url string

A relative or same-origin absolute URL to push into the location bar, as supported by history.pushState().

Returns

HtmxResponse

The current HtmxResponse instance.

Remarks

Also removes the HX-Replace-Url header and the legacy HX-Push header, which HTMX 1.9.x and 2.x would otherwise prefer. When PushUrl(string), ReplaceUrl(string), and PreventHistoryUpdate() are combined, the last call takes effect.

HTMX treats "false" and "true" as control values. Use PreventHistoryUpdate() instead of "false". HTMX 4.x replaces "true" with the response URL, while HTMX 1.9.x and 2.x push it as the relative URL true.

Redirect(string)

Sets the HX-Redirect header to perform a client-side redirect with a full-page reload.

public HtmxResponse Redirect(string value)

Parameters

value string

The header value to set.

Returns

HtmxResponse

The current HtmxResponse instance.

Examples

[HttpPost]
public IActionResult SignIn(LoginInput input)
{
    if (!auth.TrySignIn(input))
    {
        ModelState.AddModelError("", "Invalid email or password.");
        return Request.IsHtmxRequest()
            ? PartialView("_SignInForm", input)
            : View(input);
    }

    var url = Url.Action("Index", "Dashboard")!;

    if (Request.IsHtmxRequest())
    {
        // HTMX cannot read headers from a 3xx response, so send HX-Redirect with 200.
        Response.Htmx(htmx => htmx.Redirect(url));
        return Ok();
    }

    return Redirect(url);
}

Refresh()

Sets the HX-Refresh header to request a full-page refresh.

public HtmxResponse Refresh()

Returns

HtmxResponse

The current HtmxResponse instance.

ReplaceUrl(string)

Sets the HX-Replace-Url header to replace the current URL.

public HtmxResponse ReplaceUrl(string url)

Parameters

url string

A URL to replace the current URL in the location bar. This may be relative or absolute, as supported by history.replaceState(), but must have the same origin as the current URL.

Returns

HtmxResponse

The current HtmxResponse instance.

Examples

public IActionResult OnGetSearch(string query = "")
{
    // Keep the query in the address bar without adding a history entry for every keystroke.
    // The page must render the same results when /Catalog?query=... is opened directly.
    Response.Htmx(htmx => htmx.ReplaceUrl(Url.Page("/Catalog", new { query })!));

    return Partial("_SearchResults", catalog.Search(query));
}

Remarks

Also removes the HX-Push-Url header and the legacy HX-Push header, which HTMX 1.9.x and 2.x would otherwise prefer. When PushUrl(string), ReplaceUrl(string), and PreventHistoryUpdate() are combined, the last call takes effect.

HTMX treats "false" and "true" as control values. Use PreventHistoryUpdate() instead of "false". HTMX 4.x replaces "true" with the response URL, while HTMX 1.9.x and 2.x use it as the relative URL true.

Reselect(string)

Sets the HX-Reselect header to select the part of the response to swap in.

public HtmxResponse Reselect(string value)

Parameters

value string

The CSS selector to set.

Returns

HtmxResponse

The current HtmxResponse instance.

Reswap(HtmxSwap)

Sets the HX-Reswap header to specify how the response will be swapped.

public HtmxResponse Reswap(HtmxSwap value)

Parameters

value HtmxSwap

The swap style to assign to the header.

Returns

HtmxResponse

The current HtmxResponse instance.

Examples

Response.Htmx(htmx => htmx
    .Retarget("#validation-errors")
    .Reswap(HtmxSwap.InnerHtml));

return PartialView("_ValidationSummary", ModelState);

Reswap(string)

Sets the HX-Reswap header to specify how the response will be swapped.

public HtmxResponse Reswap(string value)

Parameters

value string

The header value to set.

Returns

HtmxResponse

The current HtmxResponse instance.

Retarget(string)

Sets the HX-Retarget header to update the target of the content update to a different element on the page.

public HtmxResponse Retarget(string value)

Parameters

value string

The CSS selector to set.

Returns

HtmxResponse

The current HtmxResponse instance.

TriggerEvent(string, HtmxTriggerTiming)

Adds a client-side event to the response header selected by timing.

public HtmxResponse TriggerEvent(string eventName, HtmxTriggerTiming timing = HtmxTriggerTiming.Receive)

Parameters

eventName string

The event name to trigger.

timing HtmxTriggerTiming

The event timing. Defaults to Receive.

Returns

HtmxResponse

The current HtmxResponse instance.

Examples

public IActionResult OnPostSave()
{
    _profiles.DisplayName = Input.DisplayName;

    // Components that listen for "profile-saved" reload themselves
    // after the form is swapped. The event needs no data.
    Response.Htmx(htmx => htmx.TriggerEvent("profile-saved", HtmxTriggerTiming.AfterSwap));

    return Partial("_ProfileForm", this);
}
@addTagHelper *, Ramstack.HtmxToolkit

@* Place the listener outside the form, so the save response does not replace it. *@
<aside hx-page="/Profile"
       hx-page-handler="Summary"
       hx-trigger="profile-saved from:body">
    ...
</aside>

Remarks

In HTMX 4.x, every HtmxTriggerTiming value is emitted through HX-Trigger and runs when the request completes (after the swap whenever one is performed). See PR #3900.

Events are triggered in the order they are added. If an event name is added more than once for the same header, all events of that header are replayed by the Toolkit script, which must be loaded for any of them to be triggered.

TriggerEvent(string, object, HtmxTriggerTiming)

Adds a client-side event and its detail to the response header selected by timing.

[RequiresUnreferencedCode("Event details are serialized using reflection. Use the TriggerEvent overload that accepts JsonTypeInfo<T> for trimmed applications.")]
public HtmxResponse TriggerEvent(string eventName, object detail, HtmxTriggerTiming timing = HtmxTriggerTiming.Receive)

Parameters

eventName string

The event name to trigger.

detail object

The event detail.

timing HtmxTriggerTiming

The event timing. Defaults to Receive.

Returns

HtmxResponse

The current HtmxResponse instance.

Examples

Response.Htmx(htmx => htmx.TriggerEvent(
    "product-saved",
    new { product.Id },
    HtmxTriggerTiming.AfterSwap));

return PartialView("_ProductRow", product);

Remarks

In HTMX 4.x, every HtmxTriggerTiming value is emitted through HX-Trigger and runs when the request completes (after the swap whenever one is performed). See PR #3900.

Events are triggered in the order they are added. If an event name is added more than once for the same header, all events of that header are replayed by the Toolkit script, which must be loaded for any of them to be triggered.

TriggerEvent<T>(string, T, JsonTypeInfo<T>, HtmxTriggerTiming)

Adds a client-side event and serializes its detail using the specified JSON metadata.

public HtmxResponse TriggerEvent<T>(string eventName, T detail, JsonTypeInfo<T> jsonTypeInfo, HtmxTriggerTiming timing = HtmxTriggerTiming.Receive)

Parameters

eventName string

The event name to trigger.

detail T

The event detail.

jsonTypeInfo JsonTypeInfo<T>

The JSON metadata for the event detail. Use source-generated metadata for trimming and Native AOT.

timing HtmxTriggerTiming

The event timing. Defaults to Receive.

Returns

HtmxResponse

The current HtmxResponse instance.

Type Parameters

T

The event detail type.

Examples

var detail = new ProductSaved(product.Id);

Response.Htmx(
    static (htmx, detail) => htmx.TriggerEvent(
        "product-saved",
        detail,
        AppJsonContext.Default.ProductSaved,
        HtmxTriggerTiming.AfterSwap),
    detail);

[JsonSourceGenerationOptions(PropertyNamingPolicy = JsonKnownNamingPolicy.CamelCase)]
[JsonSerializable(typeof(ProductSaved))]
internal partial class AppJsonContext : JsonSerializerContext;

internal sealed record ProductSaved(int Id);

Remarks

In HTMX 4.x, every HtmxTriggerTiming value is emitted through HX-Trigger and runs when the request completes (after the swap whenever one is performed). See PR #3900.

Events are triggered in the order they are added. If an event name is added more than once for the same header, all events of that header are replayed by the Toolkit script, which must be loaded for any of them to be triggered.