如何防止ReadAsStringAsync返回双重转义的字符串?

时间:2013-11-05 13:51:25

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

我有一个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"

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

6 个答案:

答案 0 :(得分:34)

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

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

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

而不是这个(逃脱引号):

response.Content.ReadAsStringAsync().Result;

注意:ReadAsAsyncSystem.Net.Http.HttpContentExtensions汇编中System.Net.Http.Formatting的扩展方法。如果项目中没有该功能,您可以添加NuGet包Microsoft.AspNet.WebApi.Client

答案 1 :(得分:23)

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

当您致电Request.CreateResponse<string>(HttpStatusCode statusCode, T value)时,您正在告诉Web API您希望使用其中一种媒体类型格式化程序序列化您的值。因此,Web API将您的value填充到ObjectContent的实例中,执行大量的连接代码,并确定它可以使用Formatter X来序列化您的&#34;对象&#34;。

有可能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);
}

答案 2 :(得分:0)

您没有收到值@"\\r",您正在接收"\\r" - 您的回复中不会收到逐字字符,因为逐字字符只是逃避字符串的指令特殊方式 - 逐字修饰符本身不作为字符串的一部分存储。结果是您将verbatim修饰符应用到的适当转义版本。

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

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

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

答案 3 :(得分:0)

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

您需要验证您的回复消息是否包含实际的回车符,而不是文字文本"\r"。文本读取API不会查找文字C#转义序列并特别处理它们,因为C#字符串转义序列在纯文本中没有任何意义。如果您的文字文件包含文字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();
}

答案 4 :(得分:0)

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

答案 5 :(得分:0)

在我的特定情况下,面临相同的问题,希望对其他问题有所帮助,这是由于不必要地添加行造成的

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

到我的代码。在我的Azure Function中删除此行摆脱了两次转义。