Umbraco Surface Controller疑问及动态按钮实现咨询
Umbraco Surface Controller 问题与动态按钮实现咨询
一、Surface Controller 404 问题
我刚接触Umbraco,对Surface Controller文档中的黄色高亮语句存在疑问。
以下是我的代码:
using Microsoft.AspNetCore.Mvc; using Umbraco.Cms.Core.Cache; using Umbraco.Cms.Core.Logging; using Umbraco.Cms.Core.Routing; using Umbraco.Cms.Core.Services; using Umbraco.Cms.Core.Web; using Umbraco.Cms.Infrastructure.Persistence; using Umbraco.Cms.Web.Common.Attributes; using Umbraco.Cms.Web.Common.Controllers; using Umbraco.Cms.Web.Website.Controllers; using UmbracoTest.Infrastructure; using UmbracoTest.Model; namespace UmbracoTest.Controllers { public class SectionOptionsController : SurfaceController { public SectionOptionsController(IUmbracoContextAccessor umbracoContextAccessor, IUmbracoDatabaseFactory databaseFactory, ServiceContext services, AppCaches appCaches, IProfilingLogger profilingLogger, IPublishedUrlProvider publishedUrlProvider) : base(umbracoContextAccessor, databaseFactory, services, appCaches, profilingLogger, publishedUrlProvider) { } [HttpPost] public async Task<IEnumerable<DummyModel>> GetAllDataFromDBAsync() { //returns list of data } } }
使用Postman调用接口 https://localhost:44327/Umbraco/surface/SectionOptions/GetAllDataFromDBAsync 时返回404,预期应返回数据列表。
二、动态按钮场景实现方案咨询
需要实现以下需求:
- UI中有一个可在不同内容页面复用的动态按钮
- 点击按钮后显示数据库中的对应数据表格
- 动态按钮需接收id/标识,以此确定显示哪组数据
- id/标识由内容编辑人员在各内容页面根据数据需求配置
问题解答与实现方案
1. Surface Controller 404 问题排查与解决
Surface Controller的核心特性是和Umbraco页面绑定,若要做纯数据接口,更适合用UmbracoApiController,以下是具体调整方案:
- 替换控制器继承类:将
SurfaceController改为UmbracoApiController,路由格式变为https://localhost:44327/Umbraco/Api/SectionOptions/GetAllDataFromDBAsync - 修正返回类型:Surface Controller的Action需返回
IActionResult(如JsonResult),而非直接返回集合,修改后的Action示例:
[HttpPost] public async Task<IActionResult> GetAllDataFromDBAsync() { var data = // 数据获取逻辑 return Json(data); }
若坚持使用Surface Controller,需确保请求关联到某个Umbraco页面(携带页面上下文),否则路由无法匹配。
2. 动态按钮场景实现方案
步骤1:配置后台属性
- 在Umbraco后台创建数据类型(如文本框/下拉列表),用于编辑人员输入数据组ID
- 在需要复用按钮的文档类型中添加该属性,命名为
DataGroupId
步骤2:创建可复用Partial View
创建~/Views/Partials/DynamicDataButton.cshtml,代码如下:
@inherits UmbracoViewPage @{ var dataGroupId = Model.Value<string>("DataGroupId"); } <button id="load-data-btn" data-group-id="@dataGroupId">加载数据表格</button> <div id="data-table-container"></div> <script> document.getElementById('load-data-btn').addEventListener('click', async function() { const groupId = this.dataset.groupId; if (!groupId) { alert('请配置数据组ID'); return; } try { const response = await fetch('/Umbraco/Api/SectionOptions/GetDataByGroupId', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ groupId }) }); if (response.ok) { const data = await response.json(); // 渲染表格 let tableHtml = '<table><thead><tr><th>字段1</th><th>字段2</th></tr></thead><tbody>'; data.forEach(item => { tableHtml += `<tr><td>${item.Field1}</td><td>${item.Field2}</td></tr>`; }); tableHtml += '</tbody></table>'; document.getElementById('data-table-container').innerHTML = tableHtml; } else { alert('加载数据失败'); } } catch (error) { console.error(error); alert('加载数据出错'); } }); </script>
步骤3:创建数据接口控制器
修改控制器为UmbracoApiController,添加按ID查询的Action:
using Microsoft.AspNetCore.Mvc; using Umbraco.Cms.Core.Cache; using Umbraco.Cms.Core.Logging; using Umbraco.Cms.Core.Routing; using Umbraco.Cms.Core.Services; using Umbraco.Cms.Core.Web; using Umbraco.Cms.Infrastructure.Persistence; using Umbraco.Cms.Web.Common.Controllers; using UmbracoTest.Infrastructure; using UmbracoTest.Model; namespace UmbracoTest.Controllers { public class SectionOptionsController : UmbracoApiController { private readonly IUmbracoDatabaseFactory _databaseFactory; public SectionOptionsController(IUmbracoContextAccessor umbracoContextAccessor, IUmbracoDatabaseFactory databaseFactory, ServiceContext services, AppCaches appCaches, IProfilingLogger profilingLogger, IPublishedUrlProvider publishedUrlProvider) : base(umbracoContextAccessor, databaseFactory, services, appCaches, profilingLogger, publishedUrlProvider) { _databaseFactory = databaseFactory; } [HttpPost] public async Task<IEnumerable<DummyModel>> GetDataByGroupId([FromBody] dynamic request) { var groupId = request.groupId.ToString(); using var db = _databaseFactory.CreateDatabase(); // 按groupId查询数据的逻辑 var data = await db.FetchAsync<DummyModel>("WHERE GroupId = @0", groupId); return data; } } }
步骤4:在页面中复用组件
在需要显示按钮的模板或页面中,引用Partial View即可:
@Html.Partial("~/Views/Partials/DynamicDataButton.cshtml", Model)
内容的提问来源于stack exchange,提问作者Eduwow
相关产品推荐
相关产品推荐

