title: Web Api won't download file using jQuery Ajax and Basic Auth
body: <p>I am using the ASP.NET Web API to build a prototype of a web service (and site) which has a method to download a file. When the user on the front-end presses the export button a jQuery ajax GET request is made and received by the controller which on it's turn calls the method named Excel (shown below). The method runs without any problem and finishes. When I look in Chrome at the header (see <a href="https://skydrive.live.com/redir?resid=2D85E5C937AC2BF9!77093" rel="nofollow">https://skydrive.live.com/redir?resid=2D85E5C937AC2BF9!77093</a>) it receives the response with (as far as I am concerned) all the right headers. </p>
  
  <p>I am using Basic Auth, so the user credentials are transmitted using the http authorization header which I have manually added to every jQuery Ajax request using Ajax Options.</p>
  
  <pre><code>var excelRequest = $.ajax({
      url: 'http://localhost:59390/api/mycontroller/excel',
      cache: false,
      type: 'GET',
      data: gridString,
      dataType: 'json',
      contentType: 'application/json; charset=utf-8'
  });
  
  $.ajaxSetup({
      beforeSend: function (xhr) {
          SetAuthRequestHeader(xhr)
      }
  });
  
  function SetAuthRequestHeader(jqXHR) {
      var usr = "Gebruiker2"; // TODO: Change, this is for testing only.
      var pw = "Wachtwoord23";
      jqXHR.setRequestHeader("Authorization", "Basic " + Base64.encode(usr + ":" + pw));
  }
  </code></pre>
  
  <p>My prototype has some characteristics which I should mention:</p>
  
  <ul>
  <li><p>Uses Basic Auth in Authorization header</p></li>
  <li><p>The web service and the web site which calls the service are on different domains, so I used CORS and added the following to the web.config</p></li>
  </ul>
  
  <blockquote>
  <pre><code>&lt;httpProtocol&gt;
      &lt;customHeaders&gt;
          &lt;add name="Access-Control-Allow-Origin" value="*" /&gt;
          &lt;add name="access-control-allow-headers" value="Content-Type, Authorization, Accept" /&gt;
          &lt;add name="Access-Control-Allow-Methods" value="GET, POST, PUT, DELETE, OPTIONS" 
      &lt;/customHeaders&gt;
  &lt;/httpProtocol&gt;
  </code></pre>
  </blockquote>
  
  <p>Shown below is the entire Excel method.</p>
  
  <pre><code>    [HttpGet]
      // Get api/myController/excel 
      public HttpResponseMessage Excel(string sidx, string sord, int page, int rows, string Depot, string PDID, string User, string Property, string Value)
      {
          if (AuthHelper.AuthService.HasValidCredentials(Request))
          {
              var gridResult = this.GetDataJqGridFormat( sidx,  sord,  page,  rows,  Depot,  PDID,  User,  Property,  Value);
  
              // Generate a HTML table.
              StringBuilder builder = new StringBuilder();
              // We create a html table:
              builder.Append("&lt;table border=1&gt;");
              builder.Append("&lt;tr&gt;&lt;td&gt;DEPOT&lt;/td&gt;");
              builder.Append("&lt;td&gt;PDID&lt;/td&gt;");
              builder.Append("&lt;td&gt;USER&lt;/td&gt;");
              builder.Append("&lt;td&gt;PROPERTY&lt;/td&gt;");
              builder.Append("&lt;td&gt;VALUE&lt;/td&gt;&lt;/tr&gt;");
              // Create response from anonymous type            
              foreach (var item in gridResult.rows)
              {
                  builder.Append("&lt;/tr&gt;");
                  builder.Append("&lt;tr&gt;");
                  builder.Append("&lt;td&gt;" + item.cell[0] + "&lt;/td&gt;");
                  builder.Append("&lt;td&gt;" + item.cell[2] + "&lt;/td&gt;");
                  builder.Append("&lt;td&gt;" + item.cell[3] + "&lt;/td&gt;");
                  builder.Append("&lt;td&gt;" + item.cell[4] + "&lt;/td&gt;");
                  builder.Append("&lt;td&gt;" + item.cell[5] + "&lt;/td&gt;");
              }
              builder.Append("&lt;/table&gt;");
  
              HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK);
              result.Content = new StringContent(builder.ToString());
              result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");                                
              result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
              result.Content.Headers.ContentDisposition.FileName = "file.xls";
  
              return result;
          }
          else
          {
              throw ForbiddenResponseMessage();
          }
  
      }
  </code></pre>
  
  <p>This is the header which should also return the file:
  <a href="https://skydrive.live.com/redir?resid=2D85E5C937AC2BF9!77093" rel="nofollow">https://skydrive.live.com/redir?resid=2D85E5C937AC2BF9!77093</a></p>
  
  <p>What I want is to have the file downloaded when I call the url which points to the excel method. I do not understand why it won't download. Is it even possible to download a file this way?</p>