该技能面向 Umbraco 17 的服务端渲染前端开发,重点讲解如何基于 ASP.NET Core MVC 与 Razor 构建内容页面。其核心观点是:Umbraco 将每个内容页面请求匹配到内容节点,再路由到控制器(默认是 RenderController,也可劫持它),最后由节点的模板(Razor 视图)渲染。
【用途与构建块选型】技能按需求给出构建块选择指南:为文档类型页面提供标记或共享页面外壳时,使用模板加母版布局;只需要格式化传入模型的复用标记时,使用局部视图;带自身逻辑或注入服务的可复用部件,使用视图组件;页面需要节点之外的数据(外部 API、分页、按请求逻辑)或按模板切换视图时,使用路由劫持(RenderController 加视图模型);按内容页面接收表单 POST 时,使用 Surface 控制器;JSON 或 REST 端点不属于模板范畴,应使用普通 ASP.NET Core 控制器。总体原则是选用能完成任务的最轻量构建块,顺序为模板、局部视图、视图组件、劫持控制器;查询其他内容不需要劫持,模板或视图组件即可完成。单个页面常组合多个构建块。
【使用方式与注意事项】技能强调编码前先打开所用构建块的参考文档并从其资产起步,因为 Umbraco 17 的特有陷阱只在那里说明,例如劫持的 Index 重载会抛出 AmbiguousMatchException,带 *Async 的 Surface 动作名无法路由。新模板必须在 Umbraco 中注册并分配给文档类型后才会渲染,否则页面 404。每个构建块完成后都要执行构建并请求实际用到它的页面来验证,并先检查 Umbraco:CMS:ModelsBuilder:ModelsMode:为 Nothing 或 SourceCode 时使用 dotnet build -p:RazorCompileOnBuild=true(默认 csproj 将 RazorCompileOnBuild 设为 false,普通构建不会编译视图);为 InMemoryAuto(默认)时生成模型仅存在于运行时,此时用普通 dotnet build 加页面请求验证,不要更改用户的 ModelsMode 或重写视图来让 Razor 构建通过。若无可用可运行项目,应如实说明而不是声称可用。
【最佳实践】视图只负责渲染,不获取数据,视图内不得使用 IContentService 或 IMediaService;性能陷阱参见同级技能 umbraco-common-pitfalls。仅使用异步渲染:<partial>、await Html.PartialAsync、await Component.InvokeAsync,禁止 Html.Partial 或 Html.RenderPartial。使用类型化取值 @(Model.Value<T>("alias")) 或 ModelsBuilder 生成的属性,注意 @(...) 必需,富文本转换为 IHtmlEncodedString 可直接渲染,切勿对编辑器字符串使用 Html.Raw。母版布局应保持泛型类型(UmbracoViewPage 或共享接口),否则使用自定义视图模型的劫持页面在布局绑定时会抛错。
【版本与验证】技能面向 Umbraco 17,资产在 Umbraco.Cms 17.5.3 上可编译渲染;在 Umbraco 18 上 PublishedContentWrapped 只接受 IPublishedContent,需去掉视图模型中的回退参数。Umbraco 17 文档中部分代码片段是 v8 时代产物,无法在 17 上编译运行,文档与资产冲突时以资产为准。客观断言位于 evals/evals.json,可用 umbraco-skill-evaluator 运行;所有资产都经运行时门禁断言(examples/render-pipeline/ 空白宿主),通过 HTTP 校验劫持路由、查询绑定、属性回退、视图组件和两条表单提交路径。