0

I have the following code for getting a response from my server. I can deserialize the response to my ApiResponse object type, but I can't cast an inner object to it's real type.

Here is where I am getting the response from the server:

var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
    var result = streamReader.ReadToEnd();
    GlobalTestVariables.Response = JsonConvert.DeserializeObject<ApiResponse>(result);
    var a = GlobalTestVariables.Response.Result as TokenModel; // a = null
}

The value of var result = streamReader.ReadToEnd(); is as follows:

var result = "{\"IsSuccess\":true,\"Message\":\"Login Successful\",\"Result\":{\"id_token\":\"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1bmlxdWVfbmFtZSI6InBsaW10ZXN0aW5nIiwibmJmIjoxNTE1MDc5NzMyLCJleHAiOjE1MTUwODA5MzIsImlhdCI6MTUxNTA3OTczMn0.wcr5zndSwdrDL7huea_oWpAl8ohL0GL3NZOmc_VBduc\"},\"Status\":200}"

This is what's being returned:

return new ApiResponse(true, HttpStatusCode.OK, "Login Successful", new TokenModel(JwtManager.GenerateToken(user.Username)));

Where ApiResponse is:

[DataContract]
public class ApiResponse
{
    [DataMember]
    public bool IsSuccess { get; set; }
    [DataMember]
    public String Message { get; set; }
    [DataMember(EmitDefaultValue = false)]
    public Object Result { get; set; }
    [DataMember]
    public int Status { get; set; }

    public ApiResponse() { }

    public ApiResponse(bool isSuccess, HttpStatusCode statusCode, string message = null, object result = null)
    {
        IsSuccess = isSuccess;
        Status = (int)statusCode;
        Result = result;
        Message = message;
    }
}

And TokenModel is:

public class TokenModel
{
    public string id_token { get; set; }
    public TokenModel(string token)
    {
        this.id_token = token;
    }
    public TokenModel() { }
}

Does anybody know how to deserialize it to it's correct type?

Aimee Jones
  • 881
  • 2
  • 18
  • 38

2 Answers2

0

There are two options:

  1. You change the type of ApiResponse.Result to TokenModel. The deserializer then expects a TokenModel and will deserialize it appropriately.

  2. If the type of the property Result is dynamic, you need to include type information in the serialized JSON string. For that, have a look at the TypeNameHandling setting.

Oliver Hanappi
  • 12,046
  • 7
  • 51
  • 68
0

As long as Result always has id_token in the JSON, it's as simple as changing Result to TokenModel.

    [DataContract]
public class ApiResponse
{
    [DataMember]
    public bool IsSuccess { get; set; }
    [DataMember]
    public String Message { get; set; }
    [DataMember(EmitDefaultValue = false)]
    public TokenModel Result { get; set; }
    [DataMember]
    public int Status { get; set; }

    public ApiResponse() { }

    public ApiResponse(bool isSuccess, HttpStatusCode statusCode, string message = null, TokenModel result = null)
    {
        IsSuccess = isSuccess;
        Status = (int)statusCode;
        Result = result;
        Message = message;
    }
}
Nicolás de Ory
  • 614
  • 9
  • 31
  • Result could be any type of object, not just a token model. – Aimee Jones Jan 04 '18 at 17:00
  • My bad, I thought it was always `TokenModel`, from the sample JSON. In that case take a look at option 2 of Oliver's answer, or check [this question](https://stackoverflow.com/questions/13683757/newtonsoft-json-dynamic-objects). Maybe you could do `dynamic result = JObject.Parse(resultJSON);` – Nicolás de Ory Jan 04 '18 at 17:18