c# - 通过 Web API 发送的字符串用引号括起来

标签 c# json api asp.net-web-api

我在 ASP.NET 4 中使用 C# 的 Web API 遇到了一个小问题。我正在尝试创建一个前端 GUI,它通过多个 Web API 发送和接收数据。拥有多个 API 的原因与我们的网络有关,该网络由多个安全区域组成。服务器位于不同的区域,一个简单的请求可能需要通过多达 3 个不同的 API。

具体来说,我将一个 JSON 对象从 GUI 发送到第一个 API。 JSON 对象应该被转发到下一个 API 和下一个 - 并且从那里创建一个新的 JSON 对象并沿相同的路径返回。

路径本身运行良好。问题是 JSON 对象一旦返回 GUI 就无法解析。我收到一个用引号括起来的 JSON 字符串,每个 API 一次。

字符串的开头可能是这样的:

嘿!我是一个字符串,或者是一个 JSON 对象!

API 之间的第一跳给了我这个:

“嘿!我是一个字符串,或者某种 JSON 对象!”

下一跳之后是这样的:

"\"嘿!我是一个字符串,或者是一个 JSON 对象!\""

当我的 GUI 掌握它时,我们已经有了这样的东西:

"\"\\\"嘿!我是一个字符串,或者是一个JSON对象!\\\"\""

这是解析失败的地方,原因很明显。 JSON 对象本身格式正确,但所有引号都导致 JSON.net 解析器出现问题(对象内的所有引号也被多次包装)。

到目前为止,我尝试将请求作为 application/json 类型和 text/plain 类型发送。两者都做了同样的事情。 API 返回一个 HttpResponseMessage,使用 ReadAsStringAsync() 读取。我还尝试避免读取字符串,直接从 HttpRequestMessage 读取到 HttpResponseMessage 并仅在 GUI 中执行 ReadAsStringAsync(),但问题仍然存在。 JSON 字符串是使用 JSON.nets Serialize() 方法创建的,并使用 StringContent() 放入 HttpContent。这似乎正确地完成了这项工作。我相信引号是在 API 和 GUI 收到 HttpResponseMessage 时生成的。

知道如何将 JSON 字符串作为原始字符串发送和接收,不以任何方式处理吗?

我可以通过在每个 API 上将对象解析为 JToken 或 JObject 并再次对其进行序列化来绕过此行为。然而,这不是一个好的解决方案——我宁愿 API 只是按照他们得到的方式转发消息,而不是对它做任何事情。我使用路由研究了转发,但是有很多授权的东西,这确实需要我使用 API 操作,而不是重定向路由。

澄清 (TLDR):理想的解决方案是让 API 简单地传递消息而不解析或读取任何内容。只要消息的来源被授权,请求被加密并且请求的 URL 是有效的,消息本身对每个“代理”API 并不重要。

最佳答案

在每个“代理”API 中添加引号和反斜杠,因为 JSON 字符串会针对每个响应进行重新序列化,而不是在收到响应时。

在您的代理 API 中,大概您正在做这样的事情(为简洁起见,省略了错误处理):

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

这里的问题是 Web API 默认假设它负责序列化你给它的任何东西。对于大多数用例,这正是您想要的。但如果您的内容已经序列化为 JSON,Web API 无法知道这一点;它会愉快地重新序列化字符串,在此过程中添加额外的引号和反斜杠。

若要传递一个未触及的 JSON 字符串,您需要显式创建响应内容对象(而不是让 Web API 创建它),确保将媒体类型设置为以便下游客户端仍将其解释为 JSON(而不是比纯文本)。这是修改后的代码:

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

我确信以上内容可以改进,但这就是它的要点。试一试,看看它是否可以为您解决问题。请注意,您需要在所有代理 API 上应用此修复。

关于c# - 通过 Web API 发送的字符串用引号括起来,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33681978/

相关文章:

java - 从API获取数据到字符串中

c# - HTML5 视频的 ASP.NET MVC4 媒体源 Url

c# - 应用程序在空闲一段时间后卡住

javascript - 打开excel文件并导出到json

java - 在 Spring Session JDBC 中使用 JSON 格式

python - 我的 Flask REST API 有多安全?

python - 在谷歌中使用 unicode 从 python 脚本翻译 url

c# - Winforms - 在执行长时间运行的同步请求期间如何保持窗口完全绘制/响应?

c# - 如何通过 REST API 创建 Azure Application Insights 的新实例

javascript - 存储从jquery post返回的json数据