C# 如何使用 System.Net.HttpClient 发布复杂类型?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10304863/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to use System.Net.HttpClient to post a complex type?
提问by indot_brad
I have a custom complex type that I want to work with using Web API.
我有一个自定义的复杂类型,我想使用 Web API 使用它。
public class Widget
{
public int ID { get; set; }
public string Name { get; set; }
public decimal Price { get; set; }
}
And here is my web API controller method. I want to post this object like so:
这是我的 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;
}
}
And now I'd like to use System.Net.HttpClientto make the call to the method. However, I'm unsure of what type of object to pass into the PostAsyncmethod, and how to construct it. Here is some sample client code.
现在我想用它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();
});
How do I create the HttpContentobject in a way that web API will understand it?
如何HttpContent以 Web API 能够理解的方式创建对象?
采纳答案by Joshua Ball
The generic HttpRequestMessage<T>has been removed. This :
泛型HttpRequestMessage<T>已被删除。这个 :
new HttpRequestMessage<Widget>(widget)
will no longer work.
将不再起作用。
Instead, from this post, the ASP.NET team has included some new callsto support this functionality:
相反,在这篇文章中,ASP.NET 团队包含了一些新调用来支持此功能:
HttpClient.PostAsJsonAsync<T>(T value) sends “application/json”
HttpClient.PostAsXmlAsync<T>(T value) sends “application/xml”
So, the new code (from dunston) becomes:
因此,新代码(来自 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() );
回答by dunston
You should use the SendAsyncmethod instead, this is a generic method, that serializes the input to the service
您应该改用该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() );
If you don't want to create the concrete class, you can make it with the FormUrlEncodedContentclass
如果你不想创建具体的类,你可以用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();
});
Note: you need to make your id to a nullable int (int?)
注意:您需要将您的 id 设置为可以为空的 int ( int?)
回答by Fabiano
Note that if you are using a Portable Class Library, HttpClient will not have PostAsJsonAsync method. To post a content as JSON using a Portable Class Library, you will have to do this:
请注意,如果您使用的是可移植类库,则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());
回答by Todd Menier
If you want the types of convenience methods mentioned in other answers but need portability (or even if you don't), you might want to check out Flurl[disclosure: I'm the author]. It (thinly) wraps HttpClientand Json.NET and adds some fluent sugar and other goodies, including some baked-in testing helpers.
如果您想要其他答案中提到的便利方法类型但需要可移植性(或者即使您不需要),您可能需要查看Flurl[披露:我是作者]。它(薄薄地)包装HttpClient和 Json.NET 并添加了一些流畅的糖和其他好东西,包括一些烘焙测试助手。
Post as JSON:
发布为 JSON:
var resp = await "http://localhost:44268/api/test".PostJsonAsync(widget);
or URL-encoded:
或 URL 编码:
var resp = await "http://localhost:44268/api/test".PostUrlEncodedAsync(widget);
Both examples above return an HttpResponseMessage, but Flurl includes extension methods for returning other things if you just want to cut to the chase:
上面的两个示例都返回一个HttpResponseMessage,但 Flurl 包含用于返回其他内容的扩展方法,如果您只想切入正题:
T poco = await url.PostJsonAsync(data).ReceiveJson<T>();
dynamic d = await url.PostUrlEncodedAsync(data).ReceiveJson();
string s = await url.PostUrlEncodedAsync(data).ReceiveString();
Flurl is available on NuGet:
Flurl 在 NuGet 上可用:
PM> Install-Package Flurl.Http
回答by user2366741
After investigating lots of alternatives, I have come across another approach, suitable for the API 2.0 version.
在研究了很多替代方案后,我遇到了另一种方法,适用于 API 2.0 版本。
(VB.NET is my favorite, sooo...)
(VB.NET 是我的最爱,sooo...)
Public Async Function APIPut_Response(ID as Integer, MyWidget as Widget) as Task(Of HttpResponseMessage)
Dim DesiredContent as HttpContent = New StringContent(JsonConvert.SerializeObject(MyWidget))
Return Await APIClient.PutAsync(String.Format("api/widget/{0}", ID), DesiredContent)
End Function
Good luck! For me this worked out (in the end!).
祝你好运!对我来说,这解决了(最终!)。
Regards, Peter
问候, 彼得
回答by Marius St?nescu
I think you can do this:
我认为你可以这样做:
var client = new HttpClient();
HttpContent content = new Widget();
client.PostAsync<Widget>("http://localhost:44268/api/test", content, new FormUrlEncodedMediaTypeFormatter())
.ContinueWith((postTask) => { postTask.Result.EnsureSuccessStatusCode(); });
回答by Nitin Nayyar
Make a service call like this:
像这样拨打服务电话:
public async void SaveActivationCode(ActivationCodes objAC)
{
var client = new HttpClient();
client.BaseAddress = new Uri(baseAddress);
HttpResponseMessage response = await client.PutAsJsonAsync(serviceAddress + "/SaveActivationCode" + "?apiKey=445-65-1216", objAC);
}
And Service method like this:
和这样的服务方法:
public HttpResponseMessage PutSaveActivationCode(ActivationCodes objAC)
{
}
PutAsJsonAsync takes care of Serialization and deserialization over the network
PutAsJsonAsync 负责网络上的序列化和反序列化
回答by Lodlaiden
This is the code I wound up with, based upon the other answers here. This is for an HttpPost that receives and responds with complex types:
这是我根据此处的其他答案得出的代码。这是用于接收和响应复杂类型的 HttpPost:
Task<HttpResponseMessage> response = httpClient.PostAsJsonAsync(
strMyHttpPostURL,
new MyComplexObject { Param1 = param1, Param2 = param2}).ContinueWith((postTask) => postTask.Result.EnsureSuccessStatusCode());
//debug:
//String s = response.Result.Content.ReadAsStringAsync().Result;
MyOtherComplexType moct = (MyOtherComplexType)JsonConvert.DeserializeObject(response.Result.Content.ReadAsStringAsync().Result, typeof(MyOtherComplexType));
回答by user3293338
In case someone like me didn't really understand what all above are talking about, I give an easy example which is working for me. If you have a web api which url is "http://somesite.com/verifyAddress", it is a post method and it need you to pass it an address object. You want to call this api in your code. Here what you can do.
如果像我这样的人并不真正理解上述所有内容,我会举一个对我有用的简单示例。如果您有一个 url 为“ http://somesite.com/verifyAddress”的 web api ,它是一个 post 方法,它需要您向它传递一个地址对象。你想在你的代码中调用这个 api。在这里你可以做什么。
public Address verifyAddress(Address address)
{
this.client = new HttpClient();
client.BaseAddress = new Uri("http://somesite.com/");
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var urlParm = URL + "verifyAddress";
response = client.PostAsJsonAsync(urlParm,address).Result;
var dataObjects = response.IsSuccessStatusCode ? response.Content.ReadAsAsync<Address>().Result : null;
return dataObjects;
}

