我有一个自定义复杂类型,我想使用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方法的对象类型以及如何构造它。这是一些示例客户端代码。
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理解的方式创建HttpContent对象?
答案 0 :(得分:131)
通用HttpRequestMessage<T>
已被删除。这个:
new HttpRequestMessage<Widget>(widget)
将不再有效。
相反,from this post,ASP.NET团队已经包含了一些new calls来支持此功能:
HttpClient.PostAsJsonAsync<T>(T value) sends “application/json”
HttpClient.PostAsXmlAsync<T>(T value) sends “application/xml”
因此,新代码(from 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() );
答案 1 :(得分: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() );
如果您不想创建具体类,可以使用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设置为可以为null的int(int?
)
答案 2 :(得分: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());
答案 3 :(得分:4)
如果您想要其他答案中提到的便利方法类型但需要可移植性(或者即使您不需要),您可能需要查看Flurl [披露:我是作者]。它(薄)包裹HttpClient
和Json.NET并添加一些流利的糖和其他好东西,包括一些烤好的testing helpers。
发布为JSON:
var resp = await "http://localhost:44268/api/test".PostJsonAsync(widget);
或网址编码:
var resp = await "http://localhost:44268/api/test".PostUrlEncodedAsync(widget);
以上两个示例都返回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可在NuGet上找到:
PM> Install-Package Flurl.Http
答案 4 :(得分:1)
在研究了许多替代方案之后,我遇到了另一种适用于API 2.0版本的方法。
(VB.NET是我最喜欢的,所以......)
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
祝你好运!对我来说,这个问题已经解决了(最终!)。
此致 彼得
答案 5 :(得分:1)
我认为你可以这样做:
var client = new HttpClient();
HttpContent content = new Widget();
client.PostAsync<Widget>("http://localhost:44268/api/test", content, new FormUrlEncodedMediaTypeFormatter())
.ContinueWith((postTask) => { postTask.Result.EnsureSuccessStatusCode(); });
答案 6 :(得分:0)
根据这里的其他答案,这是我结束的代码。这适用于接收和响应复杂类型的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));
答案 7 :(得分:0)
如果像我这样的人并不真正理解上述内容,我会给出一个适合我的简单例子。 如果你有一个web api,url是“http://somesite.com/verifyAddress”,那么它是一个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;
}
答案 8 :(得分:-1)
拨打这样的服务电话:
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负责网络上的序列化和反序列化