Getting started
htmx.NET gives ASP.NET Core two packages for htmx 4. This page takes you from an empty project to a working htmx interaction with antiforgery protection.
| Package | Purpose |
|---|---|
Htmx |
Request detection (IsHtmx(), HtmxRequestHeaders) and response header helpers (Response.Htmx(...)). |
Htmx.TagHelpers |
Razor tag helpers (htmx-config meta, URL generation, hx-headers-*) and the antiforgery script. |
1. Install
Section titled “1. Install”While 2.x is in preview, add --prerelease (NuGet skips pre-release versions otherwise):
dotnet add package Htmx --prereleasedotnet add package Htmx.TagHelpers --prereleaseBoth target net8.0 and net10.0. Htmx works in any ASP.NET Core app (minimal APIs, MVC, Razor Pages); Htmx.TagHelpers needs Razor (MVC views or Razor Pages).
2. Add htmx 4 to your page
Section titled “2. Add htmx 4 to your page”Vendor the file (recommended; the sample keeps it in wwwroot/lib/htmx/htmx.min.js) or use a CDN:
<script src="https://unpkg.com/htmx.org@4.0.0/dist/htmx.min.js" defer></script>3. Configure Program.cs
Section titled “3. Configure Program.cs”From samples/Htmx4.Sample/Program.cs:
using Htmx.TagHelpers;
var builder = WebApplication.CreateBuilder(args);builder.Services.AddRazorPages();builder.Services.AddControllers();builder.Services.AddAntiforgery();
var app = builder.Build();
app.UseStaticFiles();app.UseRouting();app.UseAntiforgery();
// serves /_htmx/antiforgery.jsapp.MapHtmxAntiforgeryScript();app.MapRazorPages();app.MapControllers();
app.Run();4. Register the tag helpers
Section titled “4. Register the tag helpers”Pages/_ViewImports.cshtml (or Views/_ViewImports.cshtml):
@using Htmx@addTagHelper *, Htmx.TagHelpers5. Layout <head>
Section titled “5. Layout <head>”@using Htmx.TagHelpers<meta name="htmx-config" includeAspNetAntiforgeryToken="true" /><script src="~/lib/htmx/htmx.min.js" defer></script><script src="@HtmxAntiforgeryScriptEndpoints.Path" defer></script>- The
htmx-configmeta is rendered by the config tag helper.includeAspNetAntiforgeryTokenembeds the antiforgery token so htmx requests can send it. Keep it before the htmx script. - The script served by
MapHtmxAntiforgeryScript()attaches that token toPOST/PUT/PATCH/DELETErequests. See Antiforgery.
6. A first end-to-end example
Section titled “6. A first end-to-end example”A button that loads a server-rendered fragment, plus a form that saves and fires a client event.
Pages/Products.cshtml:
@page@model ProductsModel
<h1>Products</h1>
<!-- GET: the URL comes from the page handler via the tag helper --><button hx-get hxn-page="/Products" hxn-page-handler="List" hx-target="#list">Load</button><ul id="list"></ul>
<!-- POST: antiforgery token is attached automatically --><form hx-post hxn-page="/Products" hxn-page-handler="Add" hx-target="#list" hx-swap="beforeend" hx-on:product-added="this.reset()"> <input name="name" required /> <button>Add</button></form>Pages/Products.cshtml.cs:
using Htmx;using Microsoft.AspNetCore.Mvc;using Microsoft.AspNetCore.Mvc.RazorPages;
public class ProductsModel : PageModel{ private static readonly List<string> Items = ["Chai", "Chang"];
// the full page public void OnGet() { }
public IActionResult OnGetList() { // direct visits get the full page if (!Request.IsHtmx()) return RedirectToPage(); // cache-safe: Vary: HX-Request Response.Htmx(h => h.WithVary()); return Content(string.Concat(Items.Select(i => $"<li>{i}</li>")), "text/html"); }
public IActionResult OnPostAdd(string name) { Items.Add(name); // HX-Trigger -> reset the form Response.Htmx(h => h.WithTrigger("product-added")); return Content($"<li>{System.Net.WebUtility.HtmlEncode(name)}</li>", "text/html"); }}What happens: clicking Load sends GET /Products?handler=List with HX-Request: true; the <li> fragment replaces the list contents. Submitting the form sends POST with the antiforgery token, appends the new <li> (beforeend) and the product-added event resets the form.
Where next
Section titled “Where next”| I want to… | Read |
|---|---|
| Detect htmx, boosted, partial vs full | Request detection |
| Steer htmx from the server | Response headers |
| Fire client events | Triggering events |
| Change htmx settings | Config tag helper |
| Generate URLs from routes | URL tag helper |
| Send custom headers | Headers tag helper |
| Protect POST/PUT/PATCH/DELETE | Antiforgery |
| Multi-target and morph swaps | Partials and morph |
| Cache correctly | Caching |
| Browse working demos | Samples |
Run the full sample with dotnet run --project samples/Htmx4.Sample.
From the blog: HTMX With ASP.NET Core walks through the library and NuGet packages end to end.