ASP.NET Web API带路由参数GET接口 Axios调用返回404问题
问题核心成因
- 后端定义的两个带参接口采用了路由内嵌参数的模板规则:
[Route("my-loans/{customer_id}")]要求请求URL必须携带独立的路径段匹配customer_id参数,即正确请求路径格式为/customer/api/abl/my-loans/参数值[Route("get-loan-detail/{application_id:int}")]要求请求URL必须携带独立的整数类型路径段匹配application_id参数,即正确请求路径格式为/customer/api/abl/get-loan-detail/参数值
- 前端Axios的传参逻辑和路由规则完全不匹配:Axios的
params配置会自动把参数拼接到URL的查询字符串部分,实际发出的请求路径为getLoanDetails接口实际请求:/customer/api/abl/get-loan-detail?application_id=50getLoanHistory2接口实际请求:/customer/api/abl/my-loans?customer_id=参数值
- 这类带query参数的路径没有匹配后端定义的路由模板,Web API路由系统直接返回404。之前Postman测试能正常运行,是因为测试时手动将参数填到了路径的对应段位置,和路由规则匹配。
- 同控制器下无参数接口、POST请求能正常运行,是因为这类接口的路由模板没有定义内嵌参数段,无论URL是否携带query字符串,都能命中路由规则。
可选解决方案
你可以根据项目的接口风格选择调整前端或者后端代码,两种方案都能解决问题:
方案1:调整前端Axios传参逻辑,匹配现有后端路由规则
把原本通过params传递的路由参数,直接拼接到请求路径中,不再使用query字符串传参,修正后的代码如下:
getLoanDetails: function () { var self = this; $.LoadingOverlay("show"); // 将application_id直接拼入路径段,匹配后端路由模板 axios.get(`/customer/api/abl/get-loan-detail/50`) .then(function (response) { }) .catch(function (error) { }) .then(function () { }); }, getLoanHistory2: function () { var self = this; // 将customer_id直接拼入路径段,匹配后端路由模板 axios.get(`/customer/api/abl/my-loans/${self.customerId}`) .then(function (response) { }) .catch(function (error) { }) .then(function () { }); }
注:如果项目内所有同风格接口都采用路径传参的设计,选这个方案改动最小,不需要修改后端线上代码,风险最低。
方案2:调整后端路由定义,匹配前端现有query传参习惯
去掉路由特性里的内嵌参数占位符,保留原方法的参数签名,Web API会自动从URL查询字符串中绑定对应参数,原有业务逻辑完全不需要改动,修正后的C#代码如下:
// 原路由:[HttpGet, Route("my-loans/{customer_id}")] // 改为不带内嵌参数的路由定义 [HttpGet, Route("my-loans")] public HttpResponseMessage GetMyLoans(string customerId) { return HandleResponseException(response => { var apiClient = fluentApiClient.NewGetRequest("investnow", "my-loans").AddQuery("customer_id", $"{customerId}"); var resp = apiClient.GetResponse(); response.StatusCode = resp.Success && resp.Data != null ? HttpStatusCode.OK : HttpStatusCode.BadRequest; response.Content = new ObjectContent<ApiResponse>(resp, GetMediaTypeFormatter()); }); } // 原路由:[HttpGet, Route("get-loan-detail/{application_id:int}")] // 改为不带内嵌参数的路由定义 [HttpGet, Route("get-loan-detail")] public HttpResponseMessage GetLoanDetails(int applicationId) { return HandleResponseException(response => { var apiClient = fluentApiClient.NewGetRequest("investnow", "get-loan-detail").AddQuery("application_id", $"{applicationId}"); var resp = apiClient.GetResponse(); response.StatusCode = resp.Success && resp.Data != null ? HttpStatusCode.OK : HttpStatusCode.BadRequest; response.Content = new ObjectContent<ApiResponse>(resp, GetMediaTypeFormatter()); }); }
注:如果团队通用的GET接口设计习惯是通过query字符串传参,选这个方案可以保留现有前端代码不用改动,更贴合日常开发习惯。
内容的提问来源于stack exchange,提问作者user2721794
相关产品推荐
相关产品推荐

