通过 javascript 将复杂参数传递给 Web API 服务
Posted
技术标签:
【中文标题】通过 javascript 将复杂参数传递给 Web API 服务【英文标题】:Pass complex parameter to Web API service via javascript 【发布时间】:2015-07-10 17:48:35 【问题描述】:我正在制作一个 ASP.NET Web API Web 服务和一个 html/javascript 页面来测试它。我遇到的问题是传递一个复杂的数据参数并让它在 Web API 控制器中正确通过。
我知道有很多类似的问题,我已经阅读并尝试了解决方案,但都没有解决。我还阅读了一些 JQuery 文档。
这是我的控制器:
public class TitleEstimateController : ApiController
public IHttpActionResult GetTitleEstimate([FromUri] EstimateQuery query)
// All the values in "query" are null or zero
// Do some stuff with query if there were anything to do
public class EstimateQuery
// Various fields
WebApiConfig.cs 中的路由映射:
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/controller/query"
);
还有 javascript:
var uri = 'api/titleEstimate/';
var query =
"username": $("#user").val(),
// other fields
;
$.getJSON(uri,query)
.done(function (data)
$('#product').text("OK");
)
.fail(function (jqXHR, textStatus, err)
$('#product').text('Error: ' + err);
);
目前我收到的是 404。我尝试了$.getJSON(uri + '/' + query)
,但也没有用。在传递此对象之前,我已成功调用它,因此我认为路由通常没问题。我尝试了一个类型转换器,但没有帮助,仍然是 404。有没有人看到我错过了什么/做错了什么?
【问题讨论】:
服务器端有异常吗?你检查过“输出窗口”吗? 调试输出中没有任何内容。 除了uri
之外,您做的一切都很好。有关详细信息,请参阅以下答案。
【参考方案1】:
对于复杂的对象,我通常在消息体而不是 URL 中发送。
您对类似于这个问题的答案的方法有任何异议吗? How to pass json POST data to Web API method as object
这似乎是更直接/自然的方法。
类似的东西(未经测试,但应该接近):
[RoutePrefix("api/titleestimate")]
public class TitleEstimateController : ApiController
[HttpGet]
public IHttpActionResult GetTitleEstimate([FromBody] EstimateQuery query)
// All the values in "query" are null or zero
// Do some stuff with query if there were anything to do
public class EstimateQuery
public string QueryName get; set;
public string Whatever get; set;
$(function ()
var query = QueryName:"My Query",Whatever:"Blah";
$.ajax(
type: "GET",
data :JSON.stringify(query),
url: "api/titleEstimate",
contentType: "application/json"
)
.done(function (data)
$('#product').text("OK");
)
.fail(function (jqXHR, textStatus, err)
$('#product').text('Error: ' + err);
);
);
【讨论】:
谢谢,我用 'JSON.stringify(query)' 尝试了这个版本,但它仍然给我一个 404。因为它是一个 404 而不是 500 什么的,似乎有一些关于通过这个Web API 不喜欢的参数。它找不到要调用的控制器方法。 这个答案也不起作用,因为它的 uri 也不正确。【参考方案2】:首先,我会尝试像这样使用 web.api 的属性路由功能:
[RoutePrefix("api/titleestimate")]
public class TitleEstimateController : ApiController
[HttpGet]
public IHttpActionResult GetTitleEstimate([FromUri] EstimateQuery query)
// All the values in "query" are null or zero
// Do some stuff with query if there were anything to do
在您的开发工具中查看请求也会有所帮助。我不同意 Colin 的观点,即您应该将其设为 POST,因为 HTTP POST 应该用于创建新项目。您正在尝试获取信息,因此 HTTP GET 有意义。
我认为 Web.Api 默认假定方法是 GET,但使用 HttpGet 属性声明它肯定会解决这个问题。
【讨论】:
小细节,但不错。我会调整我的答案以做出改进。 我尝试添加这些,但似乎没有多大作用。我现在得到很多关于 PDB 文件的调试输出并跳过加载符号,但没有错误。这是 Chrome 的消息:GET http://localhost:47503/api/titleEstimate/?username=whatever…&StreetSuffix=Street&County=Boulder&IsPrimary=on&State=CO&Unit=&Zip=80303 404 (Not Found)
如果需要,我愿意使用 POST,但我同意,GET 在这里更有意义,它似乎应该可以工作。
我已经多次解决这些类型的错误。如果没有所有信息,很难说。例如,用户名是小写的,但所有其他人都以大写字母开头。我通常还会在我的控制器方法上放置一个 [Route("Blah")] 属性,然后您的代码应该保存 var uri = 'api/titleEstimate/blah';它以前也依赖于我的浏览器。 Chrome 似乎使用默认标头作为 application/json,而 Firefox 似乎默认使用 application/xml。查看标题,检查大小写并更明确地说明您的路线,看看是否有帮助。
你不需要HttpGet
。没必要。【参考方案3】:
回答
您使用了错误的uri
。你需要api/titleEstimate/getTitleEstimate
。这解释了并将解决您的 404。
回答后续问题
你正在做的所有其他事情几乎都有效。解决 404 后,您会发现您没有收到值 FromUri
,并且您将有一个后续问题。因此,您需要将路由配置更改为:
config.Routes.MapHttpRoute(
name: "Default",
routeTemplate: "api/controller/action"
);
那么您不仅会解析 404,还会收到您作为查询字符串参数发送的 FromUri
值。
演示
这里是a fiddle for evidence,它正在调用this controller,它是is hosted LIVE here。我在工作版本中唯一更改的是 uri
来解析 404 和路由配置以确保您收到 FromUri
值。就是这样。
HTML
<label>Username:
<input id="user" />
</label>
<button id="submit">Submit</button>
<button id="submit-fail">Submit Fail</button>
<div id="product"></div>
JavaScript
这会成功。
请注意,我们只需要domain
,因为我们在这里进行跨站点脚本是为了演示目的。
var domain = "https://cors-webapi.azurewebsites.net";
$("#submit").click(function ()
var uri = domain + '/api/titleEstimate/getTitleEstimate';
var query =
"username": $("#user").val(),
// other fields
;
$.getJSON(uri, query)
.done(function (data)
$('#product').text(data);
)
.fail(function (jqXHR, textStatus, err)
$('#product').text('Error: ' + err);
);
);
这将是 404。
$("#submit-fail").click(function ()
var uri = domain + '/api/titleEstimate';
var query =
"username": $("#user").val(),
// other fields
;
$.getJSON(uri, query)
.done(function (data)
$('#product').text(data);
)
.fail(function (jqXHR, textStatus, err)
$('#product').text('Error: ' + err);
);
);
控制器
public class TitleEstimateController : ApiController
public class EstimateQuery
public string username get; set;
public IHttpActionResult GetTitleEstimate([FromUri] EstimateQuery query)
// All the values in "query" are null or zero
// Do some stuff with query if there were anything to do
if(query != null && query.username != null)
return Ok(query.username);
else
return Ok("Add a username!");
您可以阅读更多详细信息about WebApi routing here。通过阅读它,您可能会在您的路线配置中提出替代解决方案。还有很多terrific examples in this blog post。
【讨论】:
非常感谢您抽出宝贵时间整理出如此详细的答案。我寄予厚望,但是当我运行小提琴并按下提交(有或没有值)时,我得到错误:未找到。所以我认为那里的路由仍然有问题。 @nasch 已修复 :-)。我使用的是旧的uri
,当我更新小提琴时,我忘记将新版本设置为基础。也就是说,我使用的是/api/values/GetTitleEstimate
而不是/api/titleEstimate/GetTitleEstimate
。链接的小提琴现在可以工作了,因为我已将最新版本设置为基础。
太棒了,现在可以使用了,谢谢!令我困惑的一件事是我无法将结果显示在网页上。我和你一样有这个:$('#product').text(data);
但它什么也没做。我可以使用该值记录或警告,这很好,但是 text() 调用不起作用。我尝试输入一个字符串文字值,将其移动到函数的开头,将其放入 document.ready() 中,没有效果。我敢肯定这是愚蠢的,但如果你有任何想法,我会很高兴听到它。 div 是这样的:<div id="product">Information goes here</div>
不客气。我不确定为什么不会为您显示结果。您已经尝试了我会尝试的大多数故障排除步骤。例如。日志、警报等。我可能会尝试使用另一个 div
和另一个 id
。另外,创建一个复制错误的小提琴;这样您就可以准确地共享产生错误的代码。
好的,谢谢,如果我什么都没发生,我可能会提出另一个问题,但网页不是项目的关键部分。再次感谢您的帮助。以上是关于通过 javascript 将复杂参数传递给 Web API 服务的主要内容,如果未能解决你的问题,请参考以下文章
如何通过 HtmlDocument.InvokeScript 将对象作为参数传递给 javascript