This is a viewer only at the moment see the article on how this works.
To update the preview hit Ctrl-Alt-R (or ⌘-Alt-R on Mac) or Enter to refresh. The Save icon lets you save the markdown file to disk
This is a preview from the server running through my markdig pipeline
Friday, 28 November 2025
Jos olet rakentanut perinteisiä ASP.NET Core MVC -sovelluksia, tiedät ongelman: se pelättiin "klikkaa flash", kun käyttäjät navigoivat sivujen välillä. Koko sivun uudelleenlataukset, selaimen kroppa vilkkuu, sisältö hyppii uuden sivun renderöidessä. Se toimii, mutta se ei toimi. tunne modernia.
Tekniikka palauttaa osittainen HTML-fragmentti palvelimelta ja vaihtaa ne DOM:iin ratkaisee tämän - ja se ei ole uutta. Olen käyttänyt tätä kaavaa jQuery-päivistä lähtien, ja sitä ennenkin vaniljalla JavaScript ja XMLHttpRequestSe, mikä on muuttunut, on se, miten tyylikäs Siitä on tullut HTMX:n myötä.
HTMX kertoo meille, miten voimme tehdä sen, mitä olemme aina tehneet: palauttaa palvelimen renderöimän HTML:n ja vaihtaa sen sivulle. Ei enää mukautetun JavaScriptin kirjoittamista jokaiselle vuorovaikutukselle. Ei enää valita "asianmukaisen" palvelimen kehittämisen ja sujuvan käyttökokemuksen välillä. HTMX:n avulla saamme molemmat.
Kumppanuuspykälä: Tämä artikkeli keskittyy ASP.NET Core -integraatiopuolelle. Syvällä HTMX-tapahtumissa, elinkaaressa ja mukautetuissa laajennuksissa katso kumppanini artikkeli: Whistle-stop -kiertue HTMX-laajennuksista ja HTMX:n käytöstä ASP.NET Corella.
Tässä artikkelissa näytän, kuinka HTMX integroituu kauniisti ASP.NET Core -osuuksiin, kuinka erinomainen HTMX.NET kirjasto tekee siitä entistä paremman, ja miten minun Enimmäkseen lucid.paggingtag-auttaja NuGet-paketti käyttää HTMX:ää, joka tarjoaa tehokkaan paginoinnin minimaalisella kokoonpanolla.
Lähestymistapa on myös kehysagnostiikka - Django lisäsi mallikappaleita versioon 6.0, Railsilla on Turbo Frames, ja laajempi verkkoekosysteemi omaksuu HTML-verkkokuvioita. Nyt on hyvä aika rakentaa palvelimen renderöimiä sovelluksia.
HTMX on kirjasto, jonka avulla voit käyttää nykyaikaisia selaimen ominaisuuksia suoraan HTML:stä sen sijaan, että kirjoittaisit JavaScriptia. Se laajentaa HTML:ää attribuuteilla, joiden avulla voit tehdä AJAX-pyyntöjä, vaihtaa sisältöä ja luoda runsaita vuorovaikutussuhteita – kaikki ilman, että jätät marginaalisi.
Avainpiirteet, joita käytät useimmin:
hx-get, hx-post, hx-put, hx-delete - Tee HTTP-pyyntöjähx-target - Määrittele, mihin vastaus laitetaanhx-swap - Valvo, miten sisältöä vaihdetaan (sisältää HTML:n, ulompi HTML:n jne.)hx-trigger - Määrittele, mikä käynnistää pyynnön (napsauta, vaihda, lataa jne.)hx-push-url - Päivitä selaimen URL ilman koko sivun uudelleenlataustaTässä on sen kauneus: kirjoitat edelleen palvelimen sivukoodia, palautat palvelimen renderöidyn HTML:n. Ei JSON-rajapintoja, ei asiakaspohjaisia malleja, ei rakenneta putkistoja. Vain vanhaa kunnon HTML:ää johtojen päälle.
Ennen HTMX:ää saimme aikaan saman vaikutuksen huomattavasti seremoniallisemmin. Tältä osittaiset päivitykset näyttivät jQueryn aikakaudella:
// jQuery circa 2010
$('#load-more').click(function() {
$.ajax({
url: '/posts/page/' + currentPage,
success: function(html) {
$('#posts-container').append(html);
currentPage++;
}
});
});
Ja vielä aiemmin, vaniljalla JavaScript:
// Vanilla JS circa 2005
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (xhr.readyState === 4 && xhr.status === 200) {
document.getElementById('content').innerHTML = xhr.responseText;
}
};
xhr.open('GET', '/partial-content', true);
xhr.send();
Palvelimen sivukuvio oli identtinen – palauta HTML-fragmentit, vaihda ne DOM:iin. HTMX vain siirtää tämän logiikan JavaScriptista HTML-ominaisuuksiin, jolloin se on deklaratiivinen, helposti havaittava ja paljon vähemmän virhealtis. Innovatiivisuus ei ole tekniikka, vaan se on rajapinta.
ASP.NET-kehittäjät ovat tehneet tätä jo vuosia. UpdatePanels in WebForms (2005), PartialView() MVC:ssä ensimmäisestä päivästä lähtien, Html.RenderAction() Kokoontuville sirpaleille - kyky on aina ollut olemassa. Puuttui tyylikäs, vakiomuotoinen tapa kytkeä se asiakaspuolelle. HTMX täyttää aukon täydellisesti.
Myös laajempi teollisuus on löytänyt nämä kuviot uudelleen. Termit kuten "SSR" (Sserver-Side Rendering), "hybridirenderointi" ja "saariarkkitehtuuri" kuvaavat lähinnä sitä, mitä palvelimen puolella on aina tehty, mutta tuorein silmin. Se vahvistaa, että palvelimen renderöimät lähestymisvaa'at, suoritukset ja - oikeilla työkaluilla - tarjoavat erinomaisen käyttökokemuksen.
Sisällytä ensin HTMX asetteluusi. Voit käyttää CDN:ää tai tarjoilla sitä paikallisesti:
<script src="https://unpkg.com/[email protected]"></script>
Ei rakennusvaihetta, ei npm-asennusta, ei webpack-kokoonpanoa.
Asiakaspuolen reaktiivisuus (näyttävät/piilottavat elementit, kihelmöivät valtiot, paikallinen UI-valtio) Alppi.js Täydentää HTMX:ää täydellisesti. Vain 15 KB:n gzippissä se tarjoaa Vue/Reaktin kaltaista deklaratiivista reaktiivisuutta ilman turvotusta.
<script defer src="https://cdn.jsdelivr.net/npm/[email protected]/dist/cdn.min.js"></script>
Näin he toimivat yhdessä:
<div x-data="{ open: false }">
<button x-on:click="open = !open">Toggle</button>
<div x-show="open" x-transition>
<button hx-get="/api/data" hx-target="#results">Load Data</button>
</div>
</div>
Alppi käsittelee paikallista käyttöliittymää (toggle), HTMX käsittelee palvelinpuheluita (data nouto). Tämän artikkelin kautta näet tämän kuvion: Alppi asiakkaiden reaktiivisuuteen, HTMX palvelimen vuorovaikutukseen.
Khalid Abuhakmeh's HTMX.NET Kirjasto tarjoaa ensimmäisen luokan ASP.NET Core -integraation. Htmx sekä Htmx.TagHelpers NuGet paketteja, se tuntuu kotoisin .NET ja tekee työskentelystä HTMX on ehdoton ilo. Löydät lisää Khalidin erinomainen avoimen lähdekoodin työtä hänen GitHub.
dotnet add package Htmx
dotnet add package Htmx.TagHelpers
• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • _ViewImports.cshtml:
@addTagHelper *, Htmx.TagHelpers
Hyödyllisin ominaisuus on Request.IsHtmx() Laajennusmenetelmä kertoo, tuliko pyyntö HTMX:ltä. Näin voit palauttaa joko täydellisen tai vain osittaisen näkymän:
[HttpGet]
public async Task<IActionResult> Index(int page = 1, int pageSize = 20)
{
var posts = await blogViewService.GetPagedPosts(page, pageSize);
if (Request.IsHtmx())
return PartialView("_BlogSummaryList", posts);
return View("Index", posts);
}
Tämä malli on aivan loistava. Yhden ohjaimen toiminto palvelee molempia:
Ei erillisiä API-päätteitä, ei päällekkäistä logiikkaa, ei JSON-sarjausta yläpuolella.
Yleinen harhaluulo: Monet ASP.NET-kehittäjät ovat sitä mieltä, että tarvitset
_etuliite (kuten_BlogSummaryList.cshtml) saada osittainen renderointi.PartialView()Method itse käskee ASP.NET Corea jättämään asettelun väliin - se sanoo: "Unohda asettelu, tee tämä kohta". Voit käyttääreturn PartialView("SearchResults", model)ASP.NET Web Pages (WebMatrix) esti tiedostojen välittämisen suoraan URL-osoitteen kautta, mutta MVC on aina suojellut kaikkia näkökulmia suoralta käytöltä. Kyseessä on puhtaasti nimittelysopimus, joka auttaa tunnistamaan näkymän. aiottu Osittaisina.
HTMX.NET tarjoaa tunnisteavustimia, jotka tekevät ohjainten kanssa työskentelystä puhtaampaa. Reitin narujen kirjoittamisen sijaan voit käyttää vahvasti kirjoitettuja viittauksia:
<button
hx-controller="Comment"
hx-action="GetCommentForm"
hx-post
hx-target="#commentform">
Reply
</button>
Tämä luo oikean reitin käyttäen ASP.NET Coren reititysjärjestelmää. Jos nimeät ohjaimesi tai toimintosi uudelleen, IDE nappaa sen. Paljon parempi kuin taikajouset!
Tässä todellinen esimerkki blogin kommenttijärjestelmästä:
<button
class="btn btn-outline btn-sm mb-4"
hx-action="Comment"
hx-controller="Comment"
hx-post
hx-vals
x-on:click.prevent="window.mostlylucid.comments.setValues($event)"
hx-on="htmx:afterSwap: window.scrollTo({top: 0, behavior: 'smooth'})"
hx-swap="outerHTML"
hx-target="#commentform">
Comment
</button>
Huomaa, miten HTMX pelaa hyvin Alppien kanssa.js (x-on:click.prevent) satunnaisiin asiakaspuolen vuorovaikutuksen osiin.
Kirjastossa on myös:
Request.IsHtmxNonBoosted() - Tarkista onko kyseessä HTMX-pyyntö, mutta ei tehostettuRequest.IsHtmxRefresh() - Tarkista, onko kyse historian palauttavasta pyynnöstäTässä on tämän blogin hakuohjain, joka näyttää kolmiportaisen palautuskuvion:
[HttpGet]
[OutputCache(Duration = 3600, VaryByHeaderNames = new[] { "hx-request", "pagerequest" })]
public async Task<IActionResult> Search(
string? query,
int page = 1,
int pageSize = 10,
[FromHeader] bool pagerequest = false)
{
var searchModel = await BuildSearchModel(query, page, pageSize);
if (pagerequest && Request.IsHtmx())
return PartialView("_SearchResultsPartial", searchModel.SearchResults);
if (Request.IsHtmx())
return PartialView("SearchResults", searchModel);
return View("SearchResults", searchModel);
}
Kolme paluureittiä kolmeen skenaarioon:
Osittainen näkemys (_SearchResultsPartial.cshtml) käyttää hakutunnisteen avustajaa:
@model Mostlylucid.Models.Blog.PostListViewModel
<div class="pt-2" id="content">
@if (Model.Data?.Any() is true)
{
<div class="inline-flex w-full items-center justify-center pb-4">
@if (Model.TotalItems > Model.PageSize)
{
<pager
x-ref="pager"
link-url="@Model.LinkUrl"
hx-boost="true"
hx-target="#content"
hx-swap="show:none"
page="@Model.Page"
page-size="@Model.PageSize"
total-items="@Model.TotalItems"
hx-headers='{"pagerequest": "true"}'>
</pager>
}
</div>
@foreach (var post in Model.Data)
{
<partial name="_ListPost" model="post"/>
}
}
</div>
Hakulaitteen tunnisteen autajan hajottaminen:
hx-boost="true" - Intercepts linkittää, muuntaa AJAXiksihx-target="#content" - Mihin vaste pistetäänhx-headers='{"pagerequest": "true"}' Custom-otsikko kertoo ohjaimelle, että se paginoiRequest.IsHtmx() && pagerequest palauttaa vain minimaalinen osittainenMinä kirjoitin Enimmäkseen lucid.paggingtag-auttaja Se on HTMX-ensin, mutta toimii ilman JavaScriptiakin.
dotnet add package mostlylucid.pagingtaghelper
Lisää _ViewImports.cshtml:
@addTagHelper *, mostlylucid.pagingtaghelper
Toteuta IPagingModel<T> Ja olet valmis:
public class BasePagingModel<T> : IPagingModel<T> where T : class
{
public int Page { get; set; }
public int TotalItems { get; set; }
public int PageSize { get; set; }
public string LinkUrl { get; set; }
public List<T> Data { get; set; }
}
Mitä saat:
Tag-auttaja luo linkkejä, jotka säilyttävät kyselyn narut, tukevat mukautettuja otsikoita ja integroituvat saumattomasti HTMX:ään (ks. esimerkki yllä).
Näin koko järjestelmä sopii yhteen:
graph TB
A[Browser] -->|"Initial page load"| B[Controller Action]
B -->|"Request.IsHtmx() = false"| C[Return Full View]
C --> D[Render Layout + Partial]
A -->|"User clicks pagination/filter"| E[HTMX Request]
E -->|"hx-get with headers"| F[Same Controller Action]
F -->|"Request.IsHtmx() = true"| G{Check Headers}
G -->|"pagerequest header"| H[Return Minimal Partial]
G -->|"No special header"| I[Return Section Partial]
H --> J[Swap Content in Target]
I --> J
J -->|"User clicks another link"| E
style B stroke:#333,stroke-width:2px
style F stroke:#333,stroke-width:2px
style C stroke:#0066cc,stroke-width:2px
style H stroke:#00cc66,stroke-width:2px
style I stroke:#00cc66,stroke-width:2px
Django lisäsi versioon 6.0 (joulukuu 2024) oikean osittaisen mallin, jossa oli mallikappaleita. Sitä ennen Django-kehittäjät käyttivät yleensä sisällystunnisteita tai kolmannen osapuolen pakkauksia, kuten django-render-blokkia. ASP.NET Core on PartialView() versiosta 1.0 lähtien vuonna 2016 - eri kehykset, eri aikajanat, mutta sama kohde: HTML-fragmentit HTMX:lle.
Ruby on Rails on Turbo Frames (osa Hotwire), joka on samanlainen hengessä:
<%= turbo_frame_tag "posts" do %>
<%= render @posts %>
<% end %>
Erona on se, että Turbo tarvitsee erityisiä kehysmerkkejä sekä pyynnöstä että vastauksesta. HTMX on joustavampi - mikä tahansa päätetapahtuma voi palauttaa minkä tahansa HTML:n, ja sinä päätät, mihin se liittyy. hx-target.
Elixirin Phoenix LiveView -ohjelmalla on erilainen lähestymistapa pysyvillä WebSocket-yhteyksillä ja palvelimen puolella:
def handle_event("load_more", _params, socket) do
{:noreply, assign(socket, posts: load_more_posts())}
end
LiveView on loistava reaaliaikaisiin sovelluksiin, mutta se edellyttää WebSocket-infrastruktuuria ja palvelinmuistia yhteyksiä varten. HTMX käyttää pelkkää vanhaa HTTP:tä, joka on kansalaisuudeton, välimuistissa ja skaalattavissa.
Lähtö välimuistiin: OutputCache Ominaisuus vaihtelee hx-request Otsikko, välilyönnillä kokonaiset sivut ja osat erikseen:
[OutputCache(Duration = 3600, VaryByHeaderNames = new[] { "hx-request", "pagerequest" })]
Verkon tehokkuus: Palvelimen renderöimä HTML on usein pienempi kuin JSON + asiakassivupohjat, vaatii vähemmän pyöreitä matkoja ja välimuistit oikein.
Bundlen koko: HTMX (14KB) + valinnainen alppi.js (15KB) + hakutarkkailija (0KB, palvelinpuoli) = alle 30KB yhteensä. Vertaa tätä tyypilliseen React-sovellukseen (200KB+).
Optimistiset UI-päivitykset - Yhdistä HTMX ja Alppi pikapalautteeseen:
<div x-data="{ count: @Model.CommentCount }">
<button hx-post="/comment/like" x-on:click="count++" hx-on::after-request="count = $event.detail.xhr.response">
Likes: <span x-text="count"></span>
</button>
</div>
Laskentapäivitykset välittömästi (optimistinen), sitten synkronoidaan palvelimen vasteen kanssa.
B:n ulkopuoliset swapit - Päivitä useita sivuja yhdestä vastauksesta:
<div id="main-content"><!-- Main response --></div>
<div id="notification-count" hx-swap-oob="true"><span>5 new</span></div>
Täydellinen ilmoitusmerkeille, kärryille jne. Kannan tämän kuvion perinpohjaisesti Näyttää paahtoleivän ja Swapping HTMX:llä.
Asiakassidonnaiset mallit WebAPI:n kanssa - Joskus haluat puolivälin kokemuksen: palvelimen HTML useimmille asioille, mutta JSON WebAPIsta tietyn dynaamisen sisällön vuoksi. HTMX:n Asiakaspuolen laajennus antaa tehdä juuri näin:
<script src="https://unpkg.com/[email protected]/client-side-templates.js"></script>
<script src="https://unpkg.com/mustache@latest"></script>
<div hx-ext="client-side-templates">
<template id="post-template" type="text/mustache">
{{#posts}}
<div class="post">
<h3>{{title}}</h3>
<p>{{excerpt}}</p>
</div>
{{/posts}}
</template>
<button hx-get="/api/posts"
hx-target="#post-list"
mustache-template="post-template">
Load Posts
</button>
<div id="post-list"></div>
</div>
Tämä lähestymistapa toimii Mustache-, Handbars- tai Nunjucks-malleilla. WebAPI palauttaa JSON:n, mutta HTMX hoitaa renderointiasiakaspuolen. Se on erityisen hyödyllistä, kun sinulla on olemassa oleva API tai haluat jakaa dataa mobiilisovellusten kanssa. Lisätietoja HTMX-laajennuksista, mukaan lukien asiakaskohtaiset pohdinnat, ks. seuralaisartikkeli.
Vianetsintätyökalu: Asenna HTMX-debuggerilaajennus - siinä näkyy jokainen pyyntö, vastaus ja vaihto reaaliajassa.
ASP.NET Coren väärennösten vastaiset rahakkeet tarvitsevat erikoiskäsittelyä AJAX:n kanssa. HTMX.NET tarjoaa useita puhtaita vaihtoehtoja. HtmxAntiforgeryScriptEndpoint:
// In Program.cs
app.MapHtmxAntiforgeryScript();
<!-- In your layout head -->
<script src="@HtmxAntiforgeryScriptEndpoints.Path" defer></script>
Tai käytä tag-auttajaa: <meta name="htmx-config" includeAspNetAntiforgeryToken="true" />. Katso Khalidin artikkeli HTMX-väärennösten vastaisesta tokenista täydelliset tiedot.
Alppien @click Shorthand on ristiriidassa Razorin kanssa @ Syntaksi. Käytä sen sijaan nimenomaista lomaketta:
<button x-on:click="doSomething()">Click me</button> <!-- Instead of @click -->
<div x-bind:class="isOpen ? 'block' : 'hidden'"></div> <!-- Instead of :class -->
Tai paeta @@click, mutta selkeä syntaksi on selkeämpi.
Historiatietojen hallinta: Oletuksena on, että HTMX vie kaikki pyynnöt historiaan. Paginointi/suodattimet, joissa ei haluta historiallista saastumista:
<paging model="@Model" hx-push-url="false"> <!-- Don't add history entries -->
Tai käyttää hx-replace-url="true" URL-osoitteen päivittäminen ilman merkintää.
Phantom Osittainen ongelma: Selain takaisin/ eteenpäin näyttää vain osittaisen sirpaleen, jossa ei ole asettelua. hx-history-elt Sisällyspakkaus:
<div class="container mx-auto" id="contentcontainer" hx-history-elt>
@RenderBody()
</div>
Tämä kertoo HTMX:lle, mikä elementti kuvaan, säilyttäen ympäröivän layoutin historian palauttamisessa.
Oireet: HTMX toimii paikallisesti, mutta hajoaa CDN:n taakse - väärää sisältöä välimuistiin.
Perussyy: CDN-koodit eivät huomioi HX-Request Otsikko. Palvelimesi palauttaa eri sisältöä tämän otsikon perusteella, mutta CDN välimuistit ovat identtiset.
ASP.NET Core fix: Käyttö VaryByHeaderNames:
[OutputCache(Duration = 3600, VaryByHeaderNames = new[] { "hx-request" })]
CDN-korjaus: Määrittele välimuistisäännöt mukaan lukien HX-Request välimuistin avaimessa. Cloudflare: Dashboard → Caching → Cache Rules → Custom cache key → Headers → Include HX-Request.
hx-boost Muuttaa normaalit linkit AJAX-pyynnöiksi. HTMX:n omituinen sivu toteaa, että jotkut ydintiimin jäsenet suosittelevat välttämään sitä (hylkäykset <head> sisältöä, vaikuttaa käyttäytymisen paikallisuuteen), kun taas toiset pitävät pikavoittoja hienoina.
<div hx-boost="true" hx-target="#contentcontainer">
<a asp-action="Show" asp-route-slug="@post.Slug">Read More</a>
</div>
Tämä blogi käyttää sitä laajasti. Kun kohdistat tiettyjä kontteja, selkeä hx-get on selkeämpi, mutta hx-boost Toimii, jos olet johdonmukainen. hx-boost="false" lapsielementeistä.
HTMX, jossa on ASP.NET Core -ositteet, on paluu palvelinpuolen yksinkertaisuuteen uhraamatta modernia UX:ää. Saat:
Palvelimen hioma lähestymistapa on kestänyt ajan kokeen, ja HTMX:n avulla sillä on vihdoin se tyylikäs asiakaspuolen työkalu, jonka se ansaitsee. Voit rakentaa vankkoja, performantteja verkkosovelluksia, joissa on käytetty vuosikymmeniä toimineita malleja - ne ovat vain odottaneet oikeaa työkalua, jolla ne saadaan loistamaan uudelleen.
Tämä artikkeli on osa kaksiosaista sarjaa HTMX:stä ASP.NET Corella:
Virallinen asiakirja:
Kirjastot ja työkalut:
Yhteisön varat:
© 2026 Scott Galloway — Unlicense — All content and source code on this site is free to use, copy, modify, and sell.