1

i used WCF Restful Services as my business layer, when i try to 'GET' data from the service in IE 9 it just works fine and fill the JQgrid, but when i was trying to open the same page with Chrome or Firefox i got this error message.

{
    "statusText": "",
    "responseText": "",
    "response": "",
    "onabort": null,
    "readyState": 4,
    "upload": {
        "onloadstart": null,
        "onabort": null,
        "onerror": null,
        "onload": null,
        "onprogress": null
    },
    "onerror": null,
    "onreadystatechange": null,
    "status": 0,
    "responseXML": null,
    "onprogress": null,
    "onload": null,
    "withCredentials": false,
    "onloadstart": null,
    "responseType": ""
}

Service.svc

 [WebGet(UriTemplate = "LT_SectionListPage/?pageIndex={pageIndex}&pageSize={pageSize}&sortOrder={sortOrder}&sortColumn={sortColumn}", ResponseFormat = WebMessageFormat.Json)]  
    [OperationContract]

I used Fiddler2 to trace things out and here is the out put with IE9

HTTP/1.1 200 OK
Server: ASP.NET Development Server/10.0.0.0
Date: Thu, 12 May 2011 11:53:40 GMT
X-AspNet-Version: 2.0.50727
Cache-Control: private
Content-Type: application/json; charset=utf-8
Content-Length: 847
Connection: Close

and the output with Chrome

HTTP/1.1 405 Method Not Allowed
Server: ASP.NET Development Server/10.0.0.0
Date: Thu, 12 May 2011 11:54:07 GMT
X-AspNet-Version: 2.0.50727
Cache-Control: private
Content-Type: text/html
Content-Length: 1137
Connection: Close

<html version="-//W3C//DTD XHTML 2.0//EN" xml:lang="en" xsi:schemaLocation="http://www.w3.org/1999/xhtml http:// www.w3.org/MarkUp/SCHEMA/xhtml2.xsd" xmlns="http:// www.w3.org/1999/xhtml" xmlns:xsi="http:// www.w3.org/2001/XMLSchema-instance"><HEAD><TITLE>Request Error</TITLE></HEAD><BODY><DIV id="content"><P class="heading1"><B>Error Description:</B> 'HTTP Method not allowed'</P><P><B>This may be because an invalid URI or HTTP method was specified. Please see the <A HREF="http:// localhost:1111/Rest.svc/help">service help page</A> for constructing valid requests to the service.</B></P><!-- Padding xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx--></DIV></BODY></html>

Request in Chrome

OPTIONS http:// localhost:1111/Rest.svc/LT_SectorListPage/json/?pageIndex=1&pageSize=100&sortOrder=asc&sortColumn=ID&_=1305207336766 HTTP/1.1
Host: localhost:1111
Connection: keep-alive
Referer: http:// localhost:1407/Default.aspx
Access-Control-Request-Method: GET
Origin: http:// localhost:1407
User-Agent: Mozilla/5.0 (Windows NT 6.1) AppleWebKit/534.24 (KHTML, like Gecko) Chrome/11.0.696.65 Safari/534.24
Access-Control-Request-Headers: X-Requested-With, Accept
Accept: */*
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3

Request In IE9

GET http:// localhost:1111/Rest.svc/LT_SectorListPage/json/?pageIndex=1&pageSize=100&sortOrder=asc&sortColumn=ID&_=1305207423633 HTTP/1.1
x-requested-with: XMLHttpRequest
Accept-Language: ar-JO,en-US;q=0.5
Referer: http:// localhost:1407/Default.aspx
Accept: text/plain, */*
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)
Host: localhost:1111
Connection: Keep-Alive
Cookie: ASP.NET_SessionId=d212qpnffmvrzit1sx4z1mzb

Chrome does not accepts the method and IE9, any help would be appreciated.

Thanks

[Updated Fiddler Status]

after adding the following code into Global.asax to handle the CORS issue

protected void Application_BeginRequest(object sender, EventArgs e)
        {
            HttpContext.Current.Response.Cache.SetCacheability(HttpCacheability.NoCache);
            HttpContext.Current.Response.Cache.SetNoStore();
            HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin","*");
            if (HttpContext.Current.Request.HttpMethod == "OPTIONS")
            {
                HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "GET, POST");
                HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "Content-Type, Accept");
                HttpContext.Current.Response.End();
            }
        }

Request

OPTIONS http:// localhost:1111/Rest.svc/LT_SectorListPage/json/?pageIndex=1&pageSize=100&sortOrder=asc&sortColumn=ID&_=1305213078870 HTTP/1.1
Host: localhost:1111
Connection: keep-alive
Referer: http:// localhost:1212/Default.aspx
Access-Control-Request-Method: GET
Origin: http:// localhost:1212
User-Agent: Mozilla/5.0 (Windows NT 6.1) AppleWebKit/534.24 (KHTML, like Gecko) Chrome/11.0.696.65 Safari/534.24
Access-Control-Request-Headers: X-Requested-With, Accept
Accept: */*
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3

Response

HTTP/1.1 200 OK
Server: ASP.NET Development Server/10.0.0.0    
Date: Thu, 12 May 2011 15:11:18 GMT    
X-AspNet-Version: 2.0.50727    
Access-Control-Allow-Origin: *    
Access-Control-Allow-Methods: GET, POST    
Access-Control-Allow-Headers: Content-Type, Accept    
Cache-Control: no-cache, no-store    
Pragma: no-cache    
Expires: -1    
Content-Length: 0    
Connection: Close

Madi
  • 146
  • 1
  • 3
  • 13
  • also i dont know why the Content-Type in IE is Content-Type: application/json which is correct and with same functionality it returned as ontent-Type: text/html in Chrome and FireFox – Madi May 12 '11 at 13:15
  • @user743863: You included only the response data and not the request data for IE and Chrome. The error `HTTP Method not allowed` in chrome make interesting to compare the requests in both cases. You can modify the text of your question any time and append it with additional information. Moreover there are many strange things in your code: `ExpandColumn: "menu"` and no column with the name `"menu"`. `page: "CurretnPage"` (not Current). Moreover and the names from the `jsonReader` **not corresponds** to the name from `WebGet(UriTemplate ...` which you use. – Oleg May 12 '11 at 13:36
  • hi Oleg, i have updated the question, regarding the jqgrid its just an example i will remove those parameters from it – Madi May 12 '11 at 14:02
  • I think you should just place WFC service on the same site and use relative paths to address it. I do this always myself and have no problems. See [here](http://stackoverflow.com/questions/4680162/host-wcf-in-mvc2-site/4680617#4680617) for example. – Oleg May 12 '11 at 17:53

2 Answers2

2

You're running into cross-domain issues because your service is being hosted on a different port (1111) than you client web page (1407). Therefore Chrome is making a Cross Origin Resource Sharing Request (CORS), which is what the OPTIONS request is, to check access before continuing and your service clearly doesn't support CORS at this time.

To remedy this you have to either implement support for CORS requests on your WCF service or run the web service off the same port as the web site. If they're both going to be on the same domain/port in a production environment there's no reason to spend time implementing CORS.

FWIW, IE would also fail in a production environment in this case. It's only working because you're hitting localhost which puts IE into the more lax intranet security policy.

Here's some more documentation on/examples of CORS:

Drew Marsh
  • 33,111
  • 3
  • 82
  • 100
  • i tried to maintain the Cross Domain problem and i got Response 200 OK but without returning data as in IE9 here is the monitored response HTTP/1.1 200 OK Server: ASP.NET Development Server/10.0.0.0 Date: Thu, 12 May 2011 14:54:59 GMT X-AspNet-Version: 2.0.50727 Access-Control-Allow-Origin: * Access-Control-Allow-Methods: GET, POST Access-Control-Allow-Headers: Content-Type, Accept Cache-Control: no-cache, no-store Pragma: no-cache Expires: -1 Content-Length: 0 Connection: Close No data here :S – Madi May 12 '11 at 15:01
  • That's still a CORS response you're showing me. Did you actually change it to run over one port or did you try to implement CORS support?? Please update your original question with the full request/response trace from fiddler so I can help further dissect. – Drew Marsh May 12 '11 at 15:08
  • Ok, so you see how it's sending the X-Requested-With in the Access-Control-Request-Headers? Well you're only responding with Access-Control-Allow-Headers of Content-Type and Accept. So the preflight request is failing to be ok'd on sending a header it wants to send and therefore your GET request is never going out. If you want to just blindly support all CORS requests I suggest changing your code to just echo the requested headers/methods. It's the simplest thing to do. I don't recommend going to production that way though. – Drew Marsh May 12 '11 at 16:10
  • Also, one other thing, I notice you're only setting the CORS headers if it's an OPTIONS request, but you need to make sure you set the proper CORS headers on the GET response as well otherwise it won't work. If you've found this information useful I'd appreciate if vote it up and/or mark it as the answer. If you still need more help please let me know if you're seeing the GET request actually go through yet. – Drew Marsh May 12 '11 at 19:50
  • well im really confused, when i tried to add GET method to the CORS header i got an json2 error, to be honest im confused with the whole idea, can u referee to any helpful document to read, and for sure i will mark up ur answer as soon i solve this issue, thanks – Madi May 15 '11 at 11:35
  • Perhaps you'll find the Mozilla documentation easier to grok than the W3C spec. Especially since it has some nice detailed examples. I'll add it as a link to my answer. – Drew Marsh May 15 '11 at 15:49
0

well i found the solution for this issue with this workaround

protected void Application_BeginRequest(object sender, EventArgs e)
        {
            //Enable Cross Domain WCF Configuration
            HttpContext.Current.Response.Cache.SetCacheability(HttpCacheability.NoCache);
            HttpContext.Current.Response.Cache.SetNoStore();
            HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "*");
            string rqstMethod = HttpContext.Current.Request.Headers["Access-Control-Request-Method"];
            if (rqstMethod == "GET" || rqstMethod == "POST" || rqstMethod =="OPTIONS")
            {
                HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
                HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "X-Requested-With, Accept");
                HttpContext.Current.Response.AddHeader("Access-Control-Max-Age", "3628800");
                HttpContext.Current.Response.AddHeader("type", "application/json; charset=utf-8");
                HttpContext.Current.Response.End();
            }
        }

You should be-careful of the accepted headers in your request.

Big Thanks @Drew Marsh for help and useful documents

Madi
  • 146
  • 1
  • 3
  • 13