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
HTMX 与 ASP.NET 核心部分@:服务器 @-Side复兴
Friday, 28 November 2025
一. 导言导言 导言 导言 导言
如果您已建立传统的 ASP.NET 核心 MVC 应用程序@, 你知道问题是什么吗? 当用户在页面之间浏览时, 感觉 现代的.
从服务器上返回部分 HTML 碎片并将其转换为 DOM 的方法解决了这个 - 。 自 jQuery days ,}(甚至在此之前)与 Vanilla JavaScript 和 XMLHttpRequest@. @ what' @% 改变的是如何 优雅 与HTMX和.成为一体
HTMX 给了我们一种宣示性的方式来做 我们一直做的 @:\Q returned HTML 并把它转换到页面@.}不再为每次互动量写自定义 JavaScript *#. 没有更多的选择
附录 条款 本篇文章的焦点是 ASP.NET 核心整合面@. 深入潜入 HTMX 事件\ , 生命周期 @, 和自定义扩展@MS K4 见我的配套文章_: HTMX扩展和以 ASP=.NET 核心使用HTMX.
在本篇文章中, , @ I'}会向您展示HTMX是如何与 ASP=.#NET Core parts@,}如何完美融合的。 HTMX.NET 库里让它变得更好 @,#和我的 多数是卢比多的.+#pangging帮手 NuGet 软件包使用 HTMX 提供极强的射程,最小配置@.
这个方法是一个框架 -QQAnostic too @-Jjango 在版本“6.0,铁路”中添加了模板碎片。 而更广泛的网络生态系统包含 HTML-Over}--MS K6Wirtimation_.}它是一个建造服务器的好时机 ~-Reed application@.}
什么是HTMX ??
HTMX 是一个允许您直接从 HTML\ @,}(而不是写入 JavaScript}.}) 访问现代浏览器功能的图书馆。 它扩展了 HTMl, 包含一些属性, 可以让 AAX 请求@ ,} 互换内容@ MPK3 并创建丰富的互动 {% -} 全部不离开您的标记=.}
您'}最常使用的密钥属性@ :}{
hx-get,hx-post,hx-put,hx-delete@- 满足 HTTP 请求hx-target- 指定将回复放在何处hx-swap-控制内容如何互换@(innerHTML,}外 HTML□,等hx-trigger@ -_ 定义什么触发请求@ MS K1_ klick\ ,} change @ MPK3load @ MASK4 etc.hx-push-url\ - 更新浏览器 URL, 不重新装入整页
这里的'是它的美景 您 @ ' 仍在寫入伺服器@ MS K3side code\ , returninged HTML.}沒有 JSON APIS, 沒有用戶{-s sideplatesuble}MS K9没有建管
象AJAX自己一样老的模式
在HTMX,}之前,我们取得了同样的效果 举行了更多的仪式...
// jQuery circa 2010
$('#load-more').click(function() {
$.ajax({
url: '/posts/page/' + currentPage,
success: function(html) {
$('#posts-container').append(html);
currentPage++;
}
});
});
更早的,和香草 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();
服务器“-”的侧边图案是相同的 @-}返回 HTML 片段@,} 将它们转换为 DOMQ.HTMX 只是把这个逻辑从 JavaScript 移动到 HTMl 属性, 使它成为声明性=, 发现#, 和远小错误 <-}.} 这个创新就是"'}Technology_; it{'}作为界面=MS K12}
ASP.NET 开发商已经这样做多年了 在WebForms & (2005),}网络格式中更新的平台 PartialView() 从第一天起,在MVC , Html.RenderAction() 我们所缺少的是一种优雅的, 标准的方式 在客户端连接它\ .\ HTMX填补了这个空白
更广大的产业正在重新发现这些图案, 例如 @"@SSRQZK2}(Server-}♪SideRendering}),{"Hybrid Maturation",}和MS K8岛架构"基本上描述了服务器 <,> -边框一直做了些什么? 但有新鲜的眼睛*. ItMSG13}验证 服务器=-Reed 方法“,}用正确的工具‘-}提供出色的用户经验<.〞
在 ASP=.NET 核心中设置 HTMX
第一个, 包含 HTMX 到您的布局@ . 您可以使用 CDN 或者在本地端服务\ MS K2
<script src="https://unpkg.com/[email protected]"></script>
{\fn黑体\fs22\bord1\shad0\3aHBE\4aH00\fscx67\fscy66\2cHFFFFFF\3cH808080}你只要放下一个脚本标签 {\fn方正准圆简体\fs12\1cHC9ECC4}然后你就跑到赛马场去
AlpineMS.js:客户端MS K2Side 组件
客户端@- @side reactivity *%sK1_sshowing /}元素\ , 以切换状态,}本地的 UI stateQ, 阿尔卑斯山 提供Vue @/React@-}类似声明性反应,没有上下浮Q.
<script defer src="https://cdn.jsdelivr.net/npm/[email protected]/dist/cdn.min.js"></script>
这里:'}他们是如何合作的?
<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>
Alpine 处理本地 JUI @ ( @ tgggle),} HTMX 处理服务器呼叫@ MS K2} 数据抓取\ ). {
HTMX.NET 库
哈立德·阿布哈克梅# '# HTMX.NET 库中提供第一个“-”类 ASP.“NET 核心集成@.” Htmx 和 Htmx.TagHelpers NuGet 套件@, @ @ it feel native to @ .NET, 让HTMX的工作非常令人愉快: @._ You'}你能找到更多Khalid{'}[哈立德】MSK4#s 优秀的开放=-}来源工作 吉特胡布.
安装装置
dotnet add package Htmx
dotnet add package Htmx.TagHelpers
在你的 _ViewImports.cshtml:
@addTagHelper *, Htmx.TagHelpers
IsHtmx @ ()}扩展方法
最有用的特征是: Request.IsHtmx() 扩展方法@, 用于告知您请求是否来自 HTMX.}这样可以让您返回一个完整的视图或仅部分@ :
[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);
}
此模式绝对辉煌 @ . 单一个控制器操作可同时为@ :服务
- 当用户直接导航或刷新时,全页加载@ ( @% 1}
- 当HTMX提出要求时, 部分更新@( @% 1}
没有单独的 API 端点@, @没有重复的逻辑\ ,}无 JSON 序列连接管理 *.
一种常见的误解 : 许多 ASP.NET 开发者认为您需要
_前缀 @ (@ like_BlogSummaryList.cshtml{\fn黑体\fs22\bord1\shad0\3aHBE\4aH00\fscx67\fscy66\2cHFFFFFF\3cH808080}PartialView()方法本身告诉 ASP.NET 核心跳过布局@ - itMS K2s saying @ "}♪ forget the 布局 , 仅仅让这个位数=".可以使用return PartialView("SearchResults", model)校对:Portnoy 预定 占部分@ . @
HTMX.NET 标签辅助工具
HTMX.NET 提供标签助手,与控制器一起工作\ . 而不是写入路线字符串@, 您可以使用强烈的 @-}%styped review_:
<button
hx-controller="Comment"
hx-action="GetCommentForm"
hx-post
hx-target="#commentform">
Reply
</button>
如果您重命名您的控制器或动作“,” 您的 IDE 将会抓住它 .\ 大大胜过魔法字符串@!+#
@'_@service system=:}在此,
<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>
注意HTMX如何与阿尔卑斯山发挥优雅,x-on:click.prevent) 用于客户端的偶发位数 @-}侧面互动@.
其他 HTMX.NET 助手
图书馆也提供@: @
Request.IsHtmxNonBoosted()- 检查它是否为 HTMX 请求, 但并未提升Request.IsHtmxRefresh()- 检查它是否为历史恢复请求- HTMX 信头的响应帮助 @ ( @ triggers@ MS K1 @ refreeds @ I, @ etc_ .)}
使用部分搜索@ label
这里'%s 是来自此博客的搜索控制器 {,} 显示三MS K2\tier return status@ :}
[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);
}
三种假想的三个返回路径@: @%
- 微小部分 ( 仅列出结果列表 @)
- 过滤器更改 #% - @ 区域部分 # MS K1 导致过滤器@ )}
- 直接导航@- @全页 @(_布置#+}所有东西 @MS K3
部分视图 @( @%_SearchResultsPartial.cshtml@)# 使用传呼标签帮助器@:}
@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>
正在拆分呼叫器标签帮助@ : @
hx-boost="true"- 截取链接@, 转换为 AJAXhx-target="#content"- 填入回复的方位hx-headers='{"pagerequest": "true"}'- 自定义信头告诉控制器 it's pagenation- 控制器检查
Request.IsHtmx() && pagerequest仅返回最小部分
多数为lucid @ .}paggingtag帮手套件
我写过 多数是卢比多的.+#pangging帮手 避免重复页码@. @ it'}HTMX#-}首先但工作没有 JavaScript too_.}
安装装置
dotnet add package mostlylucid.pagingtaghelper
添加到 _ViewImports.cshtml:
@addTagHelper *, mostlylucid.pagingtaghelper
密钥特征
执行 IPagingModel<T> {\fn黑体\fs22\bord1\shad0\3aHBE\4aH00\fscx67\fscy66\2cHFFFFFF\3cH808080}而你又完成了
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; }
}
你得到了什么? :
- 需要零配置
- 多个 UI 框架 @ (TailwindCSCS @ MPK1 DisiUí,Bootsstrap {5,自定义视图@)}
- 暗模式支持
- @8 @ 语言已建立@-_in
- 可排序标题@, @}页面大小选择器
- 没有 JavaScript\ ) 的渐进增强@ ( @ work
- 继续给 NoSQL 数据库的象征性支持
标签助手生成链接, 以保存查询字符串@ , @ 支持自定义信头 @ MS K1} 并且与 HTMX {(} 无缝融合。 请参见上例).}
HTMX 流程图
这里#' @_%s 整个系统是如何搭配起来的 200)}:}@MSK1
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 模板碎片
Django 添加了适当的部分模板, 在版本中提供 @6.0 @ @ ( @ 12 @ I2024)} 并配有模板片段@ ._ 强哥开发商之前通常使用包含标签或第三方@-}政党套件, 如 Django- render-block @ MPK8} ASP=.NET Core PartialView() 不同的框架 @,}不同的时间轴@,}但同一目的地 HTMX=.}的HTMX#MSK6*
涡轮框架
Ruby on Rails有Turbo框架@(部分的热电路 @),}这在精神上是相似的_:
<%= turbo_frame_tag "posts" do %>
<%= render @posts %>
<% end %>
不同之处在于,涡轮在请求和响应时都需要具体的框架标记@.HTMX更灵活 @-任何终点都可以返回 HTML,。 hx-target.
凤凰实况影视
Elixir 'Phoenix Life LiveView采取不同的方法,使用持续的网络软盘连接和服务器@-side state @:#
def handle_event("load_more", _params, socket) do
{:noreply, assign(socket, posts: load_more_posts())}
end
LiveView 对真实的 @-#time application@,}来说是辉煌的实况,但是它需要网络软盘基础设施和服务器内存来连接 .HTMX使用普通的旧 HTTP {-Natistrial_,}%,}缩放}.}(对于一个博客 ,}这“'’s perfect=.〞
业绩考量
输出缓存# :# OutputCache 属性因 hx-request 标题@ , @ cacheing full page and parts 分开的整页和部分@ I:} @
[OutputCache(Duration = 3600, VaryByHeaderNames = new[] { "hx-request", "pagerequest" })]
网络效率:Server-sended HTML通常小于 Jsonon @+}客户端@-sides studiple{,}需要较少的往返旅行}%,}和适当的缓存=.}
套装大小:+HTMX @(14QKBK2+++可选的 [email protected] @MS K5KB#)}++呼叫标记助手 @(0+KB,}伺服器 @MSC10QSideZ)+=+在「30KB 总计=.+和典型的反应应用<(200>相比
高级模式
乐观的用户界面更新 -集HTMX和阿尔卑斯山为即时反馈}:
<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>
立即更新计数@ ( @ optimetic=),}然后与服务器响应@ MPK2同步
外边的-of-Band Swaps @- 更新一份回复的多页部分@:
<div id="main-content"><!-- Main response --></div>
<div id="notification-count" hx-swap-oob="true"><span>5 new</span></div>
符合通知徽章的完美标准@,马车计数 @,}等等#.我深入覆盖了这个图案 使用 HTMX 显示通吐和互换.
使用 WebAPI 的客户端-Side模板 ,}但来自WebAPI的JSON 用于特定动态内容*.HTMX's 客户端-side-templates 扩展 让您来做这个:吧
<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>
此方法与 Mustache @ , @ handlebars@ ,} 或 Nunjucks 模板@ MS K2} 您的 WebAPI 返回 JSON, 但 HTMX 处理着客户端“ - @ sideMSKO5” It{'} 当您已有 API 或者需要与移动应用程序共享数据时特别有用, 请查看 HTM X 扩展的更多细节, 包括客戶端@ MPK8sideMSSK9_ templates@,} 随带的物品,.
加起来的“ &” 提示
调试工具@: @% 安装 HTMX 调试器扩展 @- @ it show every request ,}回应@, @ and sywitch in real @MS K3_time. @
CSRF 代号
ASP=.NET Core'需要使用 AAX}.HTMX.Net 提供几种干净的选项@.}推荐方式的使用 HtmxAntiforgeryScriptEndpoint:
// In Program.cs
app.MapHtmxAntiforgeryScript();
<!-- In your layout head -->
<script src="@HtmxAntiforgeryScriptEndpoints.Path" defer></script>
或使用标签助手@: @% <meta name="htmx-config" includeAspNetAntiforgeryToken="true" />. 见 Khalidó' @s 有关HTMX Anti-@reggery Tokens的文章 完整详细信息@. @%
在 Razor 的 AlpineMSMK0js @ @短手
阿尔卑斯山 @click 与 Razor' @%s 的短手冲突 @ syntax@ . @ 使用明确的表单代替\ :}
<button x-on:click="doSomething()">Click me</button> <!-- Instead of @click -->
<div x-bind:class="isOpen ? 'block' : 'hidden'"></div> <!-- Instead of :class -->
或与 @@click@,}但明确的语法更清晰 ∮.∮
历史管理
控制历史条目@: @% 默认情况下, , HTMX 将每个请求都推向历史@ MS K1 用于 pagenation @ /{ filter 您不想要历史污染@ MPK4}
<paging model="@Model" hx-push-url="false"> <!-- Don't add history entries -->
或使用 hx-replace-url="true" 更新 URL 不添加条目@. @%
幻影部分问题 返回浏览器后端@ / @ forward 只显示一个部分碎片, 没有布局@ .} fix with hx-history-elt 容器内容上的“:”
<div class="container mx-auto" id="contentcontainer" hx-history-elt>
@RenderBody()
</div>
这告诉 HTMX 恢复历史时要保存周围布局的哪个元素
CDN Caching @(_Cloudflare@,}等等 .)
症状: : HTMX 在本地工作, 但是在 CDN -\ 错误内容后面被打破时会缓存@.\ @
根原因@: @% CDN 忽略 HX-Request 您的服务器返回基于此信头的不同内容, 但 CDN 以相同的方式缓存@ .}
ASP.NET 核心固定@: 使用 VaryByHeaderNames:
[OutputCache(Duration = 3600, VaryByHeaderNames = new[] { "hx-request" })]
CDN 修正@: @% 要包含的配置缓存规则 HX-Request 在缓存密钥“% . ” 中,您可以使用 Cloudflare @: Dashboard *→ 抓取 # MS K3 缓存规则@→ 自定义快取密钥 “→ headers @→}包含 HX-Request.
hx=-}启动辩论
hx-boost 将正则链接转换为 AJAX 请求@. @The HTMX 奇格页面 一些核心团队成员建议避免, @(discard <head> @, 影响行为发生地点@),,
<div hx-boost="true" hx-target="#contentcontainer">
<a asp-action="Show" asp-route-slug="@post.Slug">Read More</a>
</div>
这个博客广泛使用@.当瞄准特定容器时 @,明确 hx-get 更清晰的“,”但 hx-boost 如果您在 & ' @ re concolance *.% 禁用有选择的 hx-boost="false" 关于儿童元素的.
结论结论
带有 ASP.NET 核心部分的 HTMX 代表着返回服务器\ -}=side simple
- 动态,SPA-类似互动
- Server - @side 翻譯@(_great 表示 sEO)}
- 正确的 HTTP缓存
- 最小化 JavaScript
- 逐步加强
- 使用 HTMX#.NET 类型@-}安全路由
- Zero- config passiation 与 mostlucidMS K1pangtag helper
服务器“-”的发送方式经受了时间的考验。 HTMX@,}它终于有了优雅的客户端“MS K3”的辅助工具,值得您使用 “.”来建立坚固的网络应用程序。
本博客上的相关文章
随带条款
此篇文章是 HTMX 与 ASP @.}NET Core: 的两集中的一部分。
- 本条本条 @- 聚焦于 ASP.NET核心整合@,部分观点 @MS K3}HTMX.NetMSKO5和页码
- HTMX 扩展的口哨服务 - 深潜到 HTMX 事件@, 寿命周期 @, 扩展架构_, 和自定义延伸
更多HTMX文章
- 添加 HTMX 的呼叫 有关用老PiginationTagHelfer实施页码的原始文章
- ASP.NET 核心缓存与 HTMX hTMX 请求的缓存策略中深潜
- 使用阿尔卑斯山和HTMX的自动-refresh - 将阿尔卑斯山与HTMX结合用于反应组件
- 使用 HTMX 使您的站点更像 SPA @ - - SPA- 类似没有 JavaScript 框架的导航
- HX 指标使用 SweetAlert 使用 HTMX 的漂亮装货指标
- 使用 HTMX 显示通吐和互换 @ -_ 服务器@ MS K1_ 触发吐司通知
继续阅读
正式文件_:
- HTMX文件文档 官方HTMX文件
- HTMX 示例 HTMX模式的实例
- HTMX 扩展 -官方 HTMX 扩展
- AlpineMSMK0js 文档 -官方阿尔卑斯山 MS K1js docs
- AlpineMS.js 示例 “-实用阿尔卑斯山 .js模式”
- ASP=.NET核心部分意见 微软'}部分意见指南
- ASP.NET 核心输出缓存 -官方缓存文件
圖書館&工具MS K1
- HTMX.NET 吉特Hub -HTMX.NET图书馆源代码
- HTMX.NET NUGet @-_HTMX.NET 在 Nuget 上
- Htmx @ MSMK0Tag帮助者 Nuget - HTMX 在 Nuget 上的标签助手
- Khalid Abuhakmeh_'网站 HTMX.NET},}以优秀的博客文章,
- Khalid Abuhakmeh@' @s GitHub @-BARBAR 更辉煌的开放@-}来源 @MS K2#NET项目
- 平铺工帮手 GitHub \ - my page 标签助手源代码
- 大部分是卢比多的.+#paggingtag helper NuGet -NuGet 上的软件包
社区资源@: