JSON-Daten von HTTP-Anforderung zurückerhalten

97

Ich habe eine Webanforderung, die ordnungsgemäß funktioniert, aber nur den Status OK zurückgibt, aber ich benötige das Objekt, das ich für die Rückgabe anfordere. Ich bin nicht sicher, wie ich den von mir angeforderten JSON-Wert erhalten soll. Ich bin neu in der Verwendung des Objekts HttpClient. Gibt es eine Eigenschaft, die mir fehlt? Ich brauche das zurückkehrende Objekt wirklich. Vielen Dank für jede Hilfe

Anruf tätigen - läuft gut, gibt den Status OK zurück.

HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Accept
  .Add(new MediaTypeWithQualityHeaderValue("application/json"));
var responseMsg = client.GetAsync(string.Format("http://localhost:5057/api/Photo")).Result;

Die API-Get-Methode

//Cut out alot of code but you get the idea
public string Get()
{
    return JsonConvert.SerializeObject(returnedPhoto);
}
user516883
quelle
Fragen Sie, wie Sie den Antwortinhalt erhalten, wenn Sie die .NET 4.5 HttpClient-Klasse verwenden?
Panagiotis Kanavos

Antworten:

165

Wenn Sie in .NET 4.5 auf System.Net.HttpClient verweisen, können Sie den von GetAsync zurückgegebenen Inhalt mithilfe der Eigenschaft HttpResponseMessage.Content als von HttpContent abgeleitetes Objekt abrufen. Anschließend können Sie den Inhalt mit der Methode HttpContent.ReadAsStringAsync oder als Stream mit der Methode ReadAsStreamAsync in eine Zeichenfolge einlesen .

Die Dokumentation zur HttpClient- Klasse enthält dieses Beispiel:

  HttpClient client = new HttpClient();
  HttpResponseMessage response = await client.GetAsync("http://www.contoso.com/");
  response.EnsureSuccessStatusCode();
  string responseBody = await response.Content.ReadAsStringAsync();
Panagiotis Kanavos
quelle
3
Ich habe dies nicht getestet, aber in der Dokumentation von EnsureSuccessStatusCode heißt es: "Wenn der Inhalt nicht null ist, ruft diese Methode auch Dispose für frei verwaltete und nicht verwaltete Ressourcen auf." Vielleicht möchten Sie zuerst den Inhalt lesen. msdn.microsoft.com/en-us/library/…
Ryan Williams
4
Kein Grund dafür. Wie von Reflector belegt, wird EnsureSuccessStatusCode NUR dann entsorgt, wenn der Statuscode nicht erfolgreich ist, unmittelbar bevor eine Ausnahme ausgelöst wird. Ein weiterer Fall, in dem der Dokumentationstext etwas verwirrend ist.
Panagiotis Kanavos
1
Warum nicht einfach client.GetStringAsync(...)? Gab es das nicht im Jahr 2012. Beide würden eine Ausnahme auslösen, wenn die Antwort nicht 200richtig wäre?
Simon_Weaver
1
@Simon_Weaver, weil das nicht die Frage war - das OP fragte, wie die Zeichenfolge aus der Antwort gelesen werden soll. Es gibt Unterschiede. Sie können die Antwort nicht überprüfen, GetStringAsyncwas bedeutet, dass Sie nicht wissen, wie die Antwortnachricht lautete. Sie möchten wahrscheinlich nicht werfen, wenn eine 3xx-Antwort zurückgegeben wird. Sie möchten es wahrscheinlich erneut versuchen, ohne zu werfen, wenn ein Drosselungsfehler zurückgegeben wird.
Panagiotis Kanavos
1
@Simon_Weaver Es gibt viele Möglichkeiten, diesen Anruf zu tätigen - warum nicht GetAsync<T>? Oder GetStreamAsync und den Stream an Json.NET übergeben, wobei die temporäre Zeichenfolge vermieden wird? Auch hier kann es vorzuziehen sein, GetAsynczuerst zu verwenden und dann auf das
Inhaltsobjekt
43

Aufbauend auf der Antwort von @Panagiotis Kanavos finden Sie hier eine Arbeitsmethode als Beispiel, die die Antwort auch als Objekt anstelle einer Zeichenfolge zurückgibt :

using System.Text;
using System.Net.Http;
using System.Threading.Tasks;
using Newtonsoft.Json; // Nuget Package

public static async Task<object> PostCallAPI(string url, object jsonObject)
{
    try
    {
        using (HttpClient client = new HttpClient())
        {
            var content = new StringContent(jsonObject.ToString(), Encoding.UTF8, "application/json");
            var response = await client.PostAsync(url, content);
            if (response != null)
            {
                var jsonString = await response.Content.ReadAsStringAsync();
                return JsonConvert.DeserializeObject<object>(jsonString);
            }
        }
    }
    catch (Exception ex)
    {
        myCustomLogger.LogException(ex);
    }
    return null;
}

Beachten Sie, dass dies nur ein Beispiel ist und dass Sie es wahrscheinlich HttpClientals gemeinsam genutzte Instanz verwenden möchten, anstatt es in einer using-Klausel zu verwenden.

Wouter Vanherck
quelle
Seien Sie vorsichtig, httpclient entsorgt nicht so mit der using statment
rogue39nin
Da warte Rückgaben sofort, ist es möglich, dass if (response != null)ausgeführt wird, bevor der Post-Call abgeschlossen ist?
Nishant
8

Ich denke, der kürzeste Weg ist:

var client = new HttpClient();
string reqUrl = $"http://myhost.mydomain.com/api/products/{ProdId}";
var prodResp = await client.GetAsync(reqUrl);
if (!prodResp.IsSuccessStatusCode){
    FailRequirement();
}
var prods = await prodResp.Content.ReadAsAsync<Products>();
Greg Z.
quelle
8
Ich dachte nur, ich würde hinzufügen, dass ReadAsAsync eine Erweiterungsmethode ist. Sie müssen System.Net.Http.Formatting für .net 4+ und Microsoft.AspNet.WebApi.Client für .net Core verwenden. um das zum Laufen zu bringen.
Squibly
0

Was ich normalerweise mache, ähnlich wie bei einer Antwort:

var response = await httpClient.GetAsync(completeURL); // http://192.168.0.1:915/api/Controller/Object

if (response.IsSuccessStatusCode == true)
    {
        string res = await response.Content.ReadAsStringAsync();
        var content = Json.Deserialize<Model>(res);

// do whatever you need with the JSON which is in 'content'
// ex: int id = content.Id;

        Navigate();
        return true;
    }
    else
    {
        await JSRuntime.Current.InvokeAsync<string>("alert", "Warning, the credentials you have entered are incorrect.");
        return false;
    }

Wobei 'model' Ihre C # -Modellklasse ist.

James Heffer
quelle
0

Es funktioniert gut für mich auf folgende Weise -

public async Task<object> TestMethod(TestModel model)
    {
        try
        {
            var apicallObject = new
            {
                Id= model.Id,
                name= model.Name
            };

            if (apicallObject != null)
            {
                var bodyContent = JsonConvert.SerializeObject(apicallObject);
                using (HttpClient client = new HttpClient())
                {
                    var content = new StringContent(bodyContent.ToString(), Encoding.UTF8, "application/json");
                    content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
                    client.DefaultRequestHeaders.Add("access-token", _token); // _token = access token
                    var response = await client.PostAsync(_url, content); // _url =api endpoint url
                    if (response != null)
                    {
                        var jsonString = await response.Content.ReadAsStringAsync();

                        try
                        {
                            var result = JsonConvert.DeserializeObject<TestModel2>(jsonString); // TestModel2 = deserialize object
                        }
                        catch (Exception e){
                            //msg
                            throw e;
                        }
                    }
                }
            }
        }
        catch (Exception ex)
        {
            throw ex;
        }
        return null;
    }
bulbul bd
quelle