Umbraco后台Macro调用返回404:PrisInformation控制器无匹配Action
解决Umbraco API控制器404错误的方案
问题根源分析
出现404的核心原因是路由配置与请求URL不匹配,同时代码里存在授权逻辑的错误:
- 请求通过QueryString传递
typ和version参数(如?typ=1&version=0),但控制器Action的[Route]属性定义的是路径参数produktlista/{typ},两者格式不兼容。 - UmbracoApiController的默认路由规则为
/umbraco/api/{controller}/{action},自定义路由需要贴合该规则或正确覆盖。 - 原Authorize方法抛出异常的方式错误,会导致非预期的错误响应。
具体修复步骤
1. 修正路由属性
将Action的路由属性修改为匹配请求的URL结构,由于参数是QueryString传递,无需在路由里定义路径参数:
[HttpGet, HttpPost] [Route("umbraco/api/prisinformation/produktlista")] public HttpResponseMessage Produktlista(int typ = 0, int version = 0) { // 原有逻辑 }
或者直接移除[Route]属性,依赖Umbraco默认API路由规则,请求URL/umbraco/api/prisinformation/produktlista会自动匹配到该Action。
2. 修复授权逻辑
原Authorize方法抛出HttpException的方式错误,应直接返回未授权响应,而非抛出异常。将授权逻辑改为返回布尔值的私有方法:
private bool IsAuthorized() { if (!_membershipHelper.IsLoggedIn()) { return _userService.AddAndOrLoginMember(); } return true; }
然后在Action中调用并处理授权结果:
public HttpResponseMessage Produktlista(int typ = 0, int version = 0) { if (!IsAuthorized()) { return Request.CreateErrorResponse(HttpStatusCode.Unauthorized, "未授权访问"); } // 原有业务逻辑 }
3. 确保参数绑定正常
Action的typ和version参数已设置默认值,QueryString传递的参数会自动完成绑定,无需额外配置。
4. 验证路由注册(针对Umbraco 8+)
如果使用属性路由,需在Startup.cs中启用属性路由支持:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { // 其他配置项 app.UseUmbraco() .WithMiddleware(u => { u.UseBackOffice(); u.UseWebsite(); }) .WithEndpoints(u => { u.UseInstallerEndpoints(); u.UseBackOfficeEndpoints(); u.UseWebsiteEndpoints(); // 启用属性路由 u.EndpointRouteBuilder.MapControllers(); }); }
修正后的完整控制器代码示例
public class PrisInformationController : UmbracoApiController { private readonly ILoginService _userService; private readonly MembershipHelper _membershipHelper; public PrisInformationController(MembershipHelper membershipHelper, ILoginService userService) { _userService = userService; _membershipHelper = membershipHelper; } private bool IsAuthorized() { if (!_membershipHelper.IsLoggedIn()) { return _userService.AddAndOrLoginMember(); } return true; } [HttpGet, HttpPost] public HttpResponseMessage Produktlista(int typ = 0, int version = 0) { if (!IsAuthorized()) { return Request.CreateErrorResponse(HttpStatusCode.Unauthorized, "未授权访问"); } string result = string.Empty; string apiUrl = ConfigurationManager.AppSettings["ApiUrl"]; try { string requestUrl = $"{apiUrl}/databoken/get/produktlista/{typ}/{version}"; HttpWebRequest request = (HttpWebRequest)WebRequest.Create(requestUrl); request.Method = WebRequestMethods.Http.Get; request.Accept = "application/json"; using (var response = request.GetResponse()) using (var sr = new StreamReader(response.GetResponseStream())) { result = sr.ReadToEnd(); } return Request.CreateResponse(HttpStatusCode.OK, result, MediaTypeHeaderValue.Parse("application/json")); } catch (Exception ex) { return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, ex.Message); } } }
内容的提问来源于stack exchange,提问作者Stefan Fernström
相关产品推荐
相关产品推荐

