Unable to get JSON response from cross domain AJAX request - ajax

I'm using a JSON store in ExtJS and getting the data from an ASP.net web service. It returns the data successfully if I use it in the same domain, but in a cross-domain it returns an error:
XMLHTTPREQUEST Access-Control-Origin Header is not allowed by the
Origin
Here is my code:
var myStore = new Ext.data.JsonStore({
// Load data at once
autoLoad: true,
// Override default http proxy settings
proxy: new Ext.data.HttpProxy({
// Call web service method using GET syntax
type:'ajax',
url: path+'SelectIncidentList',
restful:true,
// Ask for Json response
headers: {'Content-type': 'application/json'},
reader: {
type: 'json',
root: 'd'
},
}),
id: 'incidentid',
// Fields declaration
fields: ['incidentid','occured','headline','source','enteredby','bodyintro','webaddress','location1','location2','location3','location4','image','incidenttypeid','incidentsubtypeid']
});
* EDIT *
Based off the answers I got, I changed my code to use JSONP. However I am running into another issue. With these changes to my ExtJS code:
var myStore = new Ext.data.JsonStore({
autoLoad: true,
// Override default http proxy settings
proxy: new Ext.data.proxy.JsonP({
type:'jsonp',
url: path+'SelectoccurList',
headers: {'Content-type': 'application/json'},
reader: {
type: 'json',
root: 'd'
},
}),
id: 'occurid',
// Fields declaration
fields: ['occurid','occured','headline','source','enteredby','bodyintro','webaddress','location1','location2','location3','location4','image','occurtypeid','occursubtypeid']
});
I am running into the following error:
<?xml version="1.0" encoding="utf-8"?>
**SelectOccurList:-1Resource interpreted as Script but transferred with MIME type text/xml.
SelectOccurList:1SyntaxError: Unexpected token '<'**
<ArrayOfOccurData xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://tempuri.org/">
<OccurData>
<occurid>22</occurid>
<occured>2012-05-26T04:33:53-04:00</occured>
<headline>headline</headline>
<source>content</source>
<enteredby />
<bodyintro>content</bodyintro>
<webaddress />
<location1>29 -156.364</location1>
<location2 />
<location3 />
<location4 />
<image>url of iamge</image>
<occurtypeid>0</occurtypeid>
<occursubtypeid>0</occursubtypeid>
</OccurData>
<OccurData>
<occurid>23</occurid>
<occured>2012-05-26T15:41:52-04:00</occured>
<headline>headline</headline>
<source>test content</source>
<enteredby />
<bodyintro>test content</bodyintro>
<webaddress />
<location1>27.75974 -82.67853</location1>
<location2 />
<location3 />
<location4 />
<image>url of image</image>
<occurtypeid />
<occursubtypeid />
</OccurData>
<OccurData>
<occurid>24</occurid>
<occured>test</occured>
<headline />
<source />
<enteredby />
<bodyintro />
<webaddress />
<location1 />
<location2 />
<location3 />
<location4 />
<image />
<occurtypeid>0</occurtypeid>
<occursubtypeid>0</occursubtypeid>
</OccurData>
<OccurData>
<occurid>25</occurid>
<occured>Testing</occured>
<headline>Testing 28 05 </headline>
<source>Dummy</source>
<enteredby>XYZ</enteredby>
<bodyintro>This occur is dummy</bodyintro>
<webaddress>http://</webaddress>
<location1>5cd41415-5c60-4cbd-a6f3-05330b368a41</location1>
<location2 />
<location3 />
<location4 />
<image />
<occurtypeid>0</occurtypeid>
<occursubtypeid>0</occursubtypeid>

That's exactly what you'd use a JsonP proxy for, which uses a script tag + callback function to get around the same domain browser restriction. The linked header documentation explains it fully with example code, including a few basic server implementations.
The other option would be to actually proxy the call on your server -- i.e., the Ajax proxy calls your server, which then calls the remote server and formats a standard JSON response back to your client. You just can't make the call directly from client to remote server.

You can configure your server to setting "access-control-" headers.
https://developer.mozilla.org/en/http_access_control

Related

Ionic 3 http post request invalid HTTP status code 403 while jQuery ajax post is working perfectly

I am working on a mobile app. I need to fetch some data from WordPress website but the http request always through error Response for preflight has invalid HTTP status code 403
Typescript
this._http.post('http://www.example.com/wp-admin/admin-ajax.php',{
'action' : 'get_votes',
'postId' : 123456
})
.subscribe(data=>{
console.log(data);
},error=>{
console.log(error);
})
jQuery
The same thing is working in jQuery on local server
$.ajax({
url: 'http://www.example.com/wp-admin/admin-ajax.php',
type: 'post',
dataType: 'JSON',
data: {
'action': 'get_votes',
'postId': 123456
},
success: function(result) {
console.log(result);
},
error: function(error) {
console.log(error);
}
});
The cordova-plugin-whitelist is already installed.
config.xml
<access origin="*" />
<allow-intent href="http://*/*" />
<allow-intent href="https://*/*" />
If you are testing with web browser, there you need to allow origin access for web browser. with chrome use plugin and configure it https://chrome.google.com/webstore/detail/allow-control-allow-origi/nlfbmbojpeacfghkpbjhddihlkkiljbi
If you are using with real device and it is still not working try to use header('Access-Control-Allow-Origin: *'); with your server side API file.
More Info here.
This is a CORS (cross-domain) issue. Your browser (not Angular) is sending an OPTIONS request before sending the actual POST request. Effectively, your server discards the OPTIONS request as not authenticated (or forbidden in your case). Please read this answer for more info.
Have you tried to set a 'content-type' header as 'application/x-www-form-urlencoded' or 'multipart/form-data'? I think is would result in the browser not to send an OPTIONS request before sending the POST request.
So, even if you solve the first problem (with the lack of OAuth header), you may still not be able to POST, because of the second problem.
You can also try and install the Chrome Allow-Control-Origin extension.
you can use ionic proxy to work arround the CORS problem,
ionic.config.json
"proxies": [
{
"path": "/api",
"proxyUrl": "http://www.example.com/wp-admin/admin-ajax.php"
}
]
and you call it this.http.post("/api")

ExtJs 5 Ajax Request with ASP .NET

Despite my best efforts I am not able to send an Ajax request with Json data to a remote web server. I do not know what other places I can put enable CORS and am running out of ideas.
Azure Website App Settings:
cors:allowOrigins: *
MVC Controller: I had installed the NuGet Cors package
[EnableCors(origins: "*", headers: "*", methods: "*")]
Web.config:
<httpProtocol>
<customHeaders>
<clear />
<add name="Access-Control-Allow-Origin" value="*" />
</customHeaders>
</httpProtocol>
ExtJs Ajax Request:
Ext.Ajax.request({
url: app.utilities.url,
defaultHeaders: {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'GET,PUT,POST,DELETE,OPTIONS',
'Access-Control-Allow-Headers': 'Content-Type, Authorization,Content-Length, X-Requested-With'
},
cors: true,
useDefaultXhrHeader: false,
params: {
jsonData: Ext.util.JSON.encode(formData)
}
Yet I still get:
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at {my url} This can be fixed by moving the resource to the same domain or enabling CORS.
Is there something I am missing?
Would you consider JsonP (JSON with Padding)?
http://docs.sencha.com/extjs/6.0/6.0.0-classic/#!/api/Ext.data.JsonP
Only for the development purpose you can set below parameter in your browser.It works for me.
--disable-web-security --allow-file-access-from-files --allow-file-access

500 System.ServiceModel.ServiceActivationException when making an Ajax call to WCF rest service

Ajax Call:
$.ajax({
type: "POST",
url: "http://SomeService/ServiceName.svc/GetSearchResults",
data: JSON.stringify({ parameters: serviceParameters }),
contentType: "application/json; charset=utf-8",
dataType: "XML",
success: function (response) {
$("#xmlText").text(response.xml);
},
error: function (msg) {
alert(msg.toString);
}
})
WCF Interface:
[OperationContract]
[WebInvoke(Method = "POST", BodyStyle = WebMessageBodyStyle.Wrapped, ResponseFormat = WebMessageFormat.Xml, RequestFormat = WebMessageFormat.Json,
UriTemplate = "GetSearchResults")]
XElement GetSearchResults(inputParameters parameters);
[OperationContract]
[WebInvoke(Method = "POST", RequestFormat = WebMessageFormat.Json, UriTemplate = "getFile")]
Stream GetFile(DocInfo info);
Web.config:
<system.web>
<compilation debug="true" targetFramework="4.0" />
<customErrors mode="Off"/>
</system.web>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true">
</serviceHostingEnvironment>
<standardEndpoints>
<webHttpEndpoint>
<standardEndpoint name="" helpEnabled="true" automaticFormatSelectionEnabled="true"></standardEndpoint>
</webHttpEndpoint>
</standardEndpoints>
</system.serviceModel>
The service is hosted on IIS6.
When I call the service I get the following error message:
500 System.ServiceModel.ServiceActivationException
I can call the GetFile method and get the response stream but I get the error message when calling GetSearchResults.
Any help will be appreciated.
I encountered this error for the reason mentioned below
Memory gates checking failed because the free memory (258187264 bytes) is less than 5% of total memory. As a result, the service will not be available for incoming requests. To resolve this, either reduce the load on the machine or adjust the value of minFreeMemoryPercentageToActivateService on the serviceHostingEnvironment config element.
Many thanks for your inspired replies and comments.
I actually encountered the same error but with different story:
At first, I got "404 (Not Found)" server error, which is because I did not have a transport for "HTTPS" as well as I already have one for the "HTTP".
I added a <httpsTransport> to my <binding> element, so it looked like this:
<bindings>
<customBinding>
<binding name="CustomBinding_ITheService">
<httpTransport keepAliveEnabled="True" transferMode="Streamed" authenticationScheme="None" maxBufferSize="2147483647" maxReceivedMessageSize="2147483647" manualAddressing="true" />
<httpsTransport keepAliveEnabled="True" transferMode="Streamed" authenticationScheme="None" maxBufferSize="2147483647" maxReceivedMessageSize="2147483647" manualAddressing="true" />
</binding>
</customBinding>
</bindings>
Then I got the 500 System.ServiceModel.ServiceActivationException error. However, I navigated "Event Viewer > Windows Log > Application" and found that "transports cannot be defined more than a time for the same binding". So, I decided to add an additional endpoint with a new binding for the "HTTPS" transport.
At the end, my configuration looks like the following:
<services>
<service name="TheService" behaviorConfiguration="WebHttpBehavior_ITheService">
<endpoint binding="customBinding" bindingConfiguration="CustomBinding_ITheService" contract="ITheService" behaviorConfiguration="EndPointBehavior_ITheService" />
<endpoint binding="customBinding" bindingConfiguration="CustomBinding_ITheService_Secured" contract="ITheService" behaviorConfiguration="EndPointBehavior_ITheService" />
</service>
</services>
<bindings>
<customBinding>
<binding name="CustomBinding_ITheService">
<httpTransport keepAliveEnabled="True" transferMode="Streamed" authenticationScheme="None" maxBufferSize="2147483647" maxReceivedMessageSize="2147483647" manualAddressing="true" />
</binding>
<binding name="CustomBinding_ITheService_Secured">
<httpsTransport keepAliveEnabled="True" transferMode="Streamed" authenticationScheme="None" maxBufferSize="2147483647" maxReceivedMessageSize="2147483647" manualAddressing="true" />
</binding>
</customBinding>
</bindings>
Then every things goes the right way and works perfectly.
In case you develop on visual Studio and use IIS-Express "Cassini", remember to enable SSL option in the properties of the website-project, that tells IIS-Express to prepare a base URL for the HTTPS transport that you previously added to binding.
Add site bindingGo to the IIS => then Default Website=> right Click on that => Edit Bindings=> click on ADD Button=> add HTTPS bindings there
Details ARE in shown screenshot

Ajax call to WCF Web Service returns 400 Bad Request [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
WCF Web Service returns “Bad Request” error when invoked through Javascript
I have a simple WCF web service Service1 with just one method Test() which returns a string. I have deployed this web service on a test machine, but when I try to invoke the Test method from the browser I simply get a 400 Bad Request error. The same happens when I try to invoke the method through an AJAX GET request. But surprisingly, the method returns the correct result when invoked through the WCFTestClient.
Here is the code:
[ServiceContract]
public interface IService1
{
// This method can be called to get a list of page sets per report.
[OperationContract]
[WebGet]
string Test();
}
public class Service1 : IService1
{
public string Test()
{
return "test";
}
}
This is my AJAX request:
var serverUrl1 = 'http://' + baseUrl + ':86/Service1.svc';
function GetTestString()
{
var methodUrl = serverUrl1 + "/Test";
$.ajax({
async: false,
type: "GET",
contentType: "application/json; charset=utf-8",
dataType: "json",
url: methodUrl,
beforeSend: function (XMLHttpRequest) {
//ensures the results will be returned as JSON.
XMLHttpRequest.setRequestHeader("Accept", "application/json");
},
success: function (data) {
ShowQRGSlides(data.d);
},
error: function (XmlHttpRequest, textStatus, errorThrown) {
alert("ERROR: GetAvailablePages() Check your browsers javascript console for more details." + " \n XmlHttpRequest: " + XmlHttpRequest + " \n textStatus: " + textStatus + " \n errorThrown: " + errorThrown);
}
});
}
Here is the web.config file for my web service:
<?xml version="1.0"?>
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
<customErrors mode="Off"/>
</system.web>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior>
<!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
<serviceMetadata httpGetEnabled="true"/>
<!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
</configuration>
This is just the simple web.config which gets automatically generated. I am unable to figure out why this simple web service method is not accessible through the browser or ajax. The same method returns the result when accessed through the WCFTestClient.
Any inputs will be greatly appreciated! Thanks.
You need to add service section to your web.config file. Host does not know that you want to use webHttpBinding unless you tell him.
<services>
<service name="Service1">
<endpoint address=""
binding="webHttpBinding"
contract="IService1" />
</service>
</services>
Link below provides detailed instructions for hosting service in IIS (with wsHttpBinding). You just need to use webHttpBinding instead of wsHttpBinding -
http://msdn.microsoft.com/en-us/library/ms733766.aspx

AJAX Cross Domain Image Post to WCF Service

I've been stuck for 2 days on this.
Can someone please provide an example of how to do a cross domain AJAX post to a WCF service?
I'm trying to upload an image to the WCF server.
EDIT
WCF Service:
[WebInvoke(UriTemplate = "/upload", Method = "POST", ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Wrapped), CorsEnabled]
void UploadImage(Stream image);
Ajax Call:
function UploadImage() {
image = document.getElementById("myimage").src;
var data = '{"image": "' + image + '"}'
//alert(data);
$.ajax({
url: "http://localhost:44665/api/upload",
type: "POST",
contentType: "application/json",
data: data,
success: function (result) {
alert("success");
},
error: function (jqXHR, textStatus, errorThrown) {
console.log(jqXHR.responseText);
}
});
}
I can get this to work if I change the WCF paramter from Stream to string. But I need to upload an image and not a string.
I am now getting a WCF error that says:
The server encountered an error processing the request. See server logs for more details.
** Edit 2 **
I added the global.asax code mentioned in the below answer and added this to my web.config:
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
</system.web>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="myServiceBehavior">
<servicedebug includeexceptiondetailinfaults="true" />
</behavior>
<behavior name="">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true"
aspNetCompatibilityEnabled="true"/>
</system.serviceModel>
</configuration>
I now get an error in the Google Chrome console that says:
POST http://localhost:44665/api/upload 500 (Internal Server Error)
So you are trying to make a POST operation from JavaScript to a WCF service that is hosted in another domain. Normally you can't do that without doing some special settings in the WCF service side.
You have to add the following headers to the response from Global.asax.cs in the service side (If the service project doesn't contains Global.asax.cs create one).
protected void Application_BeginRequest(object sender, EventArgs e)
{
//..
EnableCrossDomainCall();
}
private void EnableCrossDomainCall()
{
// this header tells that from any domain you can access me.
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "*");
if (HttpContext.Current.Request.HttpMethod == "OPTIONS")
{
// this one tells about the supported methods to client.
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods",
"GET, POST, OPTIONS");
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers",
"Content-Type, Accept");
HttpContext.Current.Response.AddHeader("Access-Control-Max-Age", "1728000");
HttpContext.Current.Response.End();
}
}
UPDATE:
You can't just post any file through AJAX, through AJAX you can only transfer data. You can use this plugin that uses hidden iframe to upload files that imitates like AJAX.
You can handle the stream object in WCF side as in this link. Try uploading small size images first and you can control the maximum size by setting the maxRequestLength in web.config.
I had this problem and tried the code did not work.
I changed the code and started to work.
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "*");
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "GET, POST,OPTIONS");
if ((HttpContext.Current.Request.HttpMethod == "OPTIONS"))
{
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "Content-Type, Accept");
HttpContext.Current.Response.AddHeader("Access-Control-Max-Age", "1728000");
HttpContext.Current.Response.End();
}

Resources