如果使用FromBody和FromForm参数始终为null / new,则对Core API的Webclient调用找不到端点

时间:2018-08-21 17:06:52

标签: c# asp.net-core webclient

这是API代码段:

[HttpPost]
[ProducesResponseType(typeof(myObject), 201)] //created
[ProducesResponseType(500)] //server error
public IActionResult Create([FromForm]myObject myObj) {
...

这是服务器端调用:

...
using (WebClient client = new WebClient()) {        
    NameValueCollection formData = new NameValueCollection();
    string targetURL = "https://localhost:44317/api/MyController/Create"
    string callMethod = "POST";
    formData["myObj"] = JsonConvert.SerializeObject(myObj);
    var thingy = client.UploadValues(targetURL, callMethod, formData);
    ...

如果我使用[FromForm],则呼叫会找到端点,但传入的数据就像我说过myObj = new MyObject();一样,具有所有内容的默认值。所以...不是完全为空。

如果我使用[FromBody],则client找不到该网址,而我得到一个400 Bad Request

我想在这里和其他地方都读过很多文章,我认为它们并不能完全涵盖这种情况,因为我观察到的内容似乎与其他人的要求相反。所以我不太确定我的代码是怎么回事。

请注意,我无法使用 async ,因此无法使用HttpClient。 (不能使用异步,因为它位于Kentico站点内,并且是门户页面内的ascx)

2 个答案:

答案 0 :(得分:1)

似乎您打算发布JSON,但实际上您是以x-www-form-urlencoded的形式发布的,其中已序列化的JSON作为myObj参数的值。由于编码类型的原因,该操作必须使用[FromForm](或完全不使用属性),但是到那时,它不能将您的“ JSON”反序列化为一个对象。我在这里在引号中使用“ JSON”,因为实际上这只是一个字符串。 ASP.NET Core甚至不知道这甚至是JSON,也不知道应该对此做些什么。总而言之,您需要发布一个实际的application/json请求正文。

using (var client = new WebClient())
{
    client.Headers["Content-Type"] = "application/json; charset=utf-8";
    var requestBody = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(myObj));
    var response = webClient.UploadData(targetUrl, callMethod, requestBody);
}

然后,当然,您实际上需要在参数上使用FromBody属性,因为实际上您现在将接收JSON。

答案 1 :(得分:0)

FromForm的问题在于,您将其序列化为字符串,并且WebAPI在默认情况下不会为您反序列化。如果要继续使用FromForm,可以将参数类型更改为string并对其进行显式反序列化:

public IActionResult Create([FromForm]string myObj) {
    myObject obj = JsonConvert.DeserializeObject<myObject>(myObj);
    ...