2013-11-17 6 views
9

Я создал два идентичных веб-проекта api, один в VS 2012 и еще один в VS 2013, оба предназначенные для рамки 4.5 .net. Проекты основаны на Filip W в видео скачать учебник здесь: http://www.strathweb.com/2013/01/asynchronously-streaming-video-with-asp-net-web-api/Что отличает PushStreamContent между web api & web api 2?

Копирование & вставки кода из учебника в проект VS 2012 (?, Используя веб-интерфейс API 1) не производит никаких ошибок (после того, как я добавляю собственно «, используя ' заявления).

Однако, когда я выполнить те же действия в проекте VS 2013, я получаю следующие две ошибки:

Ошибка 1
Вызов неоднозначен между следующими методами или свойствами: «PushStreamContent (System .Func <Stream,HttpContent,TransportContext,Task>, MediaTypeHeaderValue) ' и 'PushStreamContent (System.Action <System.IO.Stream,HttpContent,TransportContext>, MediaTypeHeaderValue)'

Ошибка 2
' недействительным VI deo_stream.Controllers.VideoStream.WriteToStream (System.IO.Stream, System.Net.Http.HttpContent, System.Net.TransportContext)»имеет неправильный тип возвращаемого

Так что моя догадка ошибка 2 является реальной проблемой как этот код:

общественного асинхронной недействительным WriteToStream (поток OutputStream, HttpContent контента, TransportContext контекст) {...}

не идентифицирована как <action> больше между Web API 1 & 2 ?? Я действительно запутался здесь, поскольку я нацелен на ту же структуру, и я не могу показаться интуитивным скачком о том, как ее исправить. Мои попытки изменить подпись WriteToStream не удались.

У кого-нибудь есть ключ к тому, что мне нужно, чтобы получить PushStreamContent, чтобы принять WriteToStream в веб-api 2 или VS 2013 или новом C# или где когда-либо разница в этом коде живет?

ответ

6

Я не уверен, что это ошибка в веб-API, мы будем исследовать ее. В то же время вы можете попробовать следующий обходной путь:

response.Content = new PushStreamContent(async (Stream outputStream, HttpContent content, TransportContext context) => 
{ 
    try 
    { 
     var buffer = new byte[65536]; 

     using (var video = File.Open(filename, FileMode.Open, FileAccess.Read)) 
     { 
      var length = (int)video.Length; 
      var bytesRead = 1; 

      while (length > 0 && bytesRead > 0) 
      { 
       bytesRead = video.Read(buffer, 0, Math.Min(length, buffer.Length)); 
       await outputStream.WriteAsync(buffer, 0, bytesRead); 
       length -= bytesRead; 
      } 
     } 
    } 
    finally 
    { 
     outputStream.Close(); 
    } 
}); 

Примечание: Я сделал еще одно изменение (удалить блок поймать) в код, чтобы исключения распространяться. Это так, что ваши клиенты знают, что на службе произошла ошибка, иначе они предполагали, что все прошло гладко.

+0

В конце концов я получил свое точное решение вчера поздно вечером, глядя на другой PushStreamContent примера я нашел. Это побудило меня «перейти к определению» в VS 12 и 13, что, я думаю, я должен был сделать с самого начала. В 12 есть 3 перегрузки для PSC, но в 13 есть 6 перегрузок. Если посмотреть внимательно, то, по-видимому, он передает внешний метод, теперь требуется дополнительный параметр (Задача), который раньше не нужен. Я могу подтвердить, что вышеуказанное решение действительно работает. – huxley

+0

Я получаю: процесс не может получить доступ к файлу. Ошибка ввода-вывода из .net – DanielV

3

Это известная проблема с спецификацией C#. Посмотрите этот вопрос SO - Compiler Ambiguous invocation error - anonymous method and method group with Func<> or Action

Когда мы представили эту перегрузку, которая возвращает задачу, мы осознали, что это изменение уровня исходного уровня (хотя оно не нарушает двоичную совместимость). Мы по-прежнему продолжали это изменение, так как не исправляли, это вызывало бы больше проблем.

И о том, как это исправить, у вас есть два варианта -

  1. Как Киран предполагалось ранее, вы можете использовать анонимный синтаксис метода, так что компилятор выбирает правильную перегрузку для вас.
  2. Вы можете использовать явное приведение типов, как показано ниже,

    response.Content = новый PushStreamContent ((Action) video.WriteToStream, новый MediaTypeHeaderValue ("видео /" + вн));

BTV, быть carefulasync void с этим методом. Предлагаю Вам изменить свою подпись на

public async Task WriteToStream(Stream outputStream, HttpContent content, TransportContext context) 
+1

Если вы изменили void на Task, то ваше литье также изменилось бы на (Func ) – CaMiX

12

Изменена подпись конструктора PushStreamContent. Его параметр onStreamAvailable является общим типом Action или Func. Проблема заключается в том, что компилятор не знает, к какому типу привязывается.

Таким образом, чтобы устранить ошибку бросить streamAvailableHandler как Действие:

response.Content = new PushStreamContent((Action<Stream, HttpContent, TransportContext>)streamAvailableHandler); 

И методы обработчика будут:

private void streamAvailableHandler(Stream stream, HttpContent content, TransportContext context) { 
    ...write to stream 
} 
0

Как sujjested по Рагураму Nadiminti, путь изменения WriteToStream возвращаемого типа из void to Task, компиляция будет выполнена успешно, и вам не понадобится явное литье.

public async Task WriteToStream (Stream outputStream, контент HttpContent, контекст TransportContext);

-1

Это был мой обходным путем: если вызов был неоднозначным, просто бросьте:

response.Content = new PushStreamContent(
    (Action<Stream, HttpContent, TransportContext>) video.WriteToStream, 
new MediaTypeHeaderValue("video/" + ext));