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)は、メディア タイプ フォーマッタの 1 つを使用して値をシリアル化することを Web API に伝えています。したがって、Web APIvalueは ObjectContent のインスタンスにあなたを詰め込み、大量の conneg コードを実行し、Formatter X を使用して「オブジェクト」をシリアル化できると判断します。

CR文字ではなく、必要と思われる文字列を返すために最善を尽くしているのはJSONSerializerである可能性があります。

とにかく、簡単な文字列をネットワーク経由で送信するように設計された 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 に答える
0

リテラルの 2 文字の\rシーケンスを ( "\\r"C# 形式で) 取得している場合、それはほぼ間違いなく、入力しているものです。Web API メソッドは「これに少し似ている」と言います。問題は、質問に投稿した内容と実際の実装の違いにあると強く思います。

応答メッセージにリテラル テキストではなく、実際のキャリッジ リターンが含まれていることを確認する必要があります"\r"。C# 文字列エスケープ シーケンスはプレーン テキストでは意味がないため、テキスト読み取り API はリテラル 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 に答える
0

あなたは値を受け取っていません@"\\r"、あなたは受け取って"\\r"います-逐語的な文字は特定の方法で文字列をエスケープするための単なる指示であるため、応答で逐語的な文字を取得しません-逐語的な修飾子自体は一部として保存されません文字列の。結果は、verbatim 修飾子を適用したものの適切にエスケープされたバージョンです。

つまり、テキスト ボックスに適用すると、エスケープされたバックスラッシュと 'r'として表示される@"\r"文字列が得られます。"\\r"\r

最初の割り当てから verbatim 修飾子を削除するだけです。

これは何の関係もありませんReadAsStringAsync。そもそも間違った文字列リテラルを割り当てているだけです。

于 2013-11-05T14:07:51.073 に答える