如何使用System.Net.HttpClient发布一个复杂的types?
我有一个自定义的复杂types,我想使用Web API。
public class Widget { public int ID { get; set; } public string Name { get; set; } public decimal Price { get; set; } }
这是我的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; } }
现在我想使用System.Net.HttpClient来调用方法。 但是,我不确定传入PostAsync方法的对象types,以及如何构造它。 这里是一些示例客户端代码。
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(); });
如何以Web API可以理解的方式创buildHttpContent对象?
通用HttpRequestMessage<T>
已被删除 。 这个 :
new HttpRequestMessage<Widget>(widget)
将不再工作 。
相反, 从这篇文章中 ,ASP.NET团队已经包含了一些新的调用来支持这个function:
HttpClient.PostAsJsonAsync<T>(T value) sends “application/json” HttpClient.PostAsXmlAsync<T>(T value) sends “application/xml”
所以,新代码( 来自邓斯顿 )变成:
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() );
您应该使用SendAsync
方法,这是一种通用的方法,将input序列化到服务
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() );
如果你不想创build具体的类,你可以使用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(); });
注意:你需要把你的id设为一个可空的int( int?
)
请注意,如果您使用的是可移植类库,则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());
如果你想在其他答案中提到的便利方法的types,但需要可移植性(或者即使你不这样做),你可能想检查Flurl [披露:我是作者]。 它(简单地)包装了HttpClient
和Json.NET,并添加了一些stream利的糖和其他好东西,包括一些烘焙testing助手 。
作为JSON发布:
var resp = await "http://localhost:44268/api/test".PostJsonAsync(widget);
或URL编码:
var resp = await "http://localhost:44268/api/test".PostUrlEncodedAsync(widget);
上面的两个例子都返回一个HttpResponseMessage
,但是Flurl包含了用于返回其他内容的扩展方法,如果你只想切换到chase:
T poco = await url.PostJsonAsync(data).ReceiveJson<T>(); dynamic d = await url.PostUrlEncodedAsync(data).ReceiveJson(); string s = await url.PostUrlEncodedAsync(data).ReceiveString();
Flurl在NuGet上可用:
PM> Install-Package Flurl.Http
在调查了许多替代scheme之后,我遇到了另一种适用于API 2.0版本的方法。
(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
祝你好运! 对我来说,这个解决了(最终!)。
问候,彼得
我认为你可以这样做:
var client = new HttpClient(); HttpContent content = new Widget(); client.PostAsync<Widget>("http://localhost:44268/api/test", content, new FormUrlEncodedMediaTypeFormatter()) .ContinueWith((postTask) => { postTask.Result.EnsureSuccessStatusCode(); });
这是我根据其他答案在这里结束的代码。 这是一个HttpPost接收和复杂types的响应:
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));
如果像我这样的人真的不明白上面所说的是什么,我就举个简单的例子来帮助我。 如果你有一个网站的API是“ http://somesite.com/verifyAddress ”,这是一个后期的方法,它需要你传递一个地址对象。 你想在你的代码中调用这个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; }
拨打这样的服务电话:
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); }
和服务方法是这样的:
public HttpResponseMessage PutSaveActivationCode(ActivationCodes objAC) { }
PutAsJsonAsync负责通过networking进行序列化和反序列化