首次请求可达控制器重复请求报404无匹配HTTP资源错误,已修复但根因不明
我查阅了无数关于此路由报错的相关帖子,但都不符合我遇到的情况,以下是简化后的代码:
请求处理逻辑
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage requestOne) { var reqClone = await requestOne.Clone(); var responseOne = await base.SendAsync(requestOne, default(CancellationToken)); var responseTwo = await base.SendAsync(reqClone, default(CancellationToken)); return responseTwo; }
控制器示例代码
/// <summary> /// 创建一条oRecord记录 /// </summary> /// <param name="cKey">键</param> /// <param name="oRecord">记录</param> /// <param name="ct">取消令牌</param> [Route(RouteDefinitions.ExampleRoutes.TestRoute)] [Authorize] [HttpPost] public async Task<IHttpActionResult> Create(string cKey, [FromBody] OResource oRecord, CancellationToken ct) { return something; }
我的控制器已配置Get、Delete、Put、Post四种请求的处理逻辑。无论发起哪类HTTP请求,首次请求都能正常到达控制器并执行预期操作,但第二次请求会直接在System.Web.Http层抛出报错:
404:未找到与请求 http://request/com/api/v1/example 匹配的HTTP资源
补充说明:如果在同一次调用中向同一服务器先后发起两个不同请求(例如先Post后Get),也会出现同样的问题。
控制器路由配置是正常的,因为首次请求可以成功响应。
想请教大家可以从哪些方向排查问题?两次请求之间是否可能有操作修改了路由数据?
提前感谢大家的帮助!
问题已修复但根因暂不明确
我已经找到问题的解决方法,对根因只有部分理解。我发现两次请求的RouteData存在差异,测试代码如下:
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage requestOne) { var reqClone = await requestOne.Clone(); IHttpRouteData routeData = requestOne.GetRouteData(); IHttpRouteData clonedRouteData = reqClone.GetRouteData(); var responseOne = await base.SendAsync(requestOne, default(CancellationToken)); IHttpRouteData routeDataAfterRequestOne = requestOne.GetRouteData(); IHttpRouteData clonedRouteDataAfterRequestOne = reqClone.GetRouteData(); var responseTwo = await base.SendAsync(reqClone, default(CancellationToken)); return responseTwo; }
运行上述代码后发现,初始的routeData和clonedRouteData类型均为RouteCollectionRouteData,但首次请求执行完成后,routeDataAfterRequestOne和clonedRouteDataAfterRequestOne均变为HttpRouteData类型。
我仍然不清楚为什么RouteData会发生变化,克隆出的请求的RouteData也被修改就更费解了。我通过以下方案解决了问题:
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage requestOne) { IHttpRouteData routeData = requestOne.GetRouteData(); var reqClone = await requestOne.Clone(); var responseOne = await base.SendAsync(requestOne, default(CancellationToken)); reqClone.setRouteData(routeData); var responseTwo = await base.SendAsync(reqClone, default(CancellationToken)); return responseTwo; }
如果有了解为什么两个请求的RouteData都会被更新的朋友,欢迎告知,我希望能更透彻地理解该问题的底层原因,谢谢!
内容的提问来源于stack exchange,提问作者JustCallMeNick

