Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
387 views
in Technique[技术] by (71.8m points)

c# - Strings sent through Web API's gets wrapped in quotes

I've run into a small problem with my Web API's in ASP.NET 4, using C#. I'm trying to create a front-end GUI which sends and receives data through multiple Web API's. The reason for having more than one API has to do with our network, which consists of several secure zones. The servers are placed in different zones, and a simple request may have to pass through as much as 3 different API's.

Specifically, I'm sending a JSON object from the GUI to the first API. The JSON object is supposed to be forwarded to the next API and the next - and from there a new JSON object is created and returned down the same path.

The path itself works fine. The problem is that the JSON object cannot be parsed once it returns to the GUI. I am receiving a JSON string that has been wrapped in quotes, once for each API.

The string may start out like this:

Hey! I am a string, or a JSON object of sorts!

The first hop between API's gives me this:

"Hey! I am a string, or a JSON object of sorts!"

After the next hop it looks like this:

""Hey! I am a string, or a JSON object of sorts!""

And by the time my GUI gets hold of it we have something like this:

"""Hey! I am a string, or a JSON object of sorts!"""

This is where parsing fails, for obvious reasons. The JSON object itself is properly formatted, but all the quotes are causing problems for the JSON.net parser (all quotes inside the object are also wrapped multiple times).

What I've tried so far is sending the request as a application/json type, and a text/plain type. Both did the same thing. The API's return a HttpResponseMessage, which are read using ReadAsStringAsync(). I've also tried to avoid the string reading and just read directly from the HttpRequestMessage into a HttpResponseMessage and do ReadAsStringAsync() only in the GUI, but the problem still remain. The JSON string is created using JSON.nets Serialize()-method, and put into the HttpContent using StringContent(). This seems to do the job correctly. I believe that the quotes are generated when the API's and the GUI receives the HttpResponseMessage.

Any idea how I can send and receive the JSON string as a raw string, that is not treated in any way?

I can bypass this behaviour by parsing the object to a JToken or JObject at each API, and serializing it again. This isn't a good solution, however - I would rather the API's just forward the message exactly the way they got it, and not do anything with it. I looked into forwards using routing, but there is a lot of authorization-stuff going on, which do require that I use an API action, and not a redirect route.

To clarify (TLDR): The ideal solution would be for the API's to simply pass along the message without parsing or reading anything into it. As long as the source of the message is authorized, the request is encrypted and the requested URL is valid, the message itself doesn't matter much to each of the "proxy" API's.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

The quotes and backslashes are being added at each "proxy" API as the JSON string is re-serialized for each response, not when the response is received.

In your proxy API, presumably you are doing something like this (error handling omitted for brevity):

[HttpGet]
public async Task<HttpResponseMessage> GetWidget(int id)
{
    HttpClient client = new HttpClient();
    string url = "http://nextapiserver.example.org/widgets/" + id;
    string json = await client.GetStringAsync(url);
    return Request.CreateResponse(HttpStatusCode.OK, json);
}

The problem here is that Web API assumes by default that it is responsible for serializing anything you give it. For most use cases, this is exactly what you would want. But if your content is already serialized to JSON, Web API has no way of knowing that; it will happily re-serialize the string, adding extra quotes and backslashes in the process.

To pass through a JSON string untouched, you need to explicitly create the response content object (rather than letting Web API create it), making sure to set the media type to so that downstream clients will still interpret it as JSON (rather than plain text). Here is the revised code:

[HttpGet]
public async Task<HttpResponseMessage> GetWidget(int id)
{
    HttpClient client = new HttpClient();
    string url = "http://nextapiserver.example.org/widgets/" + id;
    string json = await client.GetStringAsync(url);
    HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.OK);
    response.Content = new StringContent(json, Encoding.UTF8, "application/json");
    return response;
}

I'm sure the above can improved, but that is the gist of it. Give it a shot and see if it solves the issue for you. Note that you will need to apply this fix on all the proxy APIs.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...