Search code examples
http-headersasp.net-web-api2httpresponseasp.net-apicontroller

Web Api 2 custom IHttpActionResult CORS. No 'Access-Control-Allow-Origin' header is present on the requested resource


I have a problem with CORS from my WEB API 2 to Angular application. Everything is working fine till now and all the response headers are receiving the following:

Access-Control-Allow-Origin:*
Cache-Control:no-cache
Content-Length:24
Content-Type:application/json; charset=utf-8
Date:Mon, 13 Nov 2017 08:15:32 GMT
Expires:-1
Pragma:no-cache
Server:Microsoft-IIS/10.0
X-AspNet-Version:4.0.30319
X-Powered-By:ASP.NET
X-SourceFiles:=?UTF-8?B?...

Now I created a custom IHttpActionResult like this:

public class ZipFileActionResult : IHttpActionResult
{
    private const long BufferLength = 65536;
    public ZipFileActionResult(string file)
    {
        this.Filepath = file;
    }

    public string Filepath { get; private set; }

    public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
    {
        HttpResponseMessage result = new HttpResponseMessage();

        var zipf = new FilesStream(this.Filepath);
        Action<Stream, HttpContent, TransportContext> writeToStream = zipf.WriteToStream;
        result.Content = new PushStreamContent(writeToStream, new MediaTypeHeaderValue("application/" + "zip"));

        result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
        {
            FileName = "filename.zip"
        };

        return Task.FromResult(result);
    }

    private async void OnStreamConnected(Stream outputStream, HttpContent content, TransportContext context)
    {
        try
        {
            var buffer = new byte[BufferLength];

            using (var nypdVideo = File.Open(this.Filepath, FileMode.Open, FileAccess.Read, FileShare.Read))
            {
                var videoLength = (int)nypdVideo.Length;
                var videoBytesRead = 1;

                while (videoLength > 0 && videoBytesRead > 0)
                {
                    videoBytesRead = nypdVideo.Read(buffer, 0, Math.Min(videoLength, buffer.Length));
                    await outputStream.WriteAsync(buffer, 0, videoBytesRead);
                    videoLength -= videoBytesRead;
                }
            }
        }
        catch (HttpException ex)
        {
            return;
        }
        finally
        {
            // Close output stream as we are done
            outputStream.Close();
        }
    }
}

and I use this in my DownloadCOntroller like this:

    [HttpPost]
    [Route("PaperCuts")]
    public IHttpActionResult PaperCuts(List<SelectionObject> selections)
    {
        try
        {
                string sFileName = <filename> + ".zip";

                return new ZipFileActionResult(sFileName);
            }
        }
        catch (Exception ex)
        {
            throw ex;
        }
    }

I'm receiving the following error when I call this function correctly:

No 'Access-Control-Allow-Origin' header is present on the requested resource.

And I'm receiving this as response header:

HTTP/1.1 500 Internal Server Error
Cache-Control: private
Transfer-Encoding: chunked
Content-Type: text/html; charset=utf-8
Server: Microsoft-IIS/10.0
X-AspNet-Version: 4.0.30319
X-SourceFiles: =?UTF-8?B?RDpcUHJvamVjdHNcS25pcHNlbGtyYW50XEtuaXBzZWxrcmFudEFQSVxLbmlwc2Vsa3JhbnRBUElcYXBpXGRvd25sb2FkXFBhcGVyQ3V0cw==?=
X-Powered-By: ASP.NET
Date: Mon, 13 Nov 2017 08:35:33 GMT

I also have this stated in my WebApiConfig.cs (It works for all my other requests except for this one).

        var corsAttr = new EnableCorsAttribute("*", "*", "*");
        config.EnableCors(corsAttr);

So the problem is that the Access-Control-Allow-Origin header etc are not same as in ALL the other requests. So how is this possible and how can I fix this? I hope I provided enough information for my question.

Kind regards,

D.


Solution

  • I found the answer and got reminded by @ICantSeeSharp

    I added following code in my global exception handler:

    public override bool ShouldHandle(ExceptionHandlerContext context)
    {
        return true;
    }