Получение необработанных данных POST из метода Web API
У меня есть следующий метод Web API в классе ApiController:
public HttpResponseMessage Post([FromBody]byte[] incomingData)
{
...
}
Я хочу, чтобы incomingData было сырым содержанием поста. Но похоже, что стек Web API пытается проанализировать входящие данные с помощью JSON formatter, и это приводит к сбою следующего кода на стороне клиента:
new WebClient().UploadData("http://localhost:15134/api/Foo", new byte[] { 1, 2, 3 });
Есть ли простой обходной путь для этого?
5 ответов:
Для всех, кто сталкивается с этой проблемой, решение состоит в том, чтобы определить метод POST без параметров и получить доступ к необработанным данным через
Request.Content:public HttpResponseMessage Post() { Request.Content.ReadAsByteArrayAsync()... ...
Если вам нужен необработанный ввод в дополнение к параметру модели для облегчения доступа, вы можете использовать следующее:
using (var contentStream = await this.Request.Content.ReadAsStreamAsync()) { contentStream.Seek(0, SeekOrigin.Begin); using (var sr = new StreamReader(contentStream)) { string rawContent = sr.ReadToEnd(); // use raw content here } }Секрет заключается в использовании
stream.Seek(0, SeekOrigin.Begin)для сброса потока перед попыткой считывания данных.
Другие ответы предлагают удалить входной параметр, но это сломает весь существующий код. Чтобы правильно ответить на этот вопрос, проще всего создать функцию, которая выглядит следующим образом (Спасибо Кристофу ниже за этот код):
private async Task<String> getRawPostData() { using (var contentStream = await this.Request.Content.ReadAsStreamAsync()) { contentStream.Seek(0, SeekOrigin.Begin); using (var sr = new StreamReader(contentStream)) { return sr.ReadToEnd(); } } }А затем получите необработанные опубликованные данные внутри вашего вызова Web api следующим образом:
public HttpResponseMessage Post ([FromBody]byte[] incomingData) { string rawData = getRawPostData().Result; // log it or whatever return Request.CreateResponse(HttpStatusCode.OK); }
Я взял ответ Лакланба и поместил его в служебный класс с единственным статическим методом, который я могу использовать во всех своих контроллерах.
public class RawContentReader { public static async Task<string> Read(HttpRequestMessage req) { using (var contentStream = await req.Content.ReadAsStreamAsync()) { contentStream.Seek(0, SeekOrigin.Begin); using (var sr = new StreamReader(contentStream)) { return sr.ReadToEnd(); } } } }Тогда я могу вызвать его из любого из методов моего ApiController следующим образом:
string raw = await RawContentReader.Read(this.Request);
В MVC 6 запрос, похоже,не имеет свойства 'Content'. Вот что я в итоге сделал:
[HttpPost] public async Task<string> Post() { string content = await new StreamReader(Request.Body).ReadToEndAsync(); return "SUCCESS"; }
Comments