I want to retrieve some data using $.ajax from the external ASP.NET MVC site (in this case - from my site). The code below geive me a 404 Not Found error (of course the url is valid.
But, if I change the url from url: 'http://myurl.com/Home/GetMyCode/?id=mycode' to url: 'http://localhost:123/Home/GetMyCode/?id=mycode' everything is fine. So, how to fix it ?
$.ajax({
url: 'http://myurl.com/Home/GetMyCode/?id=mycode',
type: 'POST',
contentType: "application/json; charset=utf-8",
crossDomain: true,
success: function (res) {
...
},
error: function (jqXHR, textStatus, errorThrown) {
...
}
});
[HttpPost]
public JsonResult GetMyCode(string id)
{
try
{
return Json(new { result = "ok", resultData = "OK") });
}
catch (Exception e)
{
return Json(new { result = "error", resultData = "An error occured" });
}
}
Two Methods for Handling Cross-Domain Ajax Calls:
JSONP: The Current Standard for Cross-Domain Access
JSONP is a convention used by some sites to expose their content in a way that makes it easier for callers to consume data via script, even from an external domain. The trick consists in having the site return some JSON content not as a plain string but wrapped up in a script function call. For more details..
http://www.west-wind.com/weblog/posts/2007/Jul/04/JSONP-for-crosssite-Callbacks
http://www.jquery4u.com/json/jsonp-examples/
Cross-origin resource sharing (CORS)
To enable cross-domain requests in environments that do not support cors yet but do allow cross-domain XHR requests (windows gadget, etc), set $.support.cors = true;
You just tell jQuery that you're in an environment where Cross-Domain XHR requests are possible.
In order to retrieve data crossdomain, you probably need to use 'jsonp'
Looks like it might be a DNS issue. Are you able to get to: http://myurl.com ?
Is the .com domain you are trying to access publicly accessible? Or is it a loopback to localhost?
that tutorial worked for me, I had to implement the JSONP handling in my MVC project. http://www.codeguru.com/csharp/.net/net_asp/using-jsonp-in-asp.net-mvc.htm
Related
This is only a problem for me in my newest dot net core 2 web app, it works in previous dot net apps with no issue.
I have a custom javascript file with paths to various servers that my site is hosted on(mainly dev, test, live).
My ajax call looks like the following:
var gameid = '#Html.Raw(Model.Id)';
$.ajax({
type: 'GET',
url: url() + "UserGames/HasGame?id=" +gameid,
cache: false,
success: function (data) {
console.log(data);
},
error: function (req, status, err) {
console.log('Something went wrong', status, err);
}
});
The url() in question is simply looking at my local server while testing(*please note, this port has been edited, it is correct):
function url() {
return "https://localhost:4432/";
}
The error is not firing as it isnt even reaching the controller function being used.
I'm absolutely bemused as to why this isnt working, i could understand if i was getting some sort of error back, but i have used ajax calls in all of my apps and not had this problem at all until using core 2.
Has anything changed that may have affected the way you use ajax calls?
Method that is trying to fire, but i mentioned, it isnt hitting the controller(NOTE: the method does have code in it, it just isnt hitting the controller in the first place)
[HttpGet]
[ValidateAntiForgeryToken]
public async Task<IActionResult> HasGame(int id)
{
//stuff in here
}
You are getting a 400 (Bad Request) response because the framework expects the RequestVerificationToken as part of the request.The framework uses this to prevent possible CSRF attacks. If your request does not have this information, the framework will return the 400 bad request. Your current code is not sending it.
You can fix it by explicitly send that RequestVerificationToken
The form tag helper automatically creates a hidden input with name atttribute value __RequestVerificationToken and stores the token as the value of the hidden input.
var token = $("[name='__RequestVerificationToken']").val();
var gameid = '#Html.Raw(Model.Id)';
$.ajax({
type: 'GET',
url: url() + "UserGames/HasGame?id=" +gameid,
headers:{ "RequestVerificationToken": token },
success: function (data) {
console.log(data);
},
error: function (req, status, err) {
console.log('Something went wrong', status, err);
}
});
In the above example, we are using some jQuery code to get the input element with name __RequestVerificationToken and reading the value of it. A more robust approach would be injecting the IAntiforgery implementation to the view and using the GetAndStoreTokens method.
We will be injecting IHttpContextAccessor to the view. So make sure it is wired up with DI properly. Add this line to your Startup classes' ConfigureServices method.
services.AddTransient<IHttpContextAccessor, HttpContextAccessor>();
Now in your view, you can inject IHttpContextAccessor and IAntiforgery and then call the GetAndStoreTokens to get the token. Here i wrapped that into a helper function.
#inject Microsoft.AspNetCore.Http.IHttpContextAccessor HttpContext
#inject Microsoft.AspNetCore.Antiforgery.IAntiforgery Xsrf
#functions{
public string GetAntiXsrfRequestToken()
{
return Xsrf.GetAndStoreTokens(HttpContext.HttpContext).RequestToken;
}
}
Now later in my js, i can call this method inside my javascript code instead of using jQuery to get the input value.
var token = "#GetAntiXsrfRequestToken()";
var gameid = '#Html.Raw(Model.Id)';
$.ajax({
type: 'GET',
url: url() + "UserGames/HasGame?id=" +gameid,
headers:{ "RequestVerificationToken": token },
success: function (data) {
console.log(data);
},
error: function (req, status, err) {
console.log('Something went wrong', status, err);
}
});
Or Simply remove [ValidateAntiForgeryToken] attribute decoration from the action method, which excludes this check.
I recommend you to take advantage of the[ValidateAntiForgeryToken] method. Send the token as part of your request(first approach)
If anyone else comes across this issue, i managed to fix it by doing the following to both the call and the controller:
type: 'GET',
url: '#Url.Action("HasGame", "UserGames")',
data: {id : gameid},
And the controller in core 2 does not seem to like you declaring [HttpGet] at all, so i removed that also.
Thanks for all the help provided.
I am getting an error that i dont understand an cannot find any helpfull informations about:
No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'https:*******' is therefore not allowed access. The response had HTTP status code 401.
function RecordTheCall()
{
var key = '*******************';
$.get( "https://api.plivo.com/v1/Account/"+key+"/Call/?status=live", function( data ) {
var callUuid = data.call_uuid
});
$.ajax({
url: "https://api.plivo.com/v1/Account/"+key+"/Call/"+callUuid+"/Record/",
type: "POST",
data: { 'auth_id': auth_id, 'call_uuid': CallUUID },
dataType: "json",
success: function (res) {
alert(res);
},
error: function(err) {
alert(err);
}
});
}
Call recording cannot be accomplished from the Web SDK directly. You cannot use the Plivo API from your Web browser using Javascript because cross-domain ajax requests are not allowed in browsers for security reasons.
This has been explained in this Wikipedia article. There are some work arounds to overcome this, but it is browser dependent and hence it might not work always. Instead you should use the Plivo XML/API in you application.
Im trying to access gisgraphys api with this code:
$('[id$=PlaceOfDeparture]:not(.ui-autocomplete-input)').live('focus', function() {
$(this).autocomplete({
source: function (request, response) {
$.ajax({
type: 'POST',
datatype: 'jsonp',
url: 'http://services.gisgraphy.com/fulltext/fulltextsearch?q='+ request.term,
//data: {
// q: request.term
//},
success: function(res) {
console.log("Success: " + res);
},
error: function(res) {
console.log("Error: " + res);
}
});
}
});
});
when i do that i get error:
XMLHttpRequest cannot load http://services.gisgraphy.com/fulltext/fulltextsearch?q=viborgsslingan. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'mylocalhost' is therefore not allowed access.
if i press the link i get the xml in the browser just as i want it. Somehow it wont get to my code. Ive search a bit about the problem but it seems to be a security problem on the gisgraphy server... Is there anything i can do to make this cross-domain access work?
Ive search a bit about the problem but it seems to be a security problem on the gisgraphy server...
It’s not a security problem, rather the other way around. The Same Origin Policy forbids you from requesting data from other domains in JS via AJAX, unless the remote domain signals that it wants to explicitly grant you access (this is called CORS).
If the service you are accessing doesn’t offer that, and no other format that is not restricted by the SOP – like f.e. JSONP – then you can not get that data client-side via JavaScript.
Below is a cross-domain call I'm trying to make via an Ajax call. The web service we're using only returns XML, so I cannot use jsonp as a dataType. As I have it written below, I receive the following error in Chrome's debugger:
Uncaught ReferenceError: Request is not defined
Here is the code:
function GetProgramDetails() {
var URL = "http://quahildy01/xRMDRMA02/xrmservices/2011/OrganizationData.svc/AccountSet?$select=AccountId,Name,neu_UniqueId&$filter=startswith(Name,\'" + $('.searchbox').val() + "\')";
var sourceDomain = Request.Headers["Origin"];
var request = $.ajax({
type: 'POST',
beforeSend: function(request){
request.setRequestHeader("Access-Control-Allow-Origin", sourceDomain)
},
url: URL,
contentType: "application/x-www-form-urlencoded",
crossDomain: true,
dataType: XMLHttpRequest,
success: function (data) {
console.log(data);
alert(data);
},
error: function (data) {
console.log(data);
alert("Unable to process your resquest at this time.");
}
});
}
EDIT
I've tried the following versions of this code and haven't seen anything different in the error message. This is being used in an enterprise environment, so is it possible that, due to security features on the server, it is not possible for this to work? I'm brand new to Ajax, so I don't know if this is something that works 100% of the time or just in a majority of settings.
beforeSend: function (request) {
request.setRequestHeader("Access-Control-Allow-Origin: *")
},
beforeSend: function (request) {
request.setRequestHeader("Access-Control-Allow-Origin: ", "http://localhost:55152")
},
beforeSend: function (request) {
request.setRequestHeader("Access-Control-Allow-Origin", "http://localhost:55152")
},
beforeSend: function (request) {
var sourceDomain = request.Headers["http://localhost:55152"];
request.setRequestHeader("Access-Control-Allow-Origin: ", sourceDomain)
},
beforeSend: function (request) {
var sourceDomain = location.protocol + '//' + location.host;
request.setRequestHeader("Access-Control-Allow-Origin: ", sourceDomain)
},
This is your problem: var sourceDomain = Request.Headers["Origin"]; You have not defined Request with a capital R.
The meat of your problem is going to be in the cross-domain request. This is possible and you're on the right track but Access-Control-Allow-Origin is something that's set on the server as a response header, not something that's sent by the client through XHR as a request header. See https://developer.mozilla.org/en-US/docs/HTTP/Access_control_CORS#Access-Control-Allow-Origin
See the HTML5 Boilerplate .htaccess as an example of how to set this up on Apache https://github.com/h5bp/html5-boilerplate/blob/master/.htaccess and note the browser limitations https://www.bionicspirit.com/blog/2011/03/24/cross-domain-requests.html - notably that this doesn't work in IE7 and that IE doesn't support wildcards *.
Trying to mimic jsonp (returning executable JavaScript code from the server) may be possible with some clever coding but this would be more difficult - Using JSONP when returning XML
Also, if the data is sensitive then you might not want to do any sort of cross-domain request without a private key scheme since I'm not sure if the origin request header can be spoofed. The alternative would be to set up a connection for your websites to share data on the back-end rather than the front-end.
Also, JavaScript function names are not capitalized unless they are constructors.
beforeSend: function(request){
var sourceDomain = request.Headers["Origin"];
request.setRequestHeader("Access-Control-Allow-Origin", sourceDomain)
},
You were attempting to access the request before it was created, thus throwing the undefined error. The request is the jqXHR object which is passed to the beforeSend() callback function.
I'm trying to do a simple ajax GET that returns the html from google.com but with the following I keep hitting my onFailure. And when I hit status i get a 0, yet when I attempt to output the responseText I get nothing.
Anyone done a simple request like this in mootools 1.2.1?
function addSomeAction() {
el.onclick = function() {
var uri = "http://www.google.com";
var myRequest = new Request({
url: uri,
method: 'get',
onRequest: function(){
alert("loading...");
},
onSuccess: function(responseText){
alert("hi");
},
onFailure: function(responseFail){
alert("fail: " + responseFail.responseText);
}
});
myRequest.send();
}
}
Regardless of the framework used, you cannot do cross-domain AJAX requests. This is to prevent Cross-Site Request Forgery (CSRF) attacks and is a limitation imposed by the web browser.
Therefore, you can only fetch the HTML source of a page which on the same domain as the originating request.
There are specifications allowing for the asynchronous transfer of JSON data residing on another domain (JSONP), but they will not help you in this case.