Header not being set for OPTIONS Ajax request
I assume that you meant to write ashx
, not ascx
. The presence of the ProcessRequest (HttpContext context)
method suggests it's a generic handler and not a user control.
I've made a very simple page to test with:
<%@ Page Language="C#" AutoEventWireup="true" %><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head runat="server"> <title></title> <script type="text/javascript" src="Scripts/jquery-1.4.1.js"></script></head><body> <div id="testCorsDiv"> </div> <script type="text/javascript"> $.ajax({ type: "GET", url: "/Handler/testCors.ashx", dataType: "text", success: function (theData) { $("#testCorsDiv").text(theData); }, error: function (theData) { alert('error'); } }); </script> <% if(string.IsNullOrEmpty(Request.QueryString["sandboxed"])) { %> <iframe src="http://127.0.0.1:49253/SandboxTest.aspx?sandboxed=true" sandbox="allow-scripts" width="600"> </iframe> <% } %></body></html>
I load the page on http://localhost:49253/SandboxTest.aspx
. The page then makes an ajax
request to http://localhost:49253/Handler/testCors.ashx
and puts the output from that into the testCorsDiv
div. This generates a straight GET
to the handler (since it's coming from the same origin) and the output gets inserted.
In the page is also a sandboxed iframe
which loads the same page using the url http://127.0.0.1:49253/SandboxTest.aspx
. The ?sandboxed=true
is there to prevent the iframe from recursively loading an inner iframe. The page loaded in the iframe will then try to make an ajax request to http://127.0.0.1:49253/Handler/testCors.ashx
and display the output in it's own copy of the testCorsDiv
div.
As long as the sandboxed iframe has allow-scripts
this works like a charm. The iframe
generates an OPTIONS
request looking like this (from Fiddler, tested with Chrome):
OPTIONS http://127.0.0.1:49253/Handler/testCors.ashx HTTP/1.1Host: 127.0.0.1:49253Connection: keep-aliveCache-Control: max-age=0Access-Control-Request-Method: GETOrigin: nullUser-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.90 Safari/537.36Access-Control-Request-Headers: accept, x-requested-withAccept: */*Referer: http://127.0.0.1:49253/SandboxTest.aspx?sandboxed=trueAccept-Encoding: gzip, deflate, sdchAccept-Language: fi-FI,fi;q=0.8,en-US;q=0.6,en;q=0.4
My testCors.ashx
handler then spits out some headers that says that this looks ay-ok and the browser then follows up with a GET
and it just works.
The testCors.ashx
does this:
public void ProcessRequest(HttpContext context){ context.Response.ContentType = "text/plain"; context.Response.AppendHeader("Access-Control-Allow-Origin", "*"); context.Response.AppendHeader("Access-Control-Allow-Headers", "content-type, x-requested-with, accept"); context.Response.AppendHeader("Access-Control-Allow-Methods", "POST, OPTIONS, GET"); context.Response.Write("Hello World");}
So my testing suggests that it should be possible to do what you want. One thing though that might be an issue is if your handler is only accessible to authenticated/authorized users. As you can see the OPTIONS
request has not sent a cookie to the handler. But on the other hand your question says that the response to you options request is Status Code:200
. I suppose that would be some 4**
if a required authentication cookie was missing.
Wrapping up, I don't really know what's wrong in your case, but maybe (?) my simple sample page can give you some clues that will help you find the issue yourself.
Make sure you have IIS setting to allow OPTION
to that handler - deployed to app having say App pool name "web-app" and corresponding handler mapping should allow OPTION
request.
Following are the steps to do that.
- select required app pool
- Click on handler mappings
- select *.ashx and double click on the corresponding handler , click on Request Restriction , see if you have option verb there, if not, add that.
Above mentioned here - http://www.chrisweldon.net/blog/2012/04/13/jquery-file-uploader/
You may need to use following code.
public void ProcessRequest (HttpContext context) { context.Response.ContentType = "text/plain"; context.Response.AddHeader("Access-Control-Allow-Origin", "*"); // You can try adding requested origin here instead of * like this - Request.Headers["Origin"] or only the specific domain, in your case it is -https://127.0.0.1:112 if (HttpContext.Current.Request.HttpMethod == "OPTIONS") { context.Response.AddHeader("Access-Control-Allow-Methods", "POST, PUT, DELETE"); context.Response.AddHeader("Access-Control-Allow-Headers", "Content-Type, Accept"); context.Response.AddHeader("Access-Control-Max-Age", "1728000"); } context.Response.Write(Token.CreateToken());}
I have explained this in my blog. This was for WCF, but it should work for your case too! You might need to change *
for allowed origin to requested origin, as * has security issue, it allows all domains to make CORS call.
Can you try adding the below code in both of your HTML and iFrame page (in the HTML DOC) and check if it works?
<script>document.domain = 'myDomain.com'</script>
Note: Please replace the 'myDomain' with appropriate domain name of the domain you are using (the origin)