在 C# 中通过 POST 发送 JSON 并接收返回的 JSON?

Posted

技术标签:

【中文标题】在 C# 中通过 POST 发送 JSON 并接收返回的 JSON?【英文标题】:Send JSON via POST in C# and Receive the JSON returned? 【发布时间】:2014-05-10 20:23:18 【问题描述】:

这是我第一次在我的任何应用程序中使用 JSON 以及 System.NetWebRequest。我的应用程序应该向身份验证服务器发送一个类似于下面的 JSON 有效负载:


  "agent":                              
    "name": "Agent Name",                
    "version": 1                                                          
  ,
  "username": "Username",                                   
  "password": "User Password",
  "token": "xxxxxx"

为了创建这个有效载荷,我使用了JSON.NET 库。我如何将此数据发送到身份验证服务器并接收其 JSON 响应?这是我在一些示例中看到的,但没有 JSON 内容:

var http = (HttpWebRequest)WebRequest.Create(new Uri(baseUrl));
http.Accept = "application/json";
http.ContentType = "application/json";
http.Method = "POST";

string parsedContent = "Parsed JSON Content needs to go here";
ASCIIEncoding encoding = new ASCIIEncoding();
Byte[] bytes = encoding.GetBytes(parsedContent);

Stream newStream = http.GetRequestStream();
newStream.Write(bytes, 0, bytes.Length);
newStream.Close();

var response = http.GetResponse();

var stream = response.GetResponseStream();
var sr = new StreamReader(stream);
var content = sr.ReadToEnd();

但是,与我过去使用过的其他语言相比,这似乎是很多代码。我这样做正确吗?以及如何获取 JSON 响应以便进行解析?

谢谢,精英。

更新代码

// Send the POST Request to the Authentication Server
// Error Here
string json = await Task.Run(() => JsonConvert.SerializeObject(createLoginPayload(usernameTextBox.Text, password)));
var httpContent = new StringContent(json, Encoding.UTF8, "application/json");
using (var httpClient = new HttpClient())

    // Error here
    var httpResponse = await httpClient.PostAsync("URL HERE", httpContent);
    if (httpResponse.Content != null)
    
        // Error Here
        var responseContent = await httpResponse.Content.ReadAsStringAsync();
    

【问题讨论】:

你可以试试WebClient.UploadString(JsonConvert.SerializeObjectobj(yourobj))HttpClient.PostAsJsonAsync 【参考方案1】:

我发现自己使用HttpClient 库来查询 RESTful API,因为代码非常简单且完全异步。要发送此 JSON 有效负载:


  "agent":                              
    "name": "Agent Name",                
    "version": 1                                                          
  ,
  "username": "Username",                                   
  "password": "User Password",
  "token": "xxxxxx"

有两个类代表您发布的 JSON 结构,可能如下所示:

public class Credentials

    public Agent Agent  get; set; 
    
    public string Username  get; set; 
    
    public string Password  get; set; 
    
    public string Token  get; set; 


public class Agent

    public string Name  get; set; 
    
    public int Version  get; set; 

您可以使用这样的方法来执行您的 POST 请求:

var payload = new Credentials  
    Agent = new Agent  
        Name = "Agent Name",
        Version = 1 
    ,
    Username = "Username",
    Password = "User Password",
    Token = "xxxxx"
;

// Serialize our concrete class into a JSON String
var stringPayload = JsonConvert.SerializeObject(payload);

// Wrap our JSON inside a StringContent which then can be used by the HttpClient class
var httpContent = new StringContent(stringPayload, Encoding.UTF8, "application/json");

var httpClient = new HttpClient()
    
// Do the actual request and await the response
var httpResponse = await httpClient.PostAsync("http://localhost/api/path", httpContent);

// If the response contains content we want to read it!
if (httpResponse.Content != null) 
    var responseContent = await httpResponse.Content.ReadAsStringAsync();
    
    // From here on you could deserialize the ResponseContent back again to a concrete C# type using Json.Net

【讨论】:

完美,但是 await Task.run(() 是什么? 您不应该在同步 CPU 绑定方法上使用 Task.Run,​​因为您只是启动一个新线程而没有任何好处! 您不必为每个属性都输入JsonProperty。只需使用 Json.Net 内置的CamelCasePropertyNamesContractResolver 或custom NamingStrategy 来自定义序列化过程 旁注:不要将usingHttpClient 一起使用。见:aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong 使用 System.Net.Http.Formatting 您定义了扩展方法:"await httpClient.PostAsJsonAsync("api/v1/domain", csObjRequest)"【参考方案2】:

使用 JSON.NET NuGet 包和匿名类型,您可以简化其他发帖人的建议:

// ...

string payload = JsonConvert.SerializeObject(new

    agent = new
    
        name    = "Agent Name",
        version = 1,
    ,

    username = "username",
    password = "password",
    token    = "xxxxx",
);

var client = new HttpClient();
var content = new StringContent(payload, Encoding.UTF8, "application/json");

HttpResponseMessage response = await client.PostAsync(uri, content);

// ...

【讨论】:

【参考方案3】:

您可以使用JObject 的组合来构建您的HttpContent 来避免和JProperty,然后在构建StringContent 时调用ToString()

        /*
          "agent":                              
            "name": "Agent Name",                
            "version": 1                                                          
          ,
          "username": "Username",                                   
          "password": "User Password",
          "token": "xxxxxx"
        */

        JObject payLoad = new JObject(
            new JProperty("agent", 
                new JObject(
                    new JProperty("name", "Agent Name"),
                    new JProperty("version", 1)
                    ),
                new JProperty("username", "Username"),
                new JProperty("password", "User Password"),
                new JProperty("token", "xxxxxx")    
                )
            );

        using (HttpClient client = new HttpClient())
        
            var httpContent = new StringContent(payLoad.ToString(), Encoding.UTF8, "application/json");

            using (HttpResponseMessage response = await client.PostAsync(requestUri, httpContent))
            
                response.EnsureSuccessStatusCode();
                string responseBody = await response.Content.ReadAsStringAsync();
                return JObject.Parse(responseBody);
            
        

【讨论】:

如何避免Exception while executing function. Newtonsoft.Json: Can not add Newtonsoft.Json.Linq.JProperty to Newtonsoft.Json.Linq.JArray 错误? 不应使用 using 构造创建 HttpClient 实例。该实例应创建一次并在整个应用程序中使用。这是因为它使用自己的连接池。您的代码大多倾向于抛出 SocketException。 docs.microsoft.com/en-us/dotnet/api/…【参考方案4】:

您还可以使用 HttpClient() 中提供的 PostAsJsonAsync() 方法

var requestObj= JsonConvert.SerializeObject(obj);
HttpResponseMessage response = await client.PostAsJsonAsync($"endpoint",requestObj);

【讨论】:

您能否解释一下您的代码的作用以及它如何解决问题? 你可以使用你想要发布的任何对象并使用 SerializeObject(); 对其进行序列化。 var obj= new Credentials Agent = new Agent Name = "Agent Name", Version = 1 , Username = "Username", Password = "User Password", Token = "xxxxx" ; 然后无需将其转换为 httpContent,您可以使用 PostAsJsonAsync() 传递端点 URL 和转换后的 JSON 对象本身。 仅供参考,因为 .NET4.5 左右,HttpClient 上没有 PostAsJsonAsync()

以上是关于在 C# 中通过 POST 发送 JSON 并接收返回的 JSON?的主要内容,如果未能解决你的问题,请参考以下文章

在 C# 中通过 Telnet 发送和接收命令

捕获文件在 C# 中通过蓝牙发送

求一个c#的 post请求 json 并且接收返回json数据的一个demo。

如何在 Chrome 中通过 nativeMessaging 发送/接收短信?

c# 服务端接收post过来的body内容

无法解析我的Json对象,该对象在Spring Cloud流中通过绑定器接收