如何使用System.Net.HttpClient发布复杂类型?

ind*_*rad 101 c# asp.net-web-api

我有一个自定义复杂类型,我想使用Web API.

public class Widget
{
    public int ID { get; set; }
    public string Name { get; set; }
    public decimal Price { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

这是我的Web API控制器方法.我想像这样发布这个对象:

public class TestController : ApiController
{
    // POST /api/test
    public HttpResponseMessage<Widget> Post(Widget widget)
    {
        widget.ID = 1; // hardcoded for now. TODO: Save to db and return newly created ID

        var response = new HttpResponseMessage<Widget>(widget, HttpStatusCode.Created);
        response.Headers.Location = new Uri(Request.RequestUri, "/api/test/" + widget.ID.ToString());
        return response;
    }
}
Run Code Online (Sandbox Code Playgroud)

现在我想使用System.Net.HttpClient来调用该方法.但是,我不确定要传递给PostAsync方法的对象类型以及如何构造它.这是一些示例客户端代码.

var client = new HttpClient();
HttpContent content = new StringContent("???"); // how do I construct the Widget to post?
client.PostAsync("http://localhost:44268/api/test", content).ContinueWith(
    (postTask) =>
    {
        postTask.Result.EnsureSuccessStatusCode();
    });
Run Code Online (Sandbox Code Playgroud)

如何以Web API理解的方式创建HttpContent对象?

Jos*_*all 131

该通用HttpRequestMessage<T>已被删除.这个 :

new HttpRequestMessage<Widget>(widget)
Run Code Online (Sandbox Code Playgroud)

不再有效.

相反,从这篇文章中,ASP.NET团队已经包含了一些新的调用来支持这个功能:

HttpClient.PostAsJsonAsync<T>(T value) sends “application/json”
HttpClient.PostAsXmlAsync<T>(T value) sends “application/xml”
Run Code Online (Sandbox Code Playgroud)

所以,新代码(来自dunston)变成:

Widget widget = new Widget()
widget.Name = "test"
widget.Price = 1;

HttpClient client = new HttpClient();
client.BaseAddress = new Uri("http://localhost:44268");
client.PostAsJsonAsync("api/test", widget)
    .ContinueWith((postTask) => postTask.Result.EnsureSuccessStatusCode() );
Run Code Online (Sandbox Code Playgroud)

  • 请注意,您需要添加对System.Net.Http.Formatting的引用,以便能够使用`PostAsJsonAsync`或`PostAsXmlAsync` (16认同)
  • 新的`HttpClient.PostAsXXXAsync <T>(T值)方法很棒,但是对于application/x-www-form-urlencoded格式呢?有没有简单/简短的方法,或者我们还需要创建精心设计的`KeyValuePair`列表? (13认同)
  • 要使用PostAsJsonAcync,请添加NuGet包Microsoft.AspNet.WebApi.Client !! (6认同)

dun*_*ton 99

您应该使用该SendAsync方法,这是一种通用方法,它将服务的输入序列化

Widget widget = new Widget()
widget.Name = "test"
widget.Price = 1;

HttpClient client = new HttpClient();
client.BaseAddress = new Uri("http://localhost:44268/api/test");
client.SendAsync(new HttpRequestMessage<Widget>(widget))
    .ContinueWith((postTask) => postTask.Result.EnsureSuccessStatusCode() );
Run Code Online (Sandbox Code Playgroud)

如果您不想创建具体类,可以使用FormUrlEncodedContent该类创建

var client = new HttpClient();

// This is the postdata
var postData = new List<KeyValuePair<string, string>>();
postData.Add(new KeyValuePair<string, string>("Name", "test"));
postData.Add(new KeyValuePair<string, string>("Price ", "100"));

HttpContent content = new FormUrlEncodedContent(postData); 

client.PostAsync("http://localhost:44268/api/test", content).ContinueWith(
    (postTask) =>
    {
        postTask.Result.EnsureSuccessStatusCode();
    });
Run Code Online (Sandbox Code Playgroud)

注意:你需要将你的id设置为可以为null的int(int?)

  • 我得到"非泛型类型'System.Net.Http.HttpRequestMessage'不能与类型参数一起使用".这仍然有效吗? (8认同)
  • 是的,第一个解决方案不再起作用了:http://aspnetwebstack.codeplex.com/discussions/350492 (5认同)

Fab*_*ano 73

请注意,如果您使用的是可移植类库,则HttpClient将不具有PostAsJsonAsync方法.要使用可移植类库将内容发布为JSON,您必须执行以下操作:

HttpClient client = new HttpClient();
HttpContent contentPost = new StringContent(argsAsJson, Encoding.UTF8, 
"application/json");

await client.PostAsync(new Uri(wsUrl), contentPost).ContinueWith(
(postTask) => postTask.Result.EnsureSuccessStatusCode());
Run Code Online (Sandbox Code Playgroud)

  • 优秀@fabiano!这真的成​​功了.在这类项目中,这两个额外的参数是必要的. (3认同)