I try to call a ASP MVC action from outside of the domain via ajax.
Setup
I have hosted a MVC application with this action inside:
[HttpPost]
[AllowAnonymous]
public ActionResult AjaxLogin(LoginViewModel model)
{
[..Login stuff..]
return Json(new { Url: "...", Result: "..." });
}
Usage
For testing I try a manuell call with a HttpRequester addon from Firefox, with this result:
It is working correct and the answer is as expected. So now I want to made an ajax call from a second web page (different domain).
My jquery (2.2.0) ajax call looks like this:
var requestData = {
model: {
Email: emailValue,
Password: passwordValue
}
};
var requestPlain = JSON.stringify(requestData);
$.ajax({
url: json_login_url,
data: requestData,
method: 'POST',
async: false,
contentType: 'application/json; charset=utf-8',
dataType: 'json',
success: function (result, textStatus, jqXHR) {
[...]
},
error: function (jqXHR, textStatus, errorThrown) {
[...]
},
beforeSend: function (jqXHR, settings) {
return true;
},
complete: function (jqXHR, textStatus) {
},
});
Problem
The ajax call only gives me an error.
SO why is my testcall working but my ajax call not?
Attempts
I also tried a network analysis with the firefox debugging tools.
But I don't understand why it is not working because it shows "status-code 200" but the result is empty!?
This may or may not solve your issue, but if you're making cross-domain AJAX calls, make sure you set up your CORS:
Setting Access-Control-Allow-Origin in ASP.Net MVC - simplest possible method
Related
I use the following ajax script.
$.ajax({
dataType: 'json',
url: url,
data: tuDispId,
type: "GET",
success: function (data) {
bindData(data);
$("#alert-placeholder").empty();
$('#alert-placeholder').removeClass('alert alert-danger');
},
error: function (xhr, textStatus, errorThrown) {
$('#alert-placeholder').addClass('alert alert-danger');
$('#alert-placeholder').html(errorThrown);
}
});
The attribute Route in Web API before method.
[Route("api/tudisp/Edit/{tuDispId}")]
public IHttpActionResult Edit(int tuDispId)
{
}
The genarated request from ajax.
http://localhost:xxxxx/api/tudisp/Edit/?179
How to force ajax to not generate sign '?' by id parameter.
The simplest way to do it is to change the url property of the Ajax options...
$.ajax({
dataType: 'json',
url: "http://localhost:xxxxx/api/tudisp/Edit/" + tuDispId,
type: "GET",
success: function (data) {
bindData(data);
$("#alert-placeholder").empty();
$('#alert-placeholder').removeClass('alert alert-danger');
},
error: function (xhr, textStatus, errorThrown) {
$('#alert-placeholder').addClass('alert alert-danger');
$('#alert-placeholder').html(errorThrown);
}
});
GET parameters are automatically appended to the Url as a querystring, which is fine if that's what your application is expecting, but not when you're using routing as you are.
However, if you wanted to modify existing Ajax requests you can use prefiltering. This example modifies the Url of the ajax call, replacing {variable} with a given value from the data object...
$.ajaxPrefilter(function(options, originalOptions, jqXHR) {
options.data = ""; // this removes the querystring
for (key in originalOptions.data) {
options.url = options.url.replace("{" + key + "}", originalOptions.data[key]);
}
});
$.ajax({
url: "http://localhost:xxxxx/api/tudisp/Edit/{tuDispId}",
data: {
"tuDispId": 179
}
});
If you wanted to use something like that then I'd strongly recommend spending a bit of time making it more robust, but it's an example of how you could do what you want.
I have tried to use AJAX call in an MVC5 project as many similar examples on the web, but every time there is an error i.e. antiforgerytoken, 500, etc. I am looking at a proper AJAX call method with Controller Action method that has all the necessary properties and sending model data from View to Controller Action. Here are the methods I used:
View:
#using (Html.BeginForm("Insert", "Account", FormMethod.Post, new { id = "frmRegister" }))
{
#Html.AntiForgeryToken()
//code omitted for brevity
}
<script>
AddAntiForgeryToken = function (data) {
data.__RequestVerificationToken = $('#__AjaxAntiForgeryForm input[name=__RequestVerificationToken]').val();
return data;
};
$('form').submit(function (event) {
event.preventDefault();
//var formdata = JSON.stringify(#Model); //NOT WORKING???
var formdata = new FormData($('#frmRegister').get(0));
//var token = $('[name=__RequestVerificationToken]').val(); //I also tried to use this instead of "AddAntiForgeryToken" method but I encounter another error
$.ajax({
type: "POST",
url: "/Account/Insert",
data: AddAntiForgeryToken({ model: formdata }),
//data: { data: formdata, __RequestVerificationToken: token },
//contentType: "application/json",
processData: false,
contentType: false,
datatype: "json",
success: function (data) {
$('#result').html(data);
}
});
});
</script>
Controller: Code cannot hit to this Action method due to antiforgerytoken or similar problem.
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public JsonResult Insert(RegisterViewModel model)
{
try
{
//...
//code omitted for brevity
}
}
I just need a proper AJAX and Action methods that can be used for CRUD operations in MVC5. Any help would be appreciated.
UPDATE: Here is some points about which I need to be clarified:
1) We did not use "__RequestVerificationToken" and I am not sure if we send it to the Controller properly (it seems to be as cookie in the Request Headers of Firebug, but I am not sure if it is OK or not). Any idea?
2) Should I use var formdata = new FormData($('#frmRegister').get(0)); when I upload files?
3) Why do I have to avoid using processData and contentType in this scenario?
4) Is the Controller method and error part of the AJAX method are OK? Or is there any missing or extra part there?
If the model in your view is RegisterViewModel and you have generated the form controls correctly using the strongly typed HtmlHelper methods, then using either new FormData($('#frmRegister').get(0)) or $('#frmRegister').serialize() will correctly send the values of all form controls within the <form> tags, including the token, and it is not necessary to add the token again.
If your form does not include a file input, then the code should be
$('form').submit(function (event) {
event.preventDefault();
var formData = $('#frmRegister').serialize();
$.ajax({
type: "POST",
url: '#Url.Action("Insert", "Account")', // do not hard code your url's
data: formData,
datatype: "json", // refer notes below
success: function (data) {
$('#result').html(data);
}
});
});
or more simply
$.post('#Url.Action("Insert", "Account")', $('#frmRegister').serialize(), function(data) {
$('#result').html(data);
});
If you are uploading files, then you need you need to use FormData and the code needs to be (refer also this answer and
$('form').submit(function (event) {
event.preventDefault();
var formData = new FormData($('#frmRegister').get(0));
$.ajax({
type: "POST",
url: '#Url.Action("Insert", "Account")',
data: formData,
processData: false,
contentType: false,
datatype: "json", // refer notes below
success: function (data) {
$('#result').html(data);
}
});
});
Note that you must set both processData and contentType to false when using jQuery with FormData.
If you getting a 500(Internal Server Error), it almost always means that your controller method is throwing an exception. In your case, I suspect this is because your method is returning a partial view (as suggested by the $('#result').html(data); line of code in you success callback) but you have specified that the return type should be json (your use of the datatype: "json", option). Note that it is not necessary to specify the dataType option (the .ajax() method will work it out if its not specified)
If that is not the cause of the 500(Internal Server Error), then you need to debug your code to determine what is causing the expection. You can use your browser developer tools to assist that process. Open the Network tab, run the function, (the name of the function will be highlighted), click on it, and then inspect the Response. It will include the details of the expection that was thrown.
contentType should be application/x-www-form-urlencoded
Try this code
<script>
$('form').submit(function (event) {
event.preventDefault();
$.ajax({
method: "POST",
url: "/Account/Insert",
data: $(this).serialize(),
contentType:"application/x-www-form-urlencoded",
success: function (data) {
$('#result').html(data);
},
error: function (jqXHR, textStatus, errorThrown) {
console.log(errorThrown);
}
});
});
</script>
I have a add button it calls the controller does what it needs to do but it never calls the success function from the chrome browser? Works in IE so I know it is getting called with another browser not sure why chrome is not working?
$('#ui_btn_AddItem').click(function () {
//...getting the data values here....
$.ajax({
url: "/userGroup/CopyItem",
type: "POST",
dataType: "json",
contentType: "application/json; charset=utf-8",
data: { "id": distribId, "selectedIDs": selectedValues },
success: function (data) {
alert('success');
window.location(data.retUrl); // Success Callback
},
error: function (req, status, error) {
alert('error');
bootbox.alert(req.responseText);
}// error: errorCallback
});
});
My controller is called like [HttpPost]
public ActionResult CopyItem(
...doing some copy stuff then returning the json result.
return Json(new { success = true, retUrl = returnUrl }, JsonRequestBehavior.AllowGet);
not sure why my alert doesn't come up with chrome any ideas?
In jquery that is.
I would like something that works as the success-pararameter, but that is run when the function is called, rather than once I get the response.
sample (oajax is an extension of ajax for open auth)
$.oajax({
url: url,
jso_provider: "facebook", // Will match the config identifier
jso_scopes: false, // List of scopes (OPTIONAL)
dataType: 'json',
success: function(data) {
fbposts=data.data
//a bunch of code irellevant for the question
},//success done
error: function() {
console.log("ERROR Custom callback()");
}
})
};
Are you looking for .ajaxSend() ?
Attach a function to be executed before an Ajax request is sent.
This function (and .ajaxComplete et al) allow you to register callback functions that are called for the different phases of every AJAX request.
In a normal ajax function, you pass it as beforeSend:
$.ajax({
url: url,
dataType: 'json',
beforeSend: function(jqXHR, status){
// CODE HERE
},
success: function(data) {
fbposts=data.data
},
error: function() {
console.log("ERROR Custom callback()");
}
})
};
You'll have to check if oajax have this event too, but it probably do
I am using render partial concept in MVC. Its not showing the output in div. While debugging everything is OK (Showing Staus 200 OK) but its not going inside success block.Below is my jquery function.
function ShowNavigation() {
var jsonObj = {
'Display': 'Index',
taFormula: $('#taFormula').val()
};
$.ajax(
{
url: "/Home/Index",
type: "POST",
data: jsonObj,
dataType: "json",
contentType: 'application/json; charset=utf-8',
success: function (data) {
var message = data.Message;
$("#contentDiv").html(message).val();
}
});
}
My Controller code is:
[HttpPost]
public ActionResult Index(FormCollection collection)
{
var val = collection["taFormula"].ToString();
ViewBag.Output = GetValue(val);
return View();
}
Remove the datatype: "json" bit. You're receiving html back from the server, not json data, but because of that setting it's trying to parse it and failing. If you had an error callback function it would go into that.
Also, you don't need the .val() on $("#contentDiv").html(message).val();
Try adding an error handler to the ajax call and see if that gives you any more information:
error: function (xhr, status, error) {
alert(status + " : " + error);
}
Try this for your json object:
data: JSON.stringify(jsonObj),
You might need to include json.js for older browsers.