Web API AJAX GET请求参数无法映射到DTO对象问题
问题根因
核心矛盾出在GET请求的模型绑定规则和传参方式不匹配:
- 按照HTTP规范,GET请求的参数应当携带在URL查询字符串中,ASP.NET Web API的默认模型绑定器处理GET请求时,默认只会从URL查询参数中取值做绑定,不会解析请求体中的内容。
- 你给AJAX配置了
contentType: "application/json",哪怕用JSON.stringify把参数转成JSON串,内容也会被放进请求体,这时候就算加[FromBody]特性也没用——[FromBody]的设计目标就是读取请求体,而GET请求本身规范就不建议携带请求体,不同框架、代理、服务器对GET请求带Body的兼容逻辑完全不一致,属于非标准用法。你用Postman传JSON能跑通只是Postman自身做了特殊兼容,浏览器原生AJAX实现不会做这类适配。 - 把接口参数拆成两个独立string类型能绑定成功,是因为jQuery发GET请求时,如果你给
data传入普通对象,会自动把对象序列化成?Username=xxx&Password=xxx格式拼到URL后面,刚好匹配GET从查询字符串读值的逻辑;但复杂类型DTO在部分Web API版本中默认不会自动从查询参数递归映射对象属性,所以会直接拿到null。
解决方案
二选一即可,优先推荐方案1。
方案1:将接口改为POST请求(符合规范,生产环境推荐)
登录接口涉及账号密码传递,用GET请求会把明文密码拼在URL中,很容易被日志、代理、浏览器历史记录泄露,本身就不应该用GET实现。
后端代码修改
[HttpPost] public string Login([FromBody] LoginToken token) { // 业务逻辑 }
前端AJAX修改
$.ajax({ contentType:"application/json", url: "/api/Admin/Login", method: "POST", // 改为POST方法 dataType: "json", data: JSON.stringify({ // 必须将对象序列化为JSON字符串 "Username":"random", "Password":"random" }), success: function (data){ // 业务逻辑 }, error:function(data){ // 错误处理 } })
方案2:坚持使用GET请求,显式指定从查询参数绑定
如果一定要用GET,就不要传JSON格式的请求体,让jQuery把参数拼成查询字符串,同时给后端DTO加[FromQuery]特性,告诉模型绑定器从URL查询参数映射复杂对象。
后端代码修改
[HttpGet] public string Login([FromQuery] LoginToken token) { // 业务逻辑 }
前端AJAX修改
去掉contentType: "application/json"配置,也不要做JSON.stringify处理,直接传普通对象给data即可,jQuery会自动将对象转为查询字符串拼接到URL上:
$.ajax({ url: "/api/Admin/Login", method: "GET", dataType: "json", data:{ "Username":"random", "Password":"random" }, success: function (data){ // 业务逻辑 }, error:function(data){ // 错误处理 } })
注意:该方案下账号密码会明文出现在URL中,存在严重安全隐患,禁止在生产环境使用。
内容的提问来源于stack exchange,提问作者Aleksa Bajat
相关产品推荐
相关产品推荐

