Title here
Summary here
[StreamRendering]
) Issues with HTMXThis guide covers common problems developers might encounter when using Rizzy and provides steps to diagnose and resolve them. Before diving into specific issues, always ensure you’ve checked:
HX-Request
), and response content/headers.Symptoms:
hx-get
/hx-post
does nothing.Diagnosis & Solutions:
AppLayout.razor
or similar) before any elements try to use hx-*
attributes. Check the browser console for errors related to HTMX loading.hx-get
, hx-post
, etc. Does it exactly match a defined route in your ASP.NET Core application (MVC action or Minimal API endpoint)? Pay attention to leading slashes (/
) and case sensitivity if applicable.hx-*
attribute (hx-post
) match the method expected by your server endpoint ([HttpPost]
, MapPost
)?MapControllers()
, MapGet()
, MapPost()
, etc.) in Program.cs
.Symptoms:
Diagnosis & Solutions:
PartialView<YourComponent>()
or similar Rizzy result.hx-target
: Is the CSS selector in hx-target
correct and does it uniquely identify an element already present in the DOM before the swap occurs? Use the browser’s element inspector to verify the selector. Common mistakes include typos or targeting an element that doesn’t exist yet.hx-swap
: Is the hx-swap
style appropriate? innerHTML
(default) replaces the content inside the target, while outerHTML
replaces the target element itself. Other styles (beforeend
, afterend
, etc.) insert content relative to the target. Ensure the chosen style matches how your returned HTML fragment is structured. See SwapStyle docs.Symptoms:
Diagnosis & Solutions:
app.UseAntiforgery()
is present in Program.cs
and placed after app.UseRouting()
and any authentication/authorization middleware (app.UseAuthentication(); app.UseAuthorization();
).<AntiforgeryToken />
inside your Blazor EditForm
.RizzyConfig.AntiforgeryStrategy = AntiforgeryStrategy.GenerateTokensPerPage;
in Program.cs
.<HtmxAntiforgeryScript />
in your main layout (AppLayout.razor
). This component injects JavaScript that automatically adds the necessary token to HTMX requests based on the configuration in the htmx-config
meta tag.htmx-config
meta tag (rendered by <HtmxConfigHeadOutlet />
) contains the correct antiforgery
configuration (header name, form field name, cookie name). See HTMX Configuration.[ValidateAntiForgeryToken]
Attribute: Ensure the controller action or Minimal API endpoint being called has the [ValidateAntiForgeryToken]
attribute (or uses convention-based filters if configured globally)..AspNetCore.Antiforgery.*
) is present.Symptoms:
ModelState.IsValid
is false).Diagnosis & Solutions:
<EditForm Model="@YourModel">
?<DataAnnotationsValidator />
placed inside the EditForm
?<RzInitialValidator />
placed inside the EditForm
(usually right after DataAnnotationsValidator
)? This component is crucial for transferring ModelState
errors to the EditContext
.<RzValidationMessage For="@(() => YourModel.PropertyName)" />
for field-specific messages?<RzValidationSummary />
for a summary?<div class="validation-message field-validation-error" ...>Your error</div>
)?ModelState
Propagation: Are you using RzController
or IRizzyService
methods (View<T>
, PartialView<T>
)? These automatically pass ModelState
down. If you are manually rendering, ensure you pass the ModelStateDictionary
as a parameter to RzPage
or RzPartial
.aspnet-validation.js
included with RizzyUI/Rizzy or jQuery Unobtrusive Validation).RzInput*
components are generating the necessary data-val-*
attributes (inspect the rendered HTML). This relies on DataAnnotationsProcessor
and having Data Annotation attributes ([Required]
, etc.) on your model.Symptoms:
Diagnosis & Solutions:
Program.cs
, ensure:config.RootComponent = typeof(HtmxApp<YourAppLayout>);
config.DefaultLayout = typeof(HtmxLayout<YourMainLayout>);
(Replace YourAppLayout
and YourMainLayout
with your actual layout component types). These wrappers are essential for detecting HTMX requests and suppressing the full layout rendering. See Getting Started.HX-Request: true
header in the Network tab. If not, HTMX isn’t making the request correctly, or something is stripping the header.PartialView<YourComponent>()
from your controller/endpoint for partial updates? While View<YourComponent>()
should also work correctly with the HtmxLayout
wrapper, PartialView
is generally preferred for fragments as it explicitly uses an empty layout by default.Symptoms:
Diagnosis & Solutions:
hx-swap-oob="true"
(or other swap styles) attribute? These are the OOB elements.id
attribute of the OOB element in the response match the id
of an element already present in the main document before the swap happens? OOB swaps target existing elements by ID.<HtmxSwapContent />
Present: Have you included the <HtmxSwapContent />
component somewhere in your main layout (e.g., AppLayout.razor
)? This component is responsible for rendering content added via the IHtmxSwapService
. See Out of Band Swapping.IHtmxSwapService.AddSwappableComponent
, AddSwappableFragment
, etc., during the HTMX request lifecycle.[StreamRendering]
) Issues with HTMXSymptoms:
[StreamRendering]
loads initially via HTMX, showing a placeholder (“Loading…”).Diagnosis & Solutions:
hx-ext="rizzy-streaming"
to a high-level element, typically the <body>
tag in your main layout (AppLayout.razor
)? This extension is required to coordinate Blazor’s streaming updates with HTMX swaps. See Streaming Rendering with HTMX.rizzy-streaming
extension.If you’ve worked through these steps and are still facing issues: