Question

I want to use ReadAsAsync() in my mvc project with .net 4.0. The result comes as null.

If I enter the uri to address bar, the result in chrome as(tag names are changed):

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

If I use the statement in code :

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

the message comes in string format as "{\"MyListResponse\":{\"customerSessionId\"...}" which corresponds to a json object as:

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

and the properties of result1 and result2 came as null or default values. Class definitions are below. I want to read the content as an object but I couldn't. What do you advice to solve this? What am I doing wrong? Thanks in advance.

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; }
}
Était-ce utile?

La solution

I defined a new class as:

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

then I used this wrapper with,

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

then it worked. I need only MySummary object but I should write more classes to make it work.

Autres conseils

After reading your solution I came up with one that doesn't need an extra class:

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

For the sake of future readers, I think the correct approach is using ReadAsAsync overload that takes IEnumerable<MediaTypeFormatter> and provide a formatter with the same settings used on the server for serialization. That should fix it.

It is possible to use at client ReadAsAsync with MyListResponse directly (in consequence without ResponseWrapper). To do this, you can define "BodyStyle = WebMessageBodyStyle.Bare" in the operation contract of "apiuri" in stead of "BodyStyle = WebMessageBodyStyle.Wrapped" (server side, i.e. service contract).

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top