我正在使用邮递员测试我的Web API,并在邮递员中返回“ 400错误请求”或“输入无效”。我动作第一行的断点没有被击中。我怎么知道幕后发生了什么?
我将显示Postman的屏幕截图,但无法上传图片。这只是一个POST,其中为Body指定了多个字段。这是网址:
http://localhost:52126/api/v1/itinerary
这是动作:
[HttpPost]
[Route("api/v1/itinerary")]
public async Task<ActionResult> AddItineraryAsync([FromBody] Itinerary itinerary)
{
if (!ModelState.IsValid) // Break point on this line not getting hit!
{
return BadRequest(ModelState);
}
await Logic.AddItineraryAsync(itinerary);
return Ok();
}
最初,我没有为此操作指定[FromBody]。无论哪种方式都行不通。我可以检查出什么情况?
澄清(回应克里斯·普拉特):
我正处于编写第一个移动应用程序的初期阶段,作为一个自下而上的家伙,我首先开始使用一些Web API调用。我假设我会将JSON从移动应用程序传递到此服务器层。
在此Web API项目中,我没有做任何与防伪令牌有关的事情,因此我认为这些令牌没有作用……除非那是邮递员提供的。
从操作中删除参数确实可以使执行陷入我的断点,因此错误似乎与ASP.NET绑定有关。
深入研究Postman后,我确实看到标题为Content-Type指定了x-www-form-urlencoded
。根据您的建议,我将其更改为application/json
。但是,这似乎没有什么不同。
更多信息:
尝试了下面卡尔的建议后,我获得了更多信息。执行权落到了行动中,我看看邮递员正在传递什么。在这里:
----------------------------179455694862693501539465
Content-Disposition: form-data; name="StartPoint"
Tacoma
----------------------------179455694862693501539465
Content-Disposition: form-data; name="EndPoint"
Portland
----------------------------179455694862693501539465
Content-Disposition: form-data; name="TravelDate"
2018-8-21 07:00:00 AM
----------------------------179455694862693501539465
Content-Disposition: form-data; name="Name"
Test Itinerary
----------------------------179455694862693501539465
Content-Disposition: form-data; name="UserAccountId"
2
----------------------------179455694862693501539465
Content-Disposition: form-data; name="Comment"
Just doin' some testing.
----------------------------179455694862693501539465--
Json反序列化失败:
JsonReaderException: Input string '----------------------------179455694862693501539465' is not a valid number.
这些数字是什么,它们来自哪里?
答案 0 :(得分:3)
ModelState
仅在能够成功反序列化后正文/绑定的情况下才被验证。
您的问题不明确,但听起来好像您是以x-www-form-urlencoded
的身份发帖。如果是这种情况,您应该不有[FromBody]
。但是,请记住,这是一种“或/或”情况,因此,如果最终要通过JSON发布,则应保留该属性,然后从Postman发布JSON。
除此之外,请确保您未在使用防伪令牌验证,或者正在与请求一起发布有效令牌。防伪验证失败会缩短请求并立即返回400。
如果要发布JSON,请确保您的JSON有效。如果JSON无效,您将立即获得400。
答案 1 :(得分:1)
我尝试过像您的[FromBody] Itinerary itinerary
一样,但是得到了解决。 2.1框架具有问题https://github.com/aspnet/Mvc/issues/7609和https://github.com/aspnet/Mvc/issues/7799。我在2.1中工作:客户端JavaScript保持不变:
var payload = JSON.stringify({ "name": document.getElementById('firstname').value, "email": document.getElementById('email').value, "captcha": grecaptcha.getResponse() });
var oReq = new XMLHttpRequest();
oReq.ContentType = "application/json";
oReq.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
document.getElementById("update").innerHTML = this.responseText;
}
else document.getElementById("update").innerHTML = "not 4&200! : " + this.responseText;
};
oReq.open('POST', 'api/u');
oReq.send(payload);
并且控制器具有:
[Route("api/[controller]")]
// [ApiController] // works either way
public class UController : ControllerBase
{
[HttpPost]
public async Task<string> signUp()
{
String body;
using (StreamReader reader = new StreamReader(Request.Body, Encoding.UTF8))
{
body = await reader.ReadToEndAsync();
}
UserSignup user = JsonConvert.DeserializeObject<UserSignup>(body);
return user.email;
}
}
答案 2 :(得分:0)
评论解决方案:
对于179455694862693501539465,看来您正在使用PostMan,并将application / x-www-form-urlencode编码为Content-Type。
我建议您按照以下步骤操作:
1.使用AddItineraryAsync([FromBody] Itinerary itinerary)保留您的api;
2.在邮递员中清除标题
3.“正文”选项卡使用JSON(application / json)选择raw
4.输入有效的json字符串或仅使用{}
5.确保没有其他标头,除了application / json作为标头标签中的Content-Type。
6.发送请求以检查是否会命中api方法。