What should `ReadAsAsync` and `ReadAsStrin

2020-04-02 08:34发布

问题:

What should HttpContentExtensions.ReadAsAsync<string> and HttpContent.ReadAsStringAsync be used for?

They would seem to do similiar things but work in curious ways. A couple of tests and their outputs are below. In some cases JsonReaderException are thrown, in some cases, the JSON is output but with additional escape characters.

I've ended up using both functions across my code base, but was hoping to align on one if I could understand how they were supposed to work.

//Create data and serialise to JSON
var data = new
{
    message = "hello world"
};
string dataAsJson = JsonConvert.SerializeObject(data);

//Create request with data
HttpConfiguration config = new HttpConfiguration();
HttpRequestMessage request = new HttpRequestMessage();
request.SetConfiguration(config);
request.Method = HttpMethod.Post;
request.Content = new StringContent(dataAsJson, Encoding.UTF8, "application/json");

string requestContentT = request.Content.ReadAsAsync<string>().Result; // -> JsonReaderException: Error reading string.Unexpected token: StartObject.Path '', line 1, position 1.
string requestContentS = request.Content.ReadAsStringAsync().Result; // -> "{\"message\":\"hello world\"}"

//Create response from request with same data
HttpResponseMessage responseFromRequest = request.CreateResponse(HttpStatusCode.OK, dataAsJson, "application/json");

string responseFromRequestContentT = responseFromRequest.Content.ReadAsAsync<string>().Result; // -> "{\"message\":\"hello world\"}"
string responseFromRequestContentS = responseFromRequest.Content.ReadAsStringAsync().Result; // -> "\"{\\\"message\\\":\\\"hello world\\\"}\""

//Create a standalone new response
HttpResponseMessage responseNew = new HttpResponseMessage();
responseNew.Content = new StringContent(dataAsJson, Encoding.UTF8, "application/json");

string responseNewContentT = responseNew.Content.ReadAsAsync<string>().Result; // -> JsonReaderException: Error reading string.Unexpected token: StartObject.Path '', line 1, position 1.
string responseNewContentS = responseNew.Content.ReadAsStringAsync().Result; // -> "{\"message\":\"hello world\"}"

回答1:

ReadAsStringAsync: This is a basic "get me the content as a string" method. It will work on anything you throw at it because it's just strings.

ReadAsAsync<T>: This is meant to be used to deserialise a JSON response into an object. The reason it fails is because the JSON in the return is not a valid JSON representation of a single string. For example, if you serialise a string:

var result = JsonConvert.SerializeObject("hello world");
Console.WriteLine(result);

Output is:

"hello world"

Note how it is surrounded by double quotes. If you try to deserialise any arbitrary JSON directly into a string that isn't in the format "....." it will throw the exception you see because it is expecting the JSON to start with a ".