Как предотвратить использование ReadAsStringAsync двукратно экранированной строки?
У меня есть метод 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"
почему клиент получает двукратную экранированную строку и как я могу предотвратить ее?
Ответы
Ответ 1
Он делает то, что делает, потому что вы взламываете яйцо кувалдой.
Когда вы вызываете Request.CreateResponse<string>(HttpStatusCode statusCode, T value)
вы сообщаете веб-API, что вы хотите, чтобы ваше значение сериализовалось с использованием одного из Request.CreateResponse<string>(HttpStatusCode statusCode, T value)
медиафайлов. Таким образом, веб-API наполняет ваше value
в экземпляр объекта ObjectContent, что приводит к целому числу кодов conneg и определяет, что он может использовать Formatter X для сериализации вашего "объекта".
Скорее всего, именно JSONSerializer делает все возможное, чтобы попытаться вернуть вам строку, которую он считает нужным, а не символ CR.
В любом случае, вы можете сократить погоню и не выполнять 70 байонлий строк кода, используя объект HttpContent, который предназначен для отправки простых строк по проводу.
[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
Я знаю, что я, вероятно, собираюсь выпустить 70 байджонных строк кода, выполнив это (извините Даррела Миллера), но я обнаружил, что это было так же эффективно и менее разрушительно для моего выбранного шаблона разработки, чтобы использовать это:
response.Content.ReadAsAsync<string>().Result;
или
await response.Content.ReadAsAsync<string>();
вместо этого (что ускользает от котировок):
response.Content.ReadAsStringAsync().Result;
Примечание. ReadAsAsync
является методом расширения в System.Net.Http.HttpContentExtensions
в сборке System.Net.Http.Formatting
. Если он недоступен в вашем проекте, вы можете добавить пакет NuGet Microsoft.AspNet.WebApi.Client
.
Ответ 3
Вы не получаете значение @"\\r"
назад, вы получаете "\\r"
- вы не получите в своем ответе стенографического символа, потому что дословный символ - это просто команда, чтобы избежать строки определенным образом - сам модификатор verbatim не сохраняется как часть строки. Результатом является соответствующая экранированная версия того, к чему вы применили модификатор verbatim.
т.е. @"\r"
дает вам строку "\\r"
которая при применении к текстовому полю отображается как \r
- экранированная обратная косая черта и 'r'.
Вам просто нужно снять модификатор слов с вашего первоначального назначения.
Это не имеет никакого отношения к ReadAsStringAsync
- вы просто назначаете неверный строковый литерал в первую очередь.
Ответ 4
Если вы получаете буквальную двухсимвольный \r
последовательность из ("\\r"
в форме С#), то это почти наверняка, что вы ставите в. Вы говорите, что ваш веб - метод API "выглядит немного как это". Я сильно подозреваю, что проблема заключается в различии между тем, что вы опубликовали в своем вопросе, и тем, что находится в вашей реальной реализации.
Вам нужно проверить, что ваше ответное сообщение содержит фактические возвращения каретки, а не буквальный текст "\r"
. API-интерфейс чтения текста не будет искать буквенные escape-последовательности С# и обрабатывать их специально, потому что строки escape-последовательности строк С# не имеют смысла в текстовом виде. Если ваш текстовый файл содержит текст c:\name.txt
, вы не ожидаете, что API чтения текста прочитает его как c:<NEWLINE>ame.txt
.
Если вы хотите найти и преобразовать escape-последовательности С# -style, вам придется сделать это самостоятельно. Вы можете использовать такой метод (добавьте дополнительные escape-последовательности по мере необходимости):
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();
}