JSON per POST in C # senden und JSON zurückerhalten?

86

Dies ist das erste Mal, dass ich JSON sowie System.Netdas WebRequestin einer meiner Anwendungen verwende. Meine Anwendung soll eine JSON-Nutzlast, ähnlich der folgenden, an einen Authentifizierungsserver senden:

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

Um diese Nutzdaten zu erstellen, habe ich die JSON.NETBibliothek verwendet. Wie würde ich diese Daten an den Authentifizierungsserver senden und die JSON-Antwort zurückerhalten? Folgendes habe ich in einigen Beispielen gesehen, aber keinen JSON-Inhalt:

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();

Dies scheint jedoch eine Menge Code zu sein, der mit der Verwendung anderer Sprachen verglichen wird, die ich in der Vergangenheit verwendet habe. Mache ich das richtig Und wie würde ich die JSON-Antwort zurückbekommen, damit ich sie analysieren kann?

Danke, Elite.

Code aktualisiert

// 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();
    }
}
Hunter Mitchell
quelle
2
Sie können versuchen WebClient.UploadString(JsonConvert.SerializeObjectobj(yourobj))oderHttpClient.PostAsJsonAsync
LB

Antworten:

135

Ich habe die HttpClient- Bibliothek zum Abfragen von RESTful-APIs verwendet, da der Code sehr einfach und vollständig asynchron ist.

(Bearbeiten: Hinzufügen von JSON aus Frage zur Klarheit)

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

Mit zwei Klassen, die die von Ihnen veröffentlichte JSON-Struktur darstellen, könnte dies folgendermaßen aussehen:

public class Credentials
{
    [JsonProperty("agent")]
    public Agent Agent { get; set; }

    [JsonProperty("username")]
    public string Username { get; set; }

    [JsonProperty("password")]
    public string Password { get; set; }

    [JsonProperty("token")]
    public string Token { get; set; }
}

public class Agent
{
    [JsonProperty("name")]
    public string Name { get; set; }

    [JsonProperty("version")]
    public int Version { get; set; }
}

Sie könnten eine Methode wie diese haben, die Ihre POST-Anfrage erledigt:

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 = await Task.Run(() => 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");

using (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
    }
}
Kai Eichinger
quelle
5
perfekt, aber was erwartet Task.run (()?
Hunter Mitchell
23
Sie sollten Task.Run nicht für synchrone CPU-gebundene Methoden verwenden, da Sie nur einen neuen Thread ohne Nutzen auslösen!
Stephen Foster
2
Sie müssen das nicht JsonPropertyfür jede Eigenschaft eingeben. Verwenden Sie einfach den in CamelCasePropertyNamesContractResolver integrierten Json.Net oder einen benutzerdefiniertenNamingStrategy , um den Serialisierungsprozess anzupassen
Seafish
6
Randnotiz: Verwenden Sie kein usingmit HttpClient. Siehe: aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong
maxshuty
4
Mit System.Net.Http.Formatting haben Sie Erweiterungsmethoden definiert: "Warten Sie auf httpClient.PostAsJsonAsync (" api / v1 / domain ", csObjRequest)"
hB0
14

Mit dem JSON.NET NuGet-Paket und anonymen Typen können Sie vereinfachen, was die anderen Poster vorschlagen:

// ...

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

// ...
Maximilian Burszley
quelle
6

Sie können Ihre erstellen, HttpContentindem Sie die Kombination aus verwenden JObject, um zu vermeiden, JPropertyund sie dann ToString()beim Erstellen der folgenden Elemente aufrufen StringContent:

        /*{
          "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);
            }
        }
Jan Dolejsi
quelle
Wie vermeidet man Exception while executing function. Newtonsoft.Json: Can not add Newtonsoft.Json.Linq.JProperty to Newtonsoft.Json.Linq.JArrayFehler?
Jari Turkia
1
Eine HttpClient-Instanz soll nicht mit using construct erstellt werden. Die Instanz sollte einmal erstellt und in der gesamten Anwendung verwendet werden. Dies liegt daran, dass ein eigener Verbindungspool verwendet wird. Ihr Code löst meistens SocketException aus. docs.microsoft.com/en-us/dotnet/api/…
Harun Diluka Heshan
2

Sie können auch die in HttpClient () verfügbare PostAsJsonAsync () -Methode verwenden.

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

Rukshala Weerasinghe
quelle
1
Können Sie bitte eine Erklärung hinzufügen, was Ihr Code tut und wie er das Problem löst?
Nilambar Sharma
Sie können jedes Objekt, das Sie veröffentlichen möchten, mit SerializeObject () serialisieren. var obj= new Credentials { Agent = new Agent { Name = "Agent Name", Version = 1 }, Username = "Username", Password = "User Password", Token = "xxxxx" }; Und ohne es in httpContent konvertieren zu müssen, können Sie PostAsJsonAsync () verwenden, indem Sie die Endpunkt-URL und das konvertierte JSON-Objekt selbst übergeben.
Rukshala Weerasinghe