In our API client library all HttpResponseMessage responses are handled by the following function:
private async Task<ApiResponse<TResult>> ReadResponseAsync<TResult>(HttpResponseMessage response)
{
Ensure.Argument.NotNull(response, "response");
var apiResponse = new ApiResponse<TResult>();
if (response.IsSuccessStatusCode)
{
apiResponse.Content = await response.Content.ReadAsAsync<TResult>().ConfigureAwait(false);
}
else
{
apiResponse.Error = await response.Content.ReadAsAsync<HttpError>().ConfigureAwait(false);
}
return apiResponse;
}
If the response is not successful we deserialize the `HttpError` instance from the response body.
The main purpose of this is so that we can return any model state errors (HttpError["ModelState"]) back to the consumer.
Unfortunately, the deserialization of ModelState is not consistent for all formatters. When using the JsonMediaTypeFormatter, the ModelState is actually of type JObject, not the HttpError/Dictionary instance that was actually serialized.
So currently I have to resort to this hack to deserialize the ModelState:
public static ModelStateDictionary GetModelState(this HttpError httpError)
{
Ensure.Argument.NotNull(httpError, "httpError");
object serialized;
if (httpError.TryGetValue("ModelState", out serialized))
{
var modelState = new ModelStateDictionary();
if (serialized is JObject)
{
GetModelStateFromJObject((JObject)serialized, modelState);
}
else if (serialized is IDictionary<string, object>)
{
GetModelStateFromDictionary((IDictionary<string, object>)serialized, modelState);
}
return modelState;
}
return null;
}
Comments: It should be possible to use Json.NET to deserialize the JObject as an HttpError.
private async Task<ApiResponse<TResult>> ReadResponseAsync<TResult>(HttpResponseMessage response)
{
Ensure.Argument.NotNull(response, "response");
var apiResponse = new ApiResponse<TResult>();
if (response.IsSuccessStatusCode)
{
apiResponse.Content = await response.Content.ReadAsAsync<TResult>().ConfigureAwait(false);
}
else
{
apiResponse.Error = await response.Content.ReadAsAsync<HttpError>().ConfigureAwait(false);
}
return apiResponse;
}
If the response is not successful we deserialize the `HttpError` instance from the response body.
The main purpose of this is so that we can return any model state errors (HttpError["ModelState"]) back to the consumer.
Unfortunately, the deserialization of ModelState is not consistent for all formatters. When using the JsonMediaTypeFormatter, the ModelState is actually of type JObject, not the HttpError/Dictionary instance that was actually serialized.
So currently I have to resort to this hack to deserialize the ModelState:
public static ModelStateDictionary GetModelState(this HttpError httpError)
{
Ensure.Argument.NotNull(httpError, "httpError");
object serialized;
if (httpError.TryGetValue("ModelState", out serialized))
{
var modelState = new ModelStateDictionary();
if (serialized is JObject)
{
GetModelStateFromJObject((JObject)serialized, modelState);
}
else if (serialized is IDictionary<string, object>)
{
GetModelStateFromDictionary((IDictionary<string, object>)serialized, modelState);
}
return modelState;
}
return null;
}
Comments: It should be possible to use Json.NET to deserialize the JObject as an HttpError.