webentwicklung-frage-antwort-db.com.de

Verwenden von ReadAsAsync <T> () zum Deserialisieren von komplexen Json-Objekten

Ich möchte ReadAsync () in meinem MVC-Projekt mit .net 4.0 verwenden. Das Ergebnis ist null.

Wenn ich den URI in die Adressleiste eingebe, wird das Ergebnis in Chrome as (Tag-Namen geändert):

<ns2:MyListResponse xmlns:ns2="blablabla">
  <customerSessionId>xxcustomerSessionIdxx</customerSessionId>
  <numberOfRecordsRequested>0</numberOfRecordsRequested>
  <moreResultsAvailable>false</moreResultsAvailable>
  <MyList size="1" activePropertyCount="1">
    <MySummary order="0">
      <id>1234</id>
      <name>...</name>
      .
      .   
    </MySummary>
  </MyList>
</ns2:MyListResponse>

Wenn ich die Anweisung im Code verwende:

using (var client = new HttpClient())
{
     var response = client.GetAsync(apiUri).Result;
     var message = response.Content.ReadAsStringAsync().Result;

     var result1 = JsonConvert.DeserializeObject<MyListResponse>(message);
     var result2 = response.Content.ReadAsAsync<MyListResponse>().Result;
}

die Nachricht kommt im Stringformat als "{\"MyListResponse\":{\"customerSessionId\"...}", was einem Json-Objekt entspricht:

{"MyListResponse":
    {"customerSessionId":"xxcustomerSessionIdxx",
     "numberOfRecordsRequested":0,
     "moreResultsAvailable":false,
     "MyList":
        {"@size":"1",
         "@activePropertyCount":"1",
         "MySummary":
            {"@order":"0",
             "id":1234,
             "name":"...",
             .
             .
            }
        }
    }
 } 

und die Eigenschaften von result1 und result2 kamen als Null- oder Standardwerte. Klassendefinitionen sind unten. Ich möchte den Inhalt als Objekt lesen, konnte es aber nicht. Was raten Sie, um dies zu lösen? Was mache ich falsch? Danke im Voraus.

public class MySummary
{
    public int @Order { get; set; }
    public string Id { get; set; }
    public string Name { get; set; }
    .
    .
}

public class MyList
{
    public int @Size { get; set; }
    public int @ActivePropertyCount { get; set; }
    public MySummary MySummary{ get; set; }
}

public class MyListResponse
{
    public string CustomerSessionId { get; set; }
    public int NumberOfRecordsRequested { get; set; }
    public bool MoreResultsAvailable { get; set; }
    public MyList MyList { get; set; }
}
14
serefbilge

Ich habe eine neue Klasse definiert als:

public class ResponseWrapper
{
    public MyListResponse MyListResponse { get; set; }
}

dann habe ich diesen Wrapper mit verwendet,

 var result1 = JsonConvert.DeserializeObject<ResponseWrapper>(message);
 var result2 = response.Content.ReadAsAsync<ResponseWrapper>().Result;

dann hat es funktioniert. Ich brauche nur das MySummary-Objekt, aber ich sollte mehr Klassen schreiben, damit es funktioniert.

8
serefbilge

Nachdem ich Ihre Lösung gelesen hatte, kam ich zu einer Lösung, die keine zusätzliche Klasse benötigt:

    private static async Task<U> Execute<U>(HttpClient client, string path)
    {
        U output = default(U);

        HttpResponseMessage response = await client.GetAsync(path);

        if (response.IsSuccessStatusCode)
        {
            var jsonAsString = await response.Content.ReadAsStringAsync();
            output = JsonConvert.DeserializeObject<U>(jsonAsString);
        }
        else
        {
            throw new ApplicationException(string.Format("Response message is not OK. Issues in action: {0}", path));
        }

        return output;
    }
6
RoboJ1M

Für zukünftige Leser denke ich, der korrekte Ansatz ist ReadAsAsync overload, der IEnumerable<MediaTypeFormatter> verwendet und einen Formatierer mit denselben Einstellungen bereitstellt, die auf dem Server für die Serialisierung verwendet werden. Das sollte es beheben.

4
Jony Adamit

Es ist möglich, direkt am Client ReadAsAsync mit MyListResponse zu verwenden (folglich ohne ResponseWrapper). Um dies zu erreichen, können Sie "BodyStyle = WebMessageBodyStyle.Bare" anstelle des "BodyStyle = WebMessageBodyStyle.Wrapped" (serverseitig, d.