【问题标题】:What is different with PushStreamContent between web api & web api 2?Web api 和 Web api 2 之间的 PushStreamContent 有什么不同?
【发布时间】:2019-08-08 20:56:45
【问题描述】:

我创建了两个相同的 web api 项目,一个在 VS 2012 中,另一个在 VS 2013 中,都针对 4.5 .net 框架。这些项目基于 Filip W 的视频下载教程,可在此处找到: http://www.strathweb.com/2013/01/asynchronously-streaming-video-with-asp-net-web-api/

将教程中的代码复制并粘贴到 VS 2012 项目中(使用 web api 1?)不会产生错误(在我添加正确的“使用”语句之后)。

但是,当我在 VS 2013 项目中执行相同的步骤时,我收到以下两个错误:

错误 1
以下方法或属性之间的调用不明确: 'PushStreamContent(System.Func<Stream,HttpContent,TransportContext,Task>, MediaTypeHeaderValue)' 和 'PushStreamContent(System.Action<System.IO.Stream,HttpContent,TransportContext>, MediaTypeHeaderValue)'

错误 2
'void video_stream.Controllers.VideoStream.WriteToStream(System.IO.Stream, System.Net.Http.HttpContent, System.Net.TransportContext)' 返回类型错误

所以我的猜测是错误 2 是真正的问题,因为这段代码:

public async void WriteToStream(Stream outputStream, HttpContent content, TransportContext context) {...}

在 web api 1 和 2 之间不再被标识为<action>??我在这里真的很困惑,因为我的目标是相同的框架,而且我似乎无法直观地了解如何修复它。我更改 WriteToStream 签名的尝试都失败了。

是否有人知道我需要什么来让 PushStreamContent 接受 web api 2 或 VS 2013 或新 C# 中的 WriteToStream 或此代码的差异存在于何处?

【问题讨论】:

    标签: c# asp.net-web-api download large-files


    【解决方案1】:

    PushStreamContent 构造函数的签名已更改。它的 onStreamAvailable 参数是 Action 或 Func 泛型类型。问题是编译器不知道要绑定到哪个类型。

    所以要解决错误,将 streamAvailableHandler 转换为 Action:

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

    处理方法是:

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

    【讨论】:

      【解决方案2】:

      我不确定这是否是 Web 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();
          }
      });
      

      注意:我对代码进行了另一项更改(删除了 catch 块)以允许传播异常。这是为了让您的客户知道服务中发生了一些错误,否则他们会认为一切都很顺利。

      【讨论】:

      • 昨晚深夜,在查看我发现的另一个 PushStreamContent 示例时,我最终得到了您的确切解决方案。这促使我在 VS 12 和 13 中“转到定义”,我想我应该从一开始就这样做。在 12 中,PSC 有 3 次过载,但在 13 中,有 6 次过载。仔细观察,它似乎传递了一个外部方法,现在需要一个以前不需要的额外参数(任务)。我可以确认上述解决方案确实有效。
      【解决方案3】:

      这是 C# 规范的一个已知问题。看看这个 SO 问题 - Compiler Ambiguous invocation error - anonymous method and method group with Func<> or Action

      当我们引入这个返回任务的重载时,我们确实意识到这是一个源级别的破坏性更改(尽管它不会破坏二进制兼容性)。我们仍然继续进行更改,因为不修复它会导致更多问题。

      关于如何修复它,您有两种选择 -

      1. 正如 Kiran 之前建议的那样,您可以使用匿名方法语法,以便编译器为您选择正确的重载。
      2. 您可以使用显式转换,如下所示,

        response.Content = new PushStreamContent((Action)video.WriteToStream, new MediaTypeHeaderValue("video/"+ext));

      顺便说一句,使用async void 方法成为careful。我建议您将其签名更改为

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

      【讨论】:

      • 如果您确实将 void 更改为 Task 您的投射也必须更改为 (Func)
      【解决方案4】:

      正如 RaghuRam Nadiminti 所说,通过将 WriteToStream 的返回类型从 void 更改为 Task,编译将成功运行,您将不需要显式转换。

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

      【讨论】:

        【解决方案5】:

        这是我的解决方法:如果调用不明确,只需转换它:

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2012-03-16
          • 2017-09-07
          • 2017-06-09
          • 1970-01-01
          • 2023-03-20
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多