Mục tiêu của tôi là xác thực yêu cầu API Web bằng cách sử dụng AuthorizationFilter hoặc DelegatingHandler. Tôi muốn tìm mã nhận dạng khách hàng và mã xác thực ở một vài nơi, bao gồm cả phần thân yêu cầu. Lúc đầu, có vẻ như điều này sẽ dễ dàng, tôi có thể làm điều gì đó như thế nàyTại sao nội dung yêu cầu API Web đọc một lần?
var task = _message.Content.ReadAsAsync<Credentials>();
task.Wait();
if (task.Result != null)
{
// check if credentials are valid
}
Vấn đề là chỉ có thể đọc HttpContent một lần. Nếu tôi làm điều này trong một Trình xử lý hoặc Bộ lọc thì nội dung đó không có sẵn cho tôi trong phương thức hành động của tôi. Tôi tìm thấy một vài câu trả lời ở đây trên StackOverflow, như thế này: Read HttpContent in WebApi controller giải thích rằng đó là cố ý theo cách này, nhưng họ không nói TẠI SAO. Điều này có vẻ giống như một giới hạn khá nghiêm trọng ngăn tôi sử dụng bất kỳ mã phân tích nội dung API Web mát nào trong Bộ lọc hoặc Trình xử lý.
Đây có phải là hạn chế kỹ thuật không? Có phải nó đang cố gắng giữ cho tôi không thực hiện một điều RẤT NHIỀU (tm) mà tôi không thấy?
POSTMORTEM:
Tôi đã xem xét nguồn như Filip được đề xuất. ReadAsStreamAsync trả về luồng nội bộ và không có gì ngăn bạn gọi Seek nếu luồng hỗ trợ nó. Trong các thử nghiệm của tôi nếu tôi gọi là ReadAsAsync thì thực hiện điều này:
message.Content.ReadAsStreamAsync().ContinueWith(t => t.Result.Seek(0, SeekOrigin.Begin)).Wait();
Quy trình ràng buộc mô hình tự động sẽ hoạt động tốt khi nó nhấn phương pháp hành động của tôi. Tôi không sử dụng này, mặc dù tôi đã lựa chọn một cái gì đó trực tiếp hơn:
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;
Với một phương pháp mở rộng (tôi đang ở trong .NET 4.0 với không có từ khóa đang chờ đợi)
public static class TaskExtensions
{
public static T WaitFor<T>(this Task<T> task)
{
task.Wait();
if (task.IsCanceled) { throw new ApplicationException(); }
if (task.IsFaulted) { throw task.Exception; }
return task.Result;
}
}
Một bắt ngoái, HttpContent có mã hóa cứng tối đa kích thước bộ đệm:
internal const int DefaultMaxBufferSize = 65536;
vì vậy, nếu nội dung của bạn sẽ là lớn hơn mà bạn sẽ cần phải tự gọi LoadIntoBufferAsync với kích thước lớn hơn trước khi bạn cố gắng gọi ReadAsByteArrayAsync.
Mặc dù bạn đã tìm được cách để đọc nội dung nhiều lần, các bạn có biết tại sao bạn không thể đọc nó hai lần không? Bởi vì tôi thực sự kéo tóc của tôi để tìm hiểu lý do tại sao hạn chế này là có ở nơi đầu tiên. –