将列表对象传递给C# Web Api的POST方法

3

我试图将一个List传递给我的Web API,但是每次都会得到一个null值。在将列表传递到API之前,我将其转换为字符串。有什么想法可以正确地绑定它吗?

public async Task<ReturnViewModel> ModContactsAsync(List<ContactsDTO> Contacts)
 {
     ReturnViewModel vm = new ReturnViewModel();

    var postContactsUri = new UriBuilder(AppConfig.ServiceUrlBase);

    //Converts object into a string
    var jsonObject = new JavaScriptSerializer().Serialize(Contacts);


    postContactsUri.Path = string.Format(POST_CONTACTS_API_PATH, jsonObject);
    //Calls API
    var response = await _httpClient.PostAsync(postContactsUri.ToString());

    return vm;
}

POST - API调用列表prod为null

[HttpPost]
[Route("contacts/Save")]
[ResponseType(typeof(ReturnMessage))]
public async Task<IHttpActionResult> ModContacts([FromBody] List<ContactsDTO> prods)
{
    try
    {
        await Task.Delay(10);

        return Ok();
    }
    catch (Exception ex)
    {
        throw new PropertyPortalWebApiException(HttpStatusCode.InternalServerError, "Contact information does not exist.", ex);
    }
  }

1
你正在尝试将联系人放入URL中,但是却从请求正文中读取它们? - Rhumborl
尝试将PostAsync调整为以下形式:var response = await _httpClient.PostAsync(POST_CONTACTS_API_PATH, new System.Net.Http.StringContent(jsonObject, Encoding.UTF8, "application/json")); - mike123
@mike123 我仍然得到一个空值。 - Apollo
@Rhumborl 你有什么建议吗? - Apollo
你怎么通过URL接收一个列表,然后再尝试通过正文获取它们呢? - Alfredo Zamudio
5个回答

1
你应该简单地搜索并了解GET/POST的区别以及如何使用HttpClient进行POST请求。

首先,您需要将内容添加到URL中,并尝试使用HttpClient进行POST请求。

var response = await _httpClient.PostAsync(postContactsUri.ToString());

在您的API中,您正在读取已通过URL传递的对象FromBody。
public async Task<IHttpActionResult> ModContacts([FromBody] List<ContactsDTO> prods)

PostAsync方法的签名是:
public Task PostAsync(Uri uri, HttpContent content)

所以你应该将URL作为第一个参数传递,并将您的列表对象作为HttpContent形式的第二个参数传递。

或者,您可以使用PostAsJsonAsync扩展方法。


完美。谢谢。 - Amila Thennakoon
1
@AmilaThennakoon,很高兴你觉得它有帮助! - Mukesh Modhvadiya

0
public IActionResult GetAllContacts()
{
     List<Contacts> contacts = contactService.RetrieveAllContacts();
     return Json(contacts);
}

理论上,以上内容将是您的API。用户将请求GetAllContacts,您将从数据库中获取联系人,然后通过Json返回。

消费者随后将编写代码来使用:

var request = CreateWebRequest(url) as HttpWebRequest;
if(request != null)
     using(var response = request.GetResponse.GetResponseStream())
          var content = Json.DeserializeObject(request.ReadToEnd());

类似上面这样的代码,应该会为您返回一个List<Contacts>

我相信这就是您想要做的事情。


更新:
我注意到你想让用户保存数据。你可以按照以下方式操作:
public IActionResult SaveContact([FromBody] List<Contacts>)
{
     // Validate and Save
}

消费者将执行Ajax或类似的操作:

List<Contact> contacts = contactService.GetAllContacts(); // User would have a collection for you.
var post = Json.SerializeObject(contacts);

var request = WebRequest.Create(url) as HttpWebRequest;
request.Method = "POST";
request.ContentType = ...
request.ContentLength = post.Length;
request.UserAgent = ...
request.Accept = ...
request.Referer = ...

using(var writer = new StreamWriter(request.GetRequestStream())
{
     writer.Write(post); 
     request.GetResponse();
     request.Close();
}

对于我标注的请求,您不需要所有参数,但它们确实存在。希望这可以帮到您。


Greg,我正在尝试将一个列表传递给API。我该如何将其传递给API调用? - Apollo
https://dev59.com/1F4c5IYBdhLWcg3wSIgt - Apollo
@Apollo 通过Ajax或C#?我将代码更改为var而不是更加明确。 - Greg
你如何将这个传递给 PostAsync? - Apollo
1
@AluanHaddad 默认情况下,WebRequestHttpWebRequest不实现IDispose - Greg

0

我找到了问题所在。只需将Contacts对象添加到PostAsync的第二个参数中,就可以了。您不需要将对象转换为JSON。

public async Task<ReturnViewModel> ModContactsAsync(List<ContactsDTO> Contacts)
{
    ReturnViewModel vm = new ReturnViewModel();

    var postContactsUri = new UriBuilder(AppConfig.ServiceUrlBase);

    postContactsUri.Path = string.Format(POST_CONTACTS_API_PATH, jsonObject);
    //Add Contacts to second parameter
    var response = await _httpClient.PostAsync(postContactsUri.ToString(), Contacts);

return vm;

}


如果我必须在主对象中传递一些对象的列表,那么发送机制将是什么?请参考此处的问题。 - 3 rules

0

我解决了和你类似的问题(解决方案在这里)。

基本上:

public async Task<ReturnViewModel> ModContactsAsync(List<ContactsDTO> Contacts)
{
    ReturnViewModel vm = new ReturnViewModel();

    var bodyContent = JsonConvert.SerializeObject(Contacts);

    using (var client = new HttpClient())
    {
        var response = await client.PostAsync(AppConfig.ServiceUrlBase, new StringContent(bodyContent, Encoding.UTF8, "application/json"));

        return responseString.Result.Content.ReadAsStringAsync().Result;
    }

    return vm;
}

正如您从之前的评论中已经了解到的那样,客户端无法将列表作为查询参数发送,而服务器期望在正文中接收它。

通过上面的代码,客户端将列表发送到正文中,服务器从正文中读取它。

永远不要将列表作为查询参数发送,即使它只是一个小列表。URL长度有限制,而且如果POST方法允许您使用请求正文发送信息,为什么要在URL上公开您的参数呢?


-1

是的,它是空的,因为您尝试发送一个模型,但在另一种方法中,您尝试获取对象列表。必须在此之后获取涉及对象列表的对象,然后您的请求将被读取。

ModContacts([FromBody] ContactDTO prod)

在ContactDTO中,您必须拥有一个可序列化的对象列表。


我不是在发送一个模型,而是在发送一个列表。 - Apollo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接