How to use System.Net.HttpClient to post a complex type?

前端 未结 9 503
感动是毒
感动是毒 2020-11-29 16:31

I have a custom complex type that I want to work with using Web API.

public class Widget
{
    public int ID { get; set; }
    public string Name { get; set;         


        
相关标签:
9条回答
  • 2020-11-29 16:50

    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 HttpClient and Json.NET and adds some fluent sugar and other goodies, including some baked-in testing helpers.

    Post as JSON:

    var resp = await "http://localhost:44268/api/test".PostJsonAsync(widget);
    

    or URL-encoded:

    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:

    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:

    PM> Install-Package Flurl.Http
    
    0 讨论(0)
  • 2020-11-29 16:51

    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 client = new HttpClient();
    HttpContent contentPost = new StringContent(argsAsJson, Encoding.UTF8, 
    "application/json");
    
    await client.PostAsync(new Uri(wsUrl), contentPost).ContinueWith(
    (postTask) => postTask.Result.EnsureSuccessStatusCode());
    
    0 讨论(0)
  • 2020-11-29 16:51

    After investigating lots of alternatives, I have come across another approach, suitable for the API 2.0 version.

    (VB.NET is my favorite, 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

    0 讨论(0)
  • 2020-11-29 16:52

    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:

    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));
    
    0 讨论(0)
  • 2020-11-29 17:00

    You should use the SendAsync method instead, this is a generic method, that serializes the input to the service

    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 FormUrlEncodedContent class

    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?)

    0 讨论(0)
  • 2020-11-29 17:01

    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(); });
    
    0 讨论(0)
提交回复
热议问题