2

I made a c# web api at the the moment . It is working fine until today. I've tried to convert an image to a base64string, and then send the base64string to the c# server through ajax. When I did the said steps, an error occur.

XMLHttpRequest cannot load http://10.0.10.105:50231/api/hello. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://10.0.10.201' is therefore not allowed access.

I dont know where the main problem resides but in my observation, the error only occur when passing a very long base64string to the server because when i try to send short test string the problem wont appear and all is working well.

Do you have any idea what is the better remedy to fix this ? Or any other way to perform my needed objective ? my ajax code is something like this.

$.ajax({
                    type: 'POST', //GET or POST or PUT or DELETE verb
                    url: 'http://10.0.10.105:50231/api/hello', // Location of the service
                    contentType: 'application/x-www-form-urlencoded', // content type sent to server
                    data: { action: "3",pers_guid:"wew",base64image:"this-is-the-base64-image"},
                    //dataType: 'jsonp', //Expected data format from server
                    //processdata: true, //True or False
                    success: function (data) {//On Successfull service call
                        $scope.pageView = 2;
                        console.log("THE Data description for match : " + data[0].description);
                    },
                    error: function (msg) {// When Service call fails
                        alert(msg);
                    }
                });

and my c# server is similar to this (this is not the whole code).

public class theHandler : DelegatingHandler
    {
        protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
        {
            return base.SendAsync(request, cancellationToken)
            .ContinueWith((task) =>
            {
                HttpResponseMessage response = task.Result;
                response.Headers.Add("Access-Control-Allow-Origin", "*");
                return response;
            });
        }
    }

 public class HelloController : ApiController
    {
        public IEnumerable<string> Get()
        {

             return new string[] { "value1", "value2" };
        }

//.... more code here
}

This is the result when I tried to pass a very long string...

Request URL:http://10.0.10.105:50231/api/hello
Request Headers CAUTION: Provisional headers are shown.
Accept:*/*
Content-Type:application/x-www-form-urlencoded
Origin:http://10.0.10.201
Referer:http://10.0.10.201/kiosk/
User-Agent:Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.114 Safari/537.36
Form Dataview sourceview URL encoded
action:3
pers_guid:wew
base64image:the_long_base64_string

but when i pass just a sample string this is the result.

Remote Address:10.0.10.105:50231
Request URL:http://10.0.10.105:50231/api/hello
Request Method:POST
Status Code:200 OK
Request Headersview source
Accept:*/*
Accept-Encoding:gzip,deflate,sdch
Accept-Language:en-US,en;q=0.8
Connection:keep-alive
Content-Length:49
Content-Type:application/x-www-form-urlencoded
Host:10.0.10.105:50231
Origin:http://10.0.10.201
Referer:http://10.0.10.201/kiosk/
User-Agent:Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.114 Safari/537.36
Form Dataview sourceview URL encoded
action:3
pers_guid:wew
base64image:sample_string
Response Headersview source
Access-Control-Allow-Origin:*
Content-Length:103
Content-Type:application/json; charset=utf-8
Date:Wed, 04 Jun 2014 01:02:35 GMT
Server:Microsoft-HTTPAPI/2.0
Hope
  • 644
  • 2
  • 6
  • 21
  • Read this http://stackoverflow.com/questions/20433655/no-access-control-allow-origin-header-is-present-on-the-requested-resource-or – Matt Jun 02 '14 at 06:03

3 Answers3

1

This error shows up because your server listening on '10.0.10.105' does not specify the 'Access-Control-Allow-Origin' header in its HTTP response. This is a common issue with websites that 'talk' to each other, and you may read about it here (or just Google 'CORS').

As a solution, have the server listening on that IP return the following header from the POST response:

Access-Control-Allow-Origin: *

This has some security implications that you might want to read about (in general it's best to not use the "allow-all" star '*' and instead specify the requesting server explicitly).

Update: As explained in that paper under "Preflight requests", non-trivial POST requests require the server to also listen to OPTIONS requests and return these headers in the response:

Access-Control-Allow-Origin: *

Access-Control-Allow-Methods: POST, GET, OPTIONS

Can you try having the image server listen to OPTIONS (just like you did for GET, POST, etc.) and return these headers? (The client making the 'POST' request will automatically precede it with an OPTIONS request to the same server, and if the OPTIONS response contains these headers, the subsequent POST will be called.)

Community
  • 1
  • 1
OmegaDirective
  • 366
  • 2
  • 6
  • Thank you for the answer. I already add something like this in the server. response.Headers.Add("Access-Control-Allow-Origin", "*"); response.Headers.Add("Access-Control-Allow-Origin", "10.0.10.105"); but no luck am i missing something ? – Hope Jun 02 '14 at 06:24
  • Please see my updated response. A preflight request (OPTIONS) is probably needed. – OmegaDirective Jun 02 '14 at 08:12
  • Thanks for the reply but no luck. Still the error occur. – Hope Jun 03 '14 at 01:26
  • Can you use a sniffer (e.g. Fiddler) and copy the HTTP traffic here? Specifically, do you see the OPTIONS request/response? – OmegaDirective Jun 03 '14 at 05:04
1

Thank you so much for your answers. It gives me lot of ideas about access origin. It seems that my problem is on the configuration. I added this code and all is working fine.

config.MaxReceivedMessageSize = 5000000;

The program will automatically show an access-control-allow-origin when it exceeds the max limit size of the default configuration.

Thank you so much for the ideas.

Hope
  • 644
  • 2
  • 6
  • 21
0

So, CORS and the Access-Control-Allow-Origin header are awkward. I ran into this one a while back when I had an API that needed to be referenced from JavaScript code running on several different websites. I ended up writing an ActionFilterAttribute to handle it for my API controllers:

[AttributeUsage(AttributeTargets.Method)]
public class AllowReferrerAttribute : System.Web.Http.Filters.ActionFilterAttribute
{
    public override void OnActionExecuting(System.Web.Http.Controllers.HttpActionContext actionContext)
    {
        var ctx = (System.Web.HttpContextWrapper)actionContext.Request.Properties["MS_HttpContext"];
        var referrer = ctx.Request.UrlReferrer;

        if (referrer != null)
        {
            string refhost = referrer.Host;
            string thishost = ctx.Request.Url.Host;
            if (refhost != thishost)
                ctx.Response.AddHeader("Access-Control-Allow-Origin", string.Format("{0}://{1}", referrer.Scheme, referrer.Authority));
        }
        base.OnActionExecuting(actionContext);
    }
}

You can decorate your controller's methods with that attribute and it will add the correct Access-Control-Allow-Origin for your caller's website, regardless of what that website is. And assuming that you're using IIS as your host... won't work for OWIN-hosted sites.

Example usage:

public class HelloController : ApiController
{
    [AllowReferrer]
    public IEnumerable<string> Get()
    {
        return new string[] { "value1", "value2" };
    }
}
Corey
  • 15,524
  • 2
  • 35
  • 68
  • Thank you so much for your time honestly speaking im new in c# when I try your code there was an error "The type or namespace name 'HttpContextWrapper' does not exist in the namespace 'System.Web' (are you missing an assembly reference?)" what namespace do i have to use to make it work if you dont mind ? really appreciate your help. – Hope Jun 03 '14 at 01:33
  • `System.Web.HttpContextWrapper` is present in `System.Web.dll` in .net 4.0 and 4.5, or in `System.Web.Abstractions.dll` in .net 3.5. Which version of .NET are you using? Do you have the appropriate reference in your project? – Corey Jun 03 '14 at 02:20
  • thank you so much for help. I tried your given code. But still the error occur. Dont have any idea why. Do you have any idea aside from converting image to base64 ? – Hope Jun 03 '14 at 02:37
  • Check your references. In .net 4.0 the `System.Web.dll` contains the `HttpContextWrapper` class. Make sure that you're reference points to the .net 4.0 version - reference properties are `Version=4.0.0.0`, `Runtime Version=v4.0.30319`. – Corey Jun 03 '14 at 02:37
  • yeah i already fix the error and I run your given code successfully but the error still occur during the request. – Hope Jun 03 '14 at 02:43
  • Are you sure of that error? Sure you're not getting a message about `Access-Control-Allow-Methods`? – Corey Jun 03 '14 at 05:07