0

I am getting an error in Chrome when calling a webservice on my own box. The error is:

Origin http://localhost:52386 is not allowed by Access-Control-Allow-Origin.

I have read other questions here and articles like this: Cross Domain AJAX; but they tend to deal with the problem of IE not working correctly and I have a problem with Chrome.

I added the following to my webservice/Global.asax.cs:

protected void Application_BeginRequest(object sender, EventArgs e)
{
    //HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "*");
    // Changed to this:
    HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "http://localhost:52386");
    HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "http://localhost:80");

}

Here is my HTML code (I need to keep this in plain HTML, no code behind):

    $(document).ready(function () {
        var user = 'testuser';
        var pwd = 'abc123';
        var auth = 'Basic ' + Base64.encode(user + ':' + pwd);
        if ($.browser.msie) {
            jQuery.support.cors = true;
            $.ajax({
                type: "GET",
                url: "http://localhost/Website.Webservice/api/TaxDocument",
                data: "{}",
                contentType: "application/json; charset=utf-8",
                dataType: "text json",
                headers: { Authorization: auth },
                crossDomain: true,
                success: function (data, textStatus, jqXHR) { ProcessOutput(data); },
                error: function (jqXHR, textStatus, errorThrown) { alert('Error: ' + textStatus + ' ' + errorThrown); }
            });
        } else {
            $.ajax({
                type: "GET",
                url: "http://localhost/Website.Webservice/api/TaxDocument",
                data: "{}",
                contentType: "application/json; charset=utf-8",
                crossDomain: true,
                dataType: "json",
                headers: { Authorization: auth },
                success: function (data, textStatus, jqXHR) { ProcessOutput(data); },
                error: function (jqXHR, textStatus, errorThrown) { alert('Error: ' + textStatus + ' ' + errorThrown); }
            });
        }
    })
Community
  • 1
  • 1
Bruce C
  • 349
  • 1
  • 6
  • 17
  • You should specify port (if it's different from origin) in the Access-Control-Allow-Origin header. Look at the questions: http://stackoverflow.com/questions/8576252/access-control-allow-origin-problems-on-the-same-domain and http://stackoverflow.com/questions/7113877/access-control-allow-origin-issues An asterisk `*` does not work in this case. – Stan Oct 25 '12 at 21:38
  • I added port 52386 and port 80 but it still will not work in chrome or firefox. I have it working in ie and safari. Any other ideas? – Bruce C Oct 26 '12 at 22:02
  • Shouldn't this be `http://localhost:52386/` - with the trailing slash? – Stan Oct 27 '12 at 09:54
  • Ok, I added the trailing slash and it didn't help. I also confirmed that this is the problem. I published the html page to localhost and ran it and it works. So at least I know that I am truly dealing with an access control issue. I will keep plugging away at and I will post the solution when found. – Bruce C Oct 28 '12 at 15:01
  • Do you mean, that a plain html page works ok whereas ASP.NET page produces the error? If so, could you log actual http-headers that your browser receives? – Stan Oct 29 '12 at 09:55
  • No, if I run the HTML page from localhost and the webserver on localhost everything works. I checked request and response and the problem is chrome is requesting OPTIONS and the webserver is not responding. See my solution – Bruce C Oct 31 '12 at 19:05

1 Answers1

0

Ok, so this turned out to be a pretty big problem. First, IIS 7.5 and VS development server, and IIS Express handle CORS differently. The main problem was my webservice was not responding to an OPTIONS request from chrome and firefox; IE and Safari just don't really care.

I used a NuGet package from ThinkTecture that has a CORS handler. See the discussion here: CORS Support.

My revised JS now does not care about browser (I have tested in IE, Safari, Chrome, and FireFox)

<script type="text/javascript">
        var GetTaxDocument = function () {
            var url = "http://myWebService.com/WebService/Api/Products;
            var user = "myUser";
            var pwd = "pwd123";
            var auth = Base64.encode(user + ':' + pwd);

            jQuery.support.cors = true;
            $.ajax({
                type: "GET",
                url: url,
                //data: "{}",
                contentType: "application/json; charset=utf-8",
                dataType: "text json",
                headers: { Authorization: 'Basic ' + auth },
                crossDomain: true,
                success: function (data, textStatus, jqXHR) {ProcessOutput(data); }
                error: function (jqXHR, textStatus, errorThrown) { alert('Error: ' + textStatus + ' ' + errorThrown.message); }
            });
        };

        var ProcessOutput = function (data) {
            var body = "";
            $.each(data, function () {
                var row = "";
                row += "ID:   " + this.ID + "<br />";
                row += "Desc: " + this.Desc + "<br />";
                body += "<p>" + row + "</p>";
            })
            $('#results').html(body);
        };
    </script>

I added the following to global.asax.cs:

        protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();

        WebApiConfig.Register(GlobalConfiguration.Configuration);
        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
        RouteConfig.RegisterRoutes(RouteTable.Routes);
        BundleConfig.RegisterBundles(BundleTable.Bundles);

        GlobalConfiguration.Configuration.MessageHandlers
          .Add(new BasicAuthMessageHandler()
          {
              PrincipalProvider = new AuthenticationPrincipalProvider()
          });
        //This is the CORS handler
        CorsConfig.RegisterCors(GlobalConfiguration.Configuration);

    }

And in my App_start\CorsConfig.cs the follwoing:

public class CorsConfig
{
    public static void RegisterCors(HttpConfiguration httpConfig)
    {
        WebApiCorsConfiguration corsConfig = new WebApiCorsConfiguration();

        // this adds the CorsMessageHandler to the HttpConfiguration’s
        // MessageHandlers collection
        corsConfig.RegisterGlobal(httpConfig);

        // this allow all CORS requests to the Products controller
        // from the http://foo.com origin.
        corsConfig
            .ForResources("TaxDocument")
            //.ForOrigins("http://localhost", "http://localhost:49878", "http://localhost:52386")
            .AllowAllOrigins()
            .AllowAll();
    }
}

the localhost:52386 and localhost:49878 solved my problems when calling the webservice running on localhost and debugging the webpage from VS. Adding localhost helps when I am debugging the webservice running on 49878 and running the webpage on localhost or 52386. I ended up switching to .AllowAll() for now because I was loading the HTML from FILE:///c:/myWebPage.html

Please give me some feedback and/or let me know if I need to add more detail.

Bruce C
  • 349
  • 1
  • 6
  • 17