31

我有一个看起来有点像这样的 Web API 方法:

    [HttpPost]
    public ResponseMessageResult Post(Thing thing)
    {
        var content = "\r";
        var httpResponseMessage = Request.CreateResponse(HttpStatusCode.Accepted, content);
        return ResponseMessage(httpResponseMessage);
    }

在其他一些客户端代码中,当我调用时:

    var content = httpResponseMessage.Content.ReadAsStringAsync().Result;

content是:

    "\\r"

但我希望它保持原样:

    "\r"

为什么客户端会收到双重转义的字符串,我该如何防止它发生?

4

6 回答 6

57

我知道这样做可能会导致执行 70 亿行代码(对不起 Darrel Miller),但我发现使用它同样有效,并且对我选择的开发模式的破坏性更小:

response.Content.ReadAsAsync<string>().Result;

或者

await response.Content.ReadAsAsync<string>();

而不是这个(转义引号):

response.Content.ReadAsStringAsync().Result;

注意:是程序集中, 中ReadAsAsync的扩展方法。如果它在您的项目中不可用,您可以添加 NuGet 包。System.Net.Http.HttpContentExtensionsSystem.Net.Http.FormattingMicrosoft.AspNet.WebApi.Client

于 2015-12-30T09:04:44.573 回答
25

它正在做它正在做的事情,因为你正在用大锤敲打鸡蛋。

当您打电话时,Request.CreateResponse<string>(HttpStatusCode statusCode, T value)您是在告诉 Web API 您希望使用其中一种媒体类型格式化程序对您的值进行序列化。因此,Web API 将您value塞入 ObjectContent 的实例中,执行大量连接代码,并确定它可以使用 Formatter X 序列化您的“对象”。

可能是 JSONSerializer 正在尽最大努力尝试返回它认为你想要的字符串而不是 CR 字符。

无论如何,您可以使用专为通过网络发送简单字符串而设计的 HttpContent 对象来切入正题并避免执行 70 亿行代码。

[HttpPost]
public ResponseMessageResult Post(Thing thing)
{
    var content = "\r";
    var httpResponseMessage = new HttpResponseMessage(HttpStatusCode.Accepted) {
      RequestMessage = Request,
      Content = new StringContent(content)
    };
    return ResponseMessage(httpResponseMessage);
}
于 2013-11-05T15:39:21.820 回答
1
     [HttpPost]
     public async Task<string> Post(Thing thing)
     {
         var content = "\r";
         var httpResponseMessage = Request.CreateResponse(HttpStatusCode.Accepted, content);
         var escapedString = await httpResponseMessage.Content.ReadAsStringAsync();
         return Content(escapedString, "application/json");            
     }  
于 2018-09-12T14:27:51.663 回答
1

在我的特定情况下,面临同样的问题并希望它可以帮助其他人,这是由于不必要地添加了行

httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

到我的代码。在我的 Azure 函数中删除这条线摆脱了双重转义。

于 2020-07-01T19:32:14.140 回答
0

您没有收到@"\\r"返回的值,而是收到了"\\r"- 您不会在响应中得到逐字字符,因为逐字字符只是以特定方式转义字符串的指令 - 逐字修饰符本身不存储为一部分的字符串。结果是您应用逐字修饰符的适当转义版本。

ie@"\r"为您提供字符串"\\r",当应用于文本框时,该字符串显示为\r- 转义的反斜杠和“r”。

您只需要从初始分配中删除逐字修饰符。

ReadAsStringAsync这与- 您只是首先分配了错误的字符串文字无关。

于 2013-11-05T14:07:51.073 回答
0

如果您要输出一个字面的两个字符\r序列("\\r"以 C# 形式),那么这几乎肯定是您输入的内容。您说您的 Web API 方法“看起来有点像这样”。我强烈怀疑问题在于您在问题中发布的内容与实际实施中的内容之间存在差异。

您需要验证您的响应消息是否包含实际的回车符而不是文字文本"\r"。文本阅读 API 不会查找文字 C# 转义序列并专门处理它们,因为 C# 字符串转义序列在纯文本中没有意义。如果您的文本文件包含 text c:\name.txt,那么您不会期望文本读取 API 将其读取为c:<NEWLINE>ame.txt.

如果要查找和转换 C# 样式的转义序列,则必须自己完成。您可以使用这样的方法(根据需要添加其他转义序列):

private static string Unescape(string value) {
    if (value == null)
        return null;

    var length = value.Length;
    var result = new StringBuilder(length);

    for (var i = 0; i < length; i++) {
        var c = value[i];

        if (c == '\\' && i++ < length) {
            c = value[i];

            switch (c) {
                case 'n':
                    result.Append('\n');
                    break;
                case 'r':
                    result.Append('\r');
                    break;
                case 't':
                    result.Append('\t');
                    break;
                case '\\':
                    result.Append('\\');
                    break;
                default:
                    result.Append(c);
                    break;
            }
        }
        else {
            result.Append(c);
        }
    }

    return result.ToString();
}
于 2013-11-05T14:19:01.950 回答