Почему тело запроса Web API читается один раз?

Моя цель - аутентифицировать запросы веб-API с помощью AuthorizationFilter или DelegatingHandler. Я хочу найти идентификатор клиента и токен аутентификации в нескольких местах, включая тело запроса. Сначала казалось, что это будет легко, я мог бы сделать что-то вроде этого

var task = _message.Content.ReadAsAsync();

task.Wait();

if (task.Result != null)
{
    // check if credentials are valid
}

Проблема в том, что HttpContent может быть прочитан только один раз. Если я делаю это в обработчике или фильтре, то содержимое нене доступно для меня в моем методе действия. Я нашел несколько ответов здесь в StackOverflow, как этот:Читать HttpContent в контроллере WebApi которые объясняют, что так сделано намеренно, но несказать почему. Это кажется довольно серьезным ограничением, которое не позволяет мне использовать какой-либо классный код синтаксического анализа контента Web API в Filters или Handlers.

Это техническое ограничение? Это пытается удержать меня от ОЧЕНЬ ПЛОХОГО (ТМ), что яя не вижу?

POSTMORTEM:

Я посмотрел на источник, как предложил Филипп. ReadAsStreamAsync возвращает внутренний поток и тамНичто не мешает вам позвонитьесли поток поддерживает это, В моих тестах, если я вызвал ReadAsAsync, то сделал это:

message.Content.ReadAsStreamAsync().ContinueWith(t => t.Result.Seek(0, SeekOrigin.Begin)).Wait();

Процесс автоматического связывания модели будет работать нормально, когда он коснется моего метода действия. Я не'Хотя я не могу использовать это, я выбрал что-то более прямое:

var buffer = new MemoryStream(_message.Content.ReadAsByteArrayAsync().WaitFor());
var formatters = _message.GetConfiguration().Formatters;
var reader = formatters.FindReader(typeof(Credentials), _message.Content.Headers.ContentType);
var credentials = reader.ReadFromStreamAsync(typeof(Credentials), buffer, _message.Content, null).WaitFor() as Credentials;

С методом расширения (I 'м. .NET 4.0 без ключевого слова await)

public static class TaskExtensions
{
    public static T WaitFor(this Task task)
    {
        task.Wait();
        if (task.IsCanceled) { throw new ApplicationException(); }
        if (task.IsFaulted) { throw task.Exception; }
        return task.Result;
    }
}

Последний улов, HttpContent имеет жестко заданный максимальный размер буфера:

internal const int DefaultMaxBufferSize = 65536;

Так что, если ваш контент будет больше, чем выВам нужно будет вручную вызвать LoadIntoBufferAsync с большим размером, прежде чем пытаться вызвать ReadAsByteArrayAsync.

Ответы на вопрос(2)

Ваш ответ на вопрос