How do I prevent ReadAsStringAsync returning a dou

2019-03-24 15:42发布

I have a Web API method that looks a bit like this:

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

In some other client code, when I call:

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

content is:

    "\\r"

but I would like it to remain as the original:

    "\r"

why is the client receiving a doubly escaped string and how can I prevent it happening?

5条回答
冷血范
2楼-- · 2019-03-24 16:03

You aren't receiving the value @"\\r" back, you are receiving "\\r" - you won't get a verbatim character in your response because a verbatim character is just an instruction to escape a string a particular way - the verbatim modifier itself isn't stored as part of the string. The result is the appropriately escaped version of what you applied the verbatim modifier to.

i.e. @"\r" gives you the string "\\r" which, when applied to a text box, displays as \r - an escaped backslash and an 'r'.

You just need to take the verbatim modifier off your initial assignment.

This has nothing to do with ReadAsStringAsync - you're just assigning the wrong string literal in the first place.

查看更多
We Are One
3楼-- · 2019-03-24 16:05

It is doing what it is doing because you are cracking an egg with a sledgehammer.

When you call Request.CreateResponse<string>(HttpStatusCode statusCode, T value) you are telling web API that you would like your value serialized using one of the media type formatters. So Web API stuffs your value into an instance of ObjectContent does a whole slew of conneg code, and determines that it can use Formatter X to serialize your "object".

Chances are it is the JSONSerializer that is doing its best to try an return you the string it thinks you want rather than the CR character.

Anyway you can cut to the chase and avoid executing 70 bajillion lines of code by using the HttpContent object that is designed for sending simple strings over the wire.

[HttpPost]
public ResponseMessageResult Post(Thing thing)
{
    var content = "\r";
    var httpResponseMessage = new HttpResponseMessage(HttpStatusCode.Accepted) {
      RequestMessage = Request,
      Content = new StringContent(content)
    };
    return ResponseMessage(httpResponseMessage);
}
查看更多
smile是对你的礼貌
4楼-- · 2019-03-24 16:07

If you are getting a literal two-character \r sequence out ("\\r" in C# form), then that is almost certainly what you are putting in. You say your Web API method "looks a bit like this". I strongly suspect the problem lies in the difference between what you have posted in your question, and what is in your actual implementation.

You need to verify that your response message contains actual carriage returns and not the literal text "\r". A text reading API is not going to look for literal C# escape sequences and handle them specially because C# string escape sequences have no meaning in plain text. If your text file contained the text c:\name.txt, then you wouldn't expect a text reading API to read it as c:<NEWLINE>ame.txt.

If you want to find and convert C#-style escape sequences, you will have to do it yourself. You can use a method like this (add additional escape sequences as necessary):

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();
}
查看更多
Summer. ? 凉城
5楼-- · 2019-03-24 16:26

I know that I'm probably going to cause 70 bajillion lines of code to execute by doing this (sorry Darrel Miller) but I found that it was just as effective, and less disruptive to my chosen development pattern to use this:

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

or

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

instead of this (that escapes the quotes):

response.Content.ReadAsStringAsync().Result;

Note: the ReadAsAsync is an extension method in the System.Net.Http.HttpContentExtensions, in the System.Net.Http.Formatting assembly. If it's not available in your project, you can add the NuGet package Microsoft.AspNet.WebApi.Client.

查看更多
对你真心纯属浪费
6楼-- · 2019-03-24 16:29
     [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");            
     }  
查看更多
登录 后发表回答