title: Video streaming in .net core (using status code 206)
body: <p>My .NET Core application will streaming video from storage.
  I've found this solution <a href="https://www.codeproject.com/Articles/820146/HTTP-Partial-Content-In-ASP-NET-Web-API-Video" rel="noreferrer">https://www.codeproject.com/Articles/820146/HTTP-Partial-Content-In-ASP-NET-Web-API-Video</a></p>
  
  <p>And try to rewrite it like this</p>
  
  <pre><code>    [AllowAnonymous]
      [HttpGet("{container}/{name}")]
      public IActionResult Get(string container, string name)
      {
          var stream = _fileStorageClient.GetStream(container, name); //Got from storage
          if (stream == null)
              return NotFound();
  
          Response.Headers["Accept-Ranges"] = "bytes";
  
          //if there is no range - this is usual request
          var rangeHeaderValue = Request.Headers["Range"].FirstOrDefault();
          if (string.IsNullOrEmpty(rangeHeaderValue))
          {
              var fileStreamResult = new FileStreamResult(stream, "video/mp4");
              Response.ContentLength = stream.Length;
              Response.StatusCode = (int) HttpStatusCode.OK;
              return fileStreamResult;
          }
  
          if (!TryReadRangeItem(rangeHeaderValue, stream.Length, out long start, out long end))
          {
              return StatusCode((int) HttpStatusCode.RequestedRangeNotSatisfiable);
          }
  
          Response.Headers["Content-Range"] = $"{start}-{end}/{stream.Length}";
          Response.ContentLength = end - start + 1;
          Response.StatusCode = (int) HttpStatusCode.PartialContent;
  
          var outStream = new MemoryStream();
          CreatePartialContent(stream, outStream, start, end);
          outStream.Seek(0, SeekOrigin.Begin);
          return new FileStreamResult(outStream, "video/mp4");
      }
  
      private static void CreatePartialContent(Stream inputStream, Stream outputStream,
          long start, long end)
      {
          var remainingBytes = end - start + 1;
          var buffer = new byte[ReadStreamBufferSize];
          long position;
          inputStream.Position = start;
          do
          {
              try
              {
                  var count = remainingBytes &gt; ReadStreamBufferSize ? 
                      inputStream.Read(buffer, 0, ReadStreamBufferSize) : 
                      inputStream.Read(buffer, 0, (int) remainingBytes);
                  outputStream.Write(buffer, 0, count);
              }
              catch (Exception error)
              {
                  Debug.WriteLine(error);
                  break;
              }
              position = inputStream.Position;
              remainingBytes = end - position + 1;
          } while (position &lt;= end);
      }
  
      private bool TryReadRangeItem(string rangeHeaderValue, long contentLength,
          out long start, out long end)
      {
          if (string.IsNullOrEmpty(rangeHeaderValue))
              throw new ArgumentNullException(nameof(rangeHeaderValue));
  
          start = 0;
          end = contentLength - 1;
  
          var rangeHeaderSplitted = rangeHeaderValue.Split('=');
          if (rangeHeaderSplitted.Length == 2)
          {
              var range = rangeHeaderSplitted[1].Split('-');
              if (range.Length == 2)
              {
                  if (long.TryParse(range[0], out long startParsed))
                      start = startParsed;
                  if (long.TryParse(range[1], out long endParsed))
                      end = endParsed;
              }
          }
  
          return start &lt; contentLength &amp;&amp; end &lt; contentLength;
      }
  </code></pre>
  
  <p>When I try to execute action from home I've got two requests</p>
  
  <p><strong>Request 1</strong></p>
  
  <pre><code>GET /api/videoFiles/video-answers/7f72c19b-5a5a-ed17-f87d-e755834a1c92 HTTP/1.1
  Host: localhost:65086
  Connection: keep-alive
  Cache-Control: max-age=0
  Upgrade-Insecure-Requests: 1
  User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36
  Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
  Accept-Encoding: gzip, deflate, br
  Accept-Language: ru-RU,ru;q=0.8,en-US;q=0.6,en;q=0.4
  Cookie: vc=2; _ga=GA1.1.1273330415.1475670014
  </code></pre>
  
  <p><strong>Response 1</strong></p>
  
  <pre><code>HTTP/1.1 200 OK
  Content-Length: 5517780
  Content-Type: video/mp4
  Accept-Ranges: bytes
  Server: Kestrel
  X-SourceFiles: =?UTF-8?B?QzpcV29ya1xIZXJ6ZW5cSGVyemVuLldlYlxhcGlcdmlkZW9GaWxlc1x2aWRlby1hbnN3ZXJzXDdmNzJjMTliLTVhNWEtZWQxNy1mODdkLWU3NTU4MzRhMWM5Mg==?=
  X-Powered-By: ASP.NET
  Date: Wed, 20 Sep 2017 06:37:01 GMT
  </code></pre>
  
  <p>Then <strong>Request 2</strong></p>
  
  <pre><code>GET /api/videoFiles/video-answers/7f72c19b-5a5a-ed17-f87d-e755834a1c92 HTTP/1.1
  Host: localhost:65086
  Connection: keep-alive
  Accept-Encoding: identity;q=1, *;q=0
  User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36
  Accept: */*
  Referer: http://localhost:65086/api/videoFiles/video-answers/7f72c19b-5a5a-ed17-f87d-e755834a1c92
  Accept-Language: ru-RU,ru;q=0.8,en-US;q=0.6,en;q=0.4
  Cookie: vc=2; _ga=GA1.1.1273330415.1475670014
  Range: bytes=0-
  </code></pre>
  
  <p><strong>Response 2</strong></p>
  
  <pre><code>HTTP/1.1 206 Partial Content
  Content-Length: 5517780
  Content-Type: video/mp4
  Content-Range: 0-5517779/5517780
  Accept-Ranges: bytes
  Server: Kestrel
  X-SourceFiles: =?UTF-8?B?QzpcV29ya1xIZXJ6ZW5cSGVyemVuLldlYlxhcGlcdmlkZW9GaWxlc1x2aWRlby1hbnN3ZXJzXDdmNzJjMTliLTVhNWEtZWQxNy1mODdkLWU3NTU4MzRhMWM5Mg==?=
  X-Powered-By: ASP.NET
  Date: Wed, 20 Sep 2017 06:37:01 GMT
  </code></pre>
  
  <p>After loading video control is available for instant, then it becomes grayed out</p>
  
  <p>When I return FileStreamResult(as in first condition) without Accept-Ranges all is ok.</p>
  
  <p>What's wrong with this code?</p>