I wrote two Ajax calls that request data from stored procedures (in SQL Server), sp_ahtreatmentselect and sp_inventoryselect. Here is how the functions look like in the Breeze controller.
[HttpPost]
[ActionName("getinventories")]
public object GetInventories(HttpRequestMessage request)
{
var data = request.Content.ReadAsFormDataAsync().Result;
var opId = data["operationid"];
string query = "sp_inventoryselect #operationId";
SqlParameter operationId = new SqlParameter("#operationId", opId);
return UnitOfWork.Context().ExecuteStoreQuery<GetInventories>(query, operationId);
}
[HttpPost]
[ActionName("gettreatments")]
public object GetTreatments(HttpRequestMessage request)
{
var data = request.Content.ReadAsFormDataAsync().Result;
var opId = data["operationid"];
string query = "sp_ahtreatmentselect #operationId";
SqlParameter operationId = new SqlParameter("#operationId", opId);
return UnitOfWork.Context().ExecuteStoreQuery<GetTreatments>(query, operationId);
}
Now, on client-side, the Ajax calls look like this:
var ajaxImpl = breeze.config.getAdapterInstance('ajax');
function treatments(id) {
return ajaxImpl.ajax({
type: 'POST',
url: serviceName + '/gettreatments',
data: { operationid: id },
success: function(data) {
console.log('Success!');
},
error: function(error) {
console.log('Error!');
}
});
}
function inventories(id) {
return ajaxImpl.ajax({
type: 'POST',
url: serviceName + '/getinventories',
data: { operationid: id },
success: function (data) {
console.log('Success!');
},
error: function(error) {
console.log('Error!');
}
});
}
return inventories(id).then(treatments(id))
.then(function() {
// Do something
})
.fail(function(error) {
// Display error
});
Both Ajax calls work fine, BUT problem is, // Do something is run BEFORE inventories(id) and treatments(id) are run. I would like it to work the other way around instead. I also tried $.when(inventories(id), treatments(id)).then(...) and $.when(ajaxImpl.ajax(...), ajaxImpl.ajax(...)).then(...), but same problem occurs. How do I solve this?
Thanks in advance.
I realized that the issue lay on synchronous calls, not Breeze. I used queue.js to make Ajax calls and // Do something and the calls are completed. Here is how.
var ajaxImpl = breeze.config.getAdapterInstance('ajax'),
serviceName = 'some/service',
id = 1; // Could be any number
return queue()
.defer(function(callback) {
ajaxImpl.ajax({
type: 'POST',
url: serviceName + '/getinventories',
data: { operationid: id },
success: function (data) {
console.log('Success!');
callback(null, data);
});
})
.defer(function(callback) {
ajaxImpl.ajax({
type: 'POST',
url: serviceName + '/gettreatments',
data: { operationid: id },
success: function (data) {
console.log('Success!');
callback(null, data);
});
})
.awaitAll(function(error, results) {
if (error) {
console.log('Error! ' + error);
} else {
// Do something, given that:
// results[0] are inventories, and
// results[1] are treatments
}
});
I don't know what this has to do with Breeze. Did you get your ajaxImpl from a Breeze ajax adapter? I've looked at both ajax adapters shipped with Breeze and neither of them returns anything from a call to the ajax method!
Accordingly, you're expression should have died immediately with a reference error when it got to the .then in return inventories(id).then(.... I don't see how it could have gotten to \\ do something at all.
Something isn't right with the way you've posed this question.
Once you get beyond this I still don't see how this involves Breeze. Breeze won't do anything with the results of your service requests.
I'm completely flummoxed by your question.
Related
Trying to be more consistent with HTTP verbs, I'm trying to call a delete Handler on a Razor Page via AJAX;
Here's my AJAX code, followed by the C# code on my page :
return new Promise(function (resolve: any, reject: any) {
let ajaxConfig: JQuery.UrlAjaxSettings =
{
type: "DELETE",
url: url,
data: JSON.stringify(myData),
dataType: "json",
contentType: "application/json",
success: function (data) { resolve(data); },
error: function (data) { reject(data); }
};
$.ajax(ajaxConfig);
});
my handler on my cshtml page :
public IActionResult OnDeleteSupprimerEntite(int idEntite, string infoCmpl)
{
// my code
}
which never reaches ... getting a bad request instead !
When I switch to a 'GET' - both the type of the ajax request and the name of my handler function ( OnGetSupprimerEntite ) - it does work like a charm.
Any ideas ? Thanks !
Short answer: The 400 bad request indicates the request doesn't fulfill the server side's needs.
Firstly, your server is expecting a form by;
public IActionResult OnDeleteSupprimerEntite(int idEntite, string infoCmpl)
{
// my code
}
However, you're sending the payload in application/json format.
Secondly, when you sending a form data, don't forget to add a csrf token:
#inject Microsoft.AspNetCore.Antiforgery.IAntiforgery Xsrf
<script>
function deleteSupprimerEntite(myData){
var url = "Index?handler=SupprimerEntite";
return new Promise(function (resolve, reject) {
let ajaxConfig = {
type: "DELETE",
url: url,
data: myData ,
success: function (data) { resolve(data); },
error: function (data) { reject(data); }
};
$.ajax(ajaxConfig);
})
}
document.querySelector("#testbtn").addEventListener("click",function(e){
var myData ={
idEntite:1,
infoCmpl:"abc",
__RequestVerificationToken: "#(Xsrf.GetAndStoreTokens(HttpContext).RequestToken)",
};
deleteSupprimerEntite(myData);
});
</script>
A Working Demo:
Finally, in case you want to send in json format, you could change the server side Handler to:
public class MyModel {
public int idEntite {get;set;}
public string infoCmpl{get;set;}
}
public IActionResult OnDeleteSupprimerEntite([FromBody]MyModel xmodel)
{
return new JsonResult(xmodel);
}
And the js code should be :
function deleteSupprimerEntiteInJson(myData){
var url = "Index?handler=SupprimerEntite";
return new Promise(function (resolve, reject) {
let ajaxConfig = {
type: "DELETE",
url: url,
data: JSON.stringify(myData) ,
contentType:"application/json",
headers:{
"RequestVerificationToken": "#(Xsrf.GetAndStoreTokens(HttpContext).RequestToken)",
},
success: function (data) { resolve(data); },
error: function (data) { reject(data); }
};
$.ajax(ajaxConfig);
})
}
document.querySelector("#testbtn").addEventListener("click",function(e){
var myData ={
idEntite:1,
infoCmpl:"abc",
};
deleteSupprimerEntiteInJson(myData);
});
I would like to store a response result from an ajax call. This is because the ajax is the main API call used by several functions to extract information from an API.
I call callAPI function more than 8 times in my app.
Of course, I can duplicate the function callAPI 8 times to properly get information but this is not cool way to code.
var result = callAPI("GET",url,'');
$('#status').val(result.success);
$('#output').val(result);
function callAPI(method_input, url_input, body_input){
var urli = url_input;
var datai = body_input;
var method = method_input;
$.ajax({
url: urli,
beforeSend: function(xhrObj){
xhrObj.setRequestHeader("some header","some value");
},
type: method,
data: datai,
})
.done(function(data,status) {
console.log("success");
console.log(data);
return JSON.stringify(data);
})
.fail(function(data,status) {
console.log("error");
console.log(data);
return JSON.stringify(data);
});
}
I tried to store the return value using
var result = ajax(value);
but the result is empty
is there any way to store return value of a function to a variable?
EDIT
I Solved this problem by using callback function like below
function callbackResult(result){
$('#status').val(result.success);
$('#output').val(result);
}
function callAPI(method_input, url_input, body_input, callback){
var urli = url_input;
var datai = body_input;
var method = method_input;
$.ajax({
url: urli,
beforeSend: function(xhrObj){
xhrObj.setRequestHeader("some header","some value");
},
type: method,
data: datai,
})
.done(function(data,status) {
console.log("success");
console.log(data);
return JSON.stringify(data);
callback(data);
})
.fail(function(data,status) {
console.log("error");
console.log(data);
return JSON.stringify(data);
callback(data);
});
}
This was my first function to use a callback function and now I know what the callback function is.
Thank you guys all.
You need 'async': false, so:
var result = $.ajax({
url: "https://api.github.com/users",
'async': false,
type: 'GET'
})
.done(function(data,status) {
console.log("success");
})
.fail(function(data,status) {
console.log("error");
});
console.log("result: " + result.responseText);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
A few things to note:
Instead of JSON.stringify() I think you want to use JSON.parse() to parse the JSON string that is probably been returned by your API.
You can use the $.ajax option dataType to automatically parse the JSON string into an object.
$.ajax() returns a promise which can be chained to add as many callbacks as needed.
A more elegant solution would be to return the promise from your function and chain your callbacks. Ex:
function callAPI(method_input, url_input, body_input) {
var urli = url_input;
var datai = body_input;
var method = method_input;
return $.ajax({
url: urli,
// Automatically parses JSON response
dataType: 'json',
beforeSend: function(xhrObj) {
xhrObj.setRequestHeader("some header", "some value");
},
type: method,
data: datai,
})
.done(function(data, status) {
console.log("success");
console.log(data);
})
.fail(function(data, status) {
console.log("error");
console.log(data);
});
}
callAPI('GET', '').then(function(result){
// Do something with my API result
});
If you plan on making all request at once, with this solution you can consider aggregating all the request into a single promise with $.when(). Ex:
$.when(
callAPI('GET', ''),
callAPI('GET', 'second'),
callAPI('GET', 'third')
).then(function(firstResult, secondResult, thirdResult){
// Do stuff with the result of all three requests
});
I'm the similar ajax requests to get other database info working. Perhaps its something minor that is causing the issue. Each time I execute this function it fails and throws the alert.
It is returning the 13 user records stored in my database, during debugging I can see that these 13 records are all correct.
My dissertation is due on Friday, so any help with this would be much appreciated.
function FetchUsers() {
userinfo = [];
$.ajax({
type: "GET", url: "/home/GetUsers",
success: function (data) {
$.each(data, function (i, v) {
userinfo.push({
usersId: v.UserID,
username: v.Username,
});
})
},
error: function (error) {
alert('failed - error 01.000x unable to load users');
}
})
}
public JsonResult GetUsers()
{
using (MyDatabaseEntities1 dc = new MyDatabaseEntities1())
{
var users = dc.Users.ToList();
return new JsonResult { Data = users, JsonRequestBehavior = JsonRequestBehavior.AllowGet };
}
}
I have this ajax post method in my code that returns undefined. I think its because I have not passed in any data, any help will be appreciated.
I have tried passing the url string using the #Url.Action Helper and passing data in as a parameter in the success parameter in the ajax method.
//jquery ajax post method
function SaveEvent(data) {
$.ajax({
type: "POST",
url: '#Url.Action("Bookings/SaveBooking")',
data: data,
success: function (data) {
if (data.status) {
//Refresh the calender
FetchEventAndRenderCalendar();
$('#myModalSave').modal('hide');
}
},
error: function (error) {
alert('Failed' + error.val );
}
})
}
//controller action
[HttpPost]
public JsonResult SaveBooking(Booking b)
{
var status = false;
using (ApplicationDbContext db = new ApplicationDbContext())
{
if (b.ID > 0)
{
//update the event
var v = db.Bookings.Where(a => a.ID == a.ID);
if (v != null)
{
v.SingleOrDefault().Subject = b.Subject;
v.SingleOrDefault().StartDate = b.StartDate;
v.SingleOrDefault().EndDate = b.EndDate;
v.SingleOrDefault().Description = b.Description;
v.SingleOrDefault().IsFullDay = b.IsFullDay;
v.SingleOrDefault().ThemeColor = b.ThemeColor;
}
else
{
db.Bookings.Add(b);
}
db.SaveChanges();
status = true;
}
}
return new JsonResult { Data = new { status } };
}
Before the ajax call, you should collect the data in object like,
var requestData= {
ModelField1: 'pass the value here',
ModelField2: 'pass the value here')
};
Please note, I have only added two fields but as per your class declaration, you can include all your fields.
it should be like :
function SaveEvent(data) {
$.ajax({
type: "POST",
url: '#Url.Action(Bookings,SaveBooking)',
data: JSON.stringify(requestData),
dataType: 'json',
contentType: 'application/json; charset=utf-8',
success: function (data) {
if (data.status) {
//Refresh the calender
FetchEventAndRenderCalendar();
$('#myModalSave').modal('hide');
}
},
error: function (error) {
alert('Failed' + error.val );
}
})
}
Try adding contentType:'Application/json', to your ajax and simply have:
return Json(status);
In your controller instead of JsonResult. As well as this, You will need to pass the data in the ajax code as a stringified Json such as:
data:JSON.stringify(data),
Also, is there nay reason in particular why it's a JsonResult method?
There is an Api method called via Ajax. After parsing and other necessary things has been finished, I get the following result.
["IG4","E1 ","E16"]
As soon as the results received, it calls another MVC ActionResult to display data from the database, where the postcode attribute of the object contains one of these Json results. However it does not work.
public ActionResult SearchResult(JsonResult postcode)
{
var posts = db.Posts.Where(p => p.PostCode.Contains(postcode));
return PartialView("postlist", posts);
}
When the ActionResult is called via Ajax, I checked what url is being called and got the following result
SearchResult?postcode%5B%5D=IG4&postcode%5B%5D=E1+&postcode%5B%5D=E16
$('#searchBtn').on('click', function () {
var _postcode = $('#searchPostcode').val();
var _distance = $('#searchDistance').val();
alert("postcode " + _postcode + " distance " + _distance);
var _url = '#Url.Action("GetPostcodesWithin", "Api/PostcodeApi")'; // don't hard code url's
$.ajax({
type: "GET",
url: _url,
data: { postcode: _postcode, distance: _distance },
success: function(data) {
alert("search ok");
$.ajax({
type: "GET",
url: '#Url.Action("SearchResult", "Posts")',
data: { postcode: data },
success: function (data) {
alert("Post results called");
$("#postList").html(data).show();
},
error: function (reponse) {
alert("error : " + reponse);
}
});
},
error: function (reponse) {
alert("error : " + reponse);
}
});
});
Json data returned from GetPostcodesWithin method is displayed on the top, which is passed onto SearchResult
You first need to change the method to
public ActionResult SearchResult(IEnumerable<string> postcode)
Then change the 2nd ajax call to
$.ajax({
type: "GET",
url: '#Url.Action("SearchResult", "Posts")',
data: { postcode: data },
traditional: true, // add this
success: function (data) {
....
}
})
The parameter postcode in the SearchResult() method will then contain the 3 string values from your array.
Because you now have a collection of strings, your query now needs to be
var posts = db.Posts.Where(p => postcode.Contains(p.PostCode));
Side note: Your second value contains a space ("EF ") which may need to be trimmed?