title: Request is not finished when using SqlDataReader in FileStreamResult using ASP.NET MVC
body: <p>For performance considerations I am using <code>SqlConnection</code> and <code>SqlReaderStream</code> for returning a <code>byte[]</code> <strong>stream from a SQL Server database</strong>:</p>
  
  <pre><code>private static SqlConnection GetConnection()
  {
      var sqlConnectionStringBuilder =
          new SqlConnectionStringBuilder(
              ConfigurationManager.ConnectionStrings["StudentsSystemEntities"].ConnectionString)
              {
                  Pooling = true
              };
      var connection = new SqlConnection(sqlConnectionStringBuilder.ConnectionString);
      connection.Open();
      return connection;
  }
  
  public FileDownloadModel GetFileById(Guid fileId)
  {
      var connection = GetConnection();
      var command = new SqlCommand(
          @"SELECT [FileSize], [FileExtension], [Content] FROM [dbo].[Files] WHERE [FileId] = @fileId;",
          connection);
      var paramFilename = new SqlParameter(@"fileId", SqlDbType.UniqueIdentifier) { Value = fileId };
      command.Parameters.Add(paramFilename);
  
      var reader = command.ExecuteReader(
          CommandBehavior.SequentialAccess | CommandBehavior.SingleResult
          | CommandBehavior.SingleRow | CommandBehavior.CloseConnection);
  
      if (reader.Read() == false) return null;
  
      var file = new FileDownloadModel
                      {
                          FileSize = reader.GetInt32(0),
                          FileExtension = reader.GetString(1),
                          Content = new SqlReaderStream(reader, 2)
                      };
      return file;
  }
  </code></pre>
  
  <p>I am using this <code>GetFileById</code> method in <strong>ASP.NET MVC action</strong>:</p>
  
  <pre><code>[HttpGet]
  public ActionResult Get(string id)
  {
      // Validations omitted
  
      var file = this.filesRepository.GetFileById(guid);
  
      this.Response.Cache.SetCacheability(HttpCacheability.Public);
      this.Response.Cache.SetMaxAge(TimeSpan.FromDays(365));
      this.Response.Cache.SetSlidingExpiration(true);
  
      this.Response.AddHeader("Content-Length", file.FileSize.ToString());
      var contentType = MimeMapping.GetMimeMapping(
          string.Format("file.{0}", file.FileExtension));
      // this.Response.BufferOutput = false;
      return new FileStreamResult(file.Content, contentType);
  }
  </code></pre>
  
  <p>I am connecting the MVC <code>FileStreamResult</code> with the <code>SqlReaderStream</code> in the following line:</p>
  
  <pre><code>return new FileStreamResult(file.Content, contentType);
  </code></pre>
  
  <p>When I try to load the resource using Chrome (or Firefox...) <strong>the entire file is loaded but I am getting the following error:</strong></p>
  
  <blockquote>
    <p>CAUTION: request is not finished yet!</p>
  </blockquote>
  
  <p><a href="https://i.stack.imgur.com/6pn6L.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/6pn6L.png" alt="CAUTION: request is not finished yet!"></a></p>
  
  <p><strong>Response headers:</strong></p>
  
  <pre><code>HTTP/1.1 200 OK
  Cache-Control: public, max-age=31536000
  Content-Length: 33429
  Content-Type: image/png
  Server: Microsoft-IIS/10.0
  X-AspNetMvc-Version: 5.2
  X-AspNet-Version: 4.0.30319
  X-SourceFiles: =?UTF-8?B?QzpcR---trimmed---G5n?=
  X-Powered-By: ASP.NET
  Date: Tue, 28 Jul 2015 13:02:55 GMT
  </code></pre>
  
  <p><strong>Additional information:</strong></p>
  
  <ul>
  <li>I am not using any Chrome extensions</li>
  <li>The problem is only with the given <code>Get</code> action. All other actions are loading normally</li>
  <li>The <code>FilesController</code> (in which the <code>Get</code> action is) inherits directly from the <code>Controller</code> class</li>
  <li>The file is loading successfully but the browser is still waiting the server: <a href="https://i.stack.imgur.com/RzXlL.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/RzXlL.png" alt="enter image description here"></a></li>
  <li>The exact same problem I am having with Firefox</li>
  </ul>
  
  <p><strong>What are the possible causes of the problem?</strong></p>
  
  <p><strong>Source code of the <code>SqlReaderStream</code> class</strong></p>
  
  <pre><code>public class SqlReaderStream : Stream
  {
      private readonly int columnIndex;
  
      private SqlDataReader reader;
  
      private long position;
  
      public SqlReaderStream(
          SqlDataReader reader, 
          int columnIndex)
      {
          this.reader = reader;
          this.columnIndex = columnIndex;
      }
  
      public override long Position
      {
          get { return this.position; }
          set { throw new NotImplementedException(); }
      }
  
      public override bool CanRead
      {
          get { return true; }
      }
  
      public override bool CanSeek
      {
          get { return false; }
      }
  
      public override bool CanWrite
      {
          get { return false; }
      }
  
      public override long Length
      {
          get { throw new NotImplementedException(); }
      }
  
      public override void Flush()
      {
      }
  
      public override int Read(byte[] buffer, int offset, int count)
      {
          var bytesRead = this.reader.GetBytes(
              this.columnIndex, this.position, buffer, offset, count);
          this.position += bytesRead;
          return (int)bytesRead;
      }
  
      public override long Seek(long offset, SeekOrigin origin)
      {
          throw new NotImplementedException();
      }
  
      public override void SetLength(long value)
      {
          throw new NotImplementedException();
      }
  
      public override void Write(byte[] buffer, int offset, int count)
      {
          throw new NotImplementedException();
      }
  
      protected override void Dispose(bool disposing)
      {
          if (disposing &amp;&amp; null != this.reader)
          {
              this.reader.Dispose();
              this.reader = null;
          }
  
          base.Dispose(disposing);
      }
  }
  </code></pre>