问题
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
回答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.)
回答2:
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.
回答3:
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" };
}
}
来源:https://stackoverflow.com/questions/23950526/sending-base64-string-to-c-sharp-server