【发布时间】:2016-02-14 06:54:02
【问题描述】:
我有一个非常基本的场景......我觉得我之前已经做过 100 次但由于某种原因它决定不工作并将我的时间浪费在一些琐碎的事情上......
我正在使用带有属性路由的 WebAPI(喜欢它们)。
我正在尝试传入两个参数,一个来自 Body,一个来自 Uri。它们都是基本类型……一个是Boolean,另一个是Long赞助商ID。
相当简单的服务签名...
[HttpPut]
[Route("adminAPI/sponsors/{sponsorID:long}/Enable")]
public HttpResponseMessage EnableSponsor([FromBody]Boolean enabled, [FromUri] Int64 sponsorID)
{
HttpResponseMessage ret = null;
// does stuff and populates the response
return ret;
}
使用 Postman 和 Advanced REST Client 和 JQuery/Chrome 我收到“错误请求”错误...
var request = function () {
$.ajax({
type: 'PUT',
url: 'http://localhost:50865/adminAPI/Sponsor/23/Enable',
data: { "enabled": true },
contentType: "application/json"
})
.done(function (data, textStatus, jqXHR) {
if ([200, 204, 304].indexOf(data.StatusCode) === -1) {
} else {
}
})
.fail(function (jqXHR, textStatus, errorThrown) {
});
};
我收到以下错误...
参数字典包含参数的空条目 方法的“启用”不可为空类型“System.Boolean” 'System.Net.Http.HttpResponseMessage EnableSponsorBanner(布尔值, 'WEB.Admin.api.SponsorAPIController' 中的 Int64)'。可选参数 必须是引用类型、可空类型或声明为 可选参数。”
由于某种原因,[FromBody] 参数没有随请求一起传递,从而导致错误。当我使参数可以为空时,请求会通过,但正如预期的那样,启用的参数是 NULL?
我的头撞墙了……有什么想法吗?
解决方案
我尝试简单地从 Web 服务调用中删除密钥,但没有成功。相反,我使用可能单独发送到服务的基本数据类型创建了一个数据传输对象 (DTO)。我可以使用它来传递这个模型,从而为这个和将来提出的任何其他请求传递简单的值引用。
//
// The Data Transfer Object
public class APIValueTypes
{
public Boolean booleanValue { get; set; }
public Int64 longValue { get; set; }
public String stringValue { get; set; }
public DateTime dateValue { get; set; }
}
由于服务知道它正在寻找什么值,它可以获取它需要的任何值。
[HttpPut]
[Route("adminAPI/sponsors/{sponsorID:long}/Enable")]
public HttpResponseMessage EnableSponsor([FromBody]APIValueTypes enabled, [FromUri] Int64 sponsorID)
{
HttpResponseMessage ret = null;
Boolean isEnabled = enabled.booleanValue;
// does stuff and populates the response
return ret;
}
警告
此时我必须承认,虽然我让它在我的 REST 工具中工作,但我无法让它在我的 JQuery 实现中工作。因此,虽然我的帖子已得到答复,但我遇到了 JQuery ajax$ 的另一个问题......即使我在 DTO 对象中发送服务方法仍然收到 null 而不是对象......(我怀疑的另一个帖子...... - 叹息)
var request = function () {
$.ajax({
type: 'PUT',
url: 'http://localhost/adminAPI/Sponsor/23/Enable',
data: { "booleanValue": false },
contentType: "application/json",
})
.done(function (data, textStatus, jqXHR) {
console.log(data);
if ([200, 204, 304].indexOf(data.StatusCode) === -1) {
} else {
}
})
.fail(function (jqXHR, textStatus, errorThrown) {
});
};
警告解决方案
我发现仅仅将 JSON 对象作为数据负载发送是行不通的。我必须对数据进行“字符串化”,以便将其序列化回 APIValueTypes 参数数据类型。所以从 JQuery 对服务的调用现在看起来像......注意 data 分配......
var request = function () {
$.ajax({
type: 'PUT',
url: 'http://localhost/adminAPI/Sponsor/23/Enable',
data: JSON.stringify({ "booleanValue": false }),
contentType: "application/json",
})
.done(function (data, textStatus, jqXHR) {
console.log(data);
if ([200, 204, 304].indexOf(data.StatusCode) === -1) {
} else {
}
})
.fail(function (jqXHR, textStatus, errorThrown) {
});
};
我希望有人能发现这个小旅程很有用,当我在 6 个月后忘记它时,这篇文章仍然会在这里提醒我!!再次感谢!
【问题讨论】:
-
我一直在研究 [FromBody] 属性的类似问题,结果发现您对 JSON 字符串化的评论似乎是我在尝试将数据填充到时遇到的唯一问题那个参数。感谢您阐明这个小细节。
标签: c# asp.net-web-api