Pass message from Controller to AJAX script in View - javascript

I'm using jQuery and AJAX in the View to send some data to the Controller that writes it to the database. On success I show a div tag with a green background with "OK" text. But what if I do a check first in the Controller if the data already exist in the database, then I would like to alert the user that the data could not be added. Is there a way to pass some kind of message back to the AJAX script?
I guess the success option is just a confirm of contact with the Controller and not a real confirm that everything is OK and the data has been added to the database!?
What action in the Controller would cause the error function in the AJAX code to run?
Finally I just wonder what kind of return I should use since I'm actually not returning anything?
My script in the View:
$.ajax({
url: "/Orders/AddOrder",
type: "GET",
cache: false,
data: { a: order, b: seller },
success: function () {
console.log('AJAX successful');
// Show confirm message
$(".messageOk").show();
$(".messageOk").text("OK").delay(2000).queue(function () {
location.reload();
});
},
error: function () {
????
},
complete: function () {
????
}
});
Controller:
// Add new Resource
public ActionResult AddOrder(int a, int b)
{
var order = new Order
{
OrderNumber = a,
Seller = b
};
db.Orders.Add(order);
db.SaveChanges();
//return new EmptyResult();
return RedirectToAction("Index", "Home"); // ??????
}

You could return the appropriate HTTP status code from your controller action: 409 Conflict.
if (the resource already exists in db) {
return new HttpStatusCodeResult(HttpStatusCode.Conflict);
}
which will trigger the error AJAX function in which you could check whether you are in this situation and act accordingly:
error: function(jqXHR) {
if (jqXHR.status == 409) {
alert('Sorry but this resource already exists');
}
}
As you can see this way it's up to the view to decide what error messages to display based on proper HTTP status codes returned from the server. This way you are not cluttering the server with view logic.

Along with the correct response status code, you can also pass in your response body error messages from the server may be as JSON string or plain string

Related

Javascript processes 200 response before server sends the 200

I have a timing problem with an ASP.NET core 5 system I'm working on. My page shows a DataTable with id='outsideDataTable', and when an item is selected a modal bootstrap dialog is shown. The submit button invokes method submitModal() which does this:
$.ajax({
type: 'POST',
url: '/api/Submit',
dataType: 'json',
statusCode: {
200: SubmitDone()
},
error: 'SubmitError',
data: $('#ModalForm').serialize()
});
The /api/Submit function calls the server's Submit function which does an update to the database. None of the C# code uses async coding. The database interface is NPoco. At the end of the update the function calls Ok() which I believe returns the status 200 to the ajax call.
[HttpPost("api/[action]")]
public IActionResult Submit(
int recordId,
... other formdata ...)
{
if (recordId == 0)
{
var sr = new Record() { ... fill with form data ... };
db.Insert(sr);
}
else
{
var sr = db.Single("select * from Records where recordId=#0", recordId);
if (sr == null)
return BadRequest($"Couldn't find record with ID={recordId}");
... update sr with form data ...
db.Update(sr);
}
return Ok();
}
The OK() function returns status of 200 back to the client, which should now execute the js SubmitDone() function.
function SubmitDone() {
$('#ModalDlg').modal('hide');
$('#outsideDataTable').DataTable().draw();
}
The problem is that when the outsideDataTable is redrawn from within the SubmitDone function, it will retrieve the data, which does not yet include the changes put into the database by the submit action routine. Why is that? In my opinion the database should have done its thing by the time the status 200 is returned to the ajax call, ergo when the redraw happens the database should have the new data.
As a matter of fact, in fiddler I see that the list load from the redraw happens before the ajax to the submit function.
I have not isolated this into working code I can share, but can do so if needed - unless someone knows what I'm doing wrong.
When you assign the SubmitDone function to the statusCode.200 callback you shouldn't use parentheses because this is making the function execute immediately. Instead, it should be like this:
$.ajax({
type: 'POST',
url: '/api/Submit',
dataType: 'json',
statusCode: {
200: SubmitDone
},
error: 'SubmitError',
data: $('#ModalForm').serialize()
});

Ajax request keeps returning error function in Laravel

Good day guys. In my laravel application I'm trying to check if attendence for a particular date, subject, grade exists in my table. If so I have an if statement setup to display desire results based on what is returned.
I'm making the request with ajax but it seems like ajax keeps running the error function and I don't seem to get any error code whatsoever or internal server error(500, 404, 403, etc) In my console the status return is 200 ok
here is my script:
$(document).on('change', '#subject', function(event) {
event.preventDefault();
/* Act on the event */
var subject = $('#subject').val();
var grade = $('#grade').val();
var date = $('#date').val();
if (subject != "" && grade != "") {
$.ajax({
url:"/attendence/students",
method:"GET",
data:{"subject_id":subject, "grade_id":grade, "date":date},
dataType:"json",
success:function(data){
$("#result").html(data);
},
error:function(){
$("#result").html('There was an error please contact administrator');
}
});
}
});
Here is the controller the request is send to:
public function students(Request $request)
{
//
$grade = Grade::findOrFail($request->grade_id);
$subject = Subject::findOrFail($request->subject_id);
$students = Student::where('grade_id', $grade->id)->get(['id', 'first_name','middle_name', 'surname', 'grade_id']);
$statuses = Attendence::statuses();
// this check if attendence has been setup for the given date.
// if so prevent user for enter another date
$attendenceExists = Attendence::where([
'grade_id' => $grade->id,
'subject_id' => $subject->id,
'date' => $request->date
])->first();
if ($attendenceExists) {
return response()->json('A recorded attendence already exists for the seleced grade and subject!');
}
else {
return \View::make('attendence.partials.attendence-form')->with(array(
'students' => $students,
'subject' => $subject,
'date' => $request->date,
'statuses' => $statuses
));
}
}
Now, if this code returns true:
// this check if attendence has been setup for the given date.
// if so prevent user for enter another date
$attendenceExists = Attendence::where([
'grade_id' => $grade->id,
'subject_id' => $subject->id,
'date' => $request->date
])->first();
if ($attendenceExists) {
return response()->json('A recorded attendence already exists for the seleced grade and subject!');
}
The condition here runs and the right result is returned. But my else statement in the above does run but I don't get the right result. This is the result I get:
There was an error please contact administrator
Which shows that it is this part of the ajax request that is running:
error:function(){
$("#result").html('There was an error please contact administrator');
}
Surprisingly when I check the console this is what I see:
Which is exactly what I want but ajax is return otherwise. Am I doing something wrong?
Your dataType is set to json while you're returning html. Change it to html.
$.ajax({
url:"/attendence/students",
method:"GET",
data:{"subject_id":subject, "grade_id":grade, "date":date},
dataType:"json",
statusCode: {
200: function(data) {
$("#result").html(data.responseText);
};
}
}
});
Try this. I hope this will help you
I would say don't set the dataType at all. Just remove that setting altogether and let the jQuery ajax() method detect it automatically for you. That way, if the response type is JSON, it'll work. If the response type is HTML, it'll also work. 👍🏻

Why does validation not fail on client side but fails on server side?

Right now, I have a form with several fields and on submit, I want to check if the username is taken or not. If taken, do nothing (show validation error), if not taken, successfully proceed onto the next form.
Here's what I have done so far:
View:
var RequestCreateAccount_Submit = function () {
var res = false;
ValidationAttribute.BlankValue(true);
var form = $('form#RequestCreateAccount');
$.validator.unobtrusive.parse(form);
var res = form.valid();
var data = form.serialize();
if (res) {
$.ajax({
url: Url.getFullUrl('Account/RequestCreateAccount_Submit'),
type: 'Post',
data: data,
cache:false,
success: function (data) {
//Next Dialog
},
error: AjaxLog.HandleAjaxCallFail
});
}
return res;
}
Controller:
[AllowAnonymous]
[HttpPost]
public ActionResult RequestCreateAccount_Submit(UserAccount userAccount)
{
//Check if username is unique
if (!WebSecurity.UserExists(userAccount.UserName))
{
UserSession.AddValue(StateName.CreateOrEditAccount, "CurrentUserAccount", userAccount);
JsonResult res = Json(new { Success = true, data = "", Message = "" });
return res;
}
JsonResult jres = Json(new { Success = false, data = "", Message = "Username is already registered"});
return jres;
}
I tested it with a known username and it did hit the success=false (outside of the if statement) line and it did not go inside the if statment. So I know the validation on the server side works.
However, I am wondering why on the client side, it still success = true and the next dialog appeared. It did not fail on validation. What am I doing wrong on the client side?
The reason is that your controller does actually successfully return a result. It is just that the successful result indicates an error. While logically similar at this point, they are very different. Error is going to be reserved for actual exceptions thrown or 404 no route present type of scenarios.
You should check for the response status inside of your success callback function
dotNetFiddle Demo
$.ajax({
url: Url.getFullUrl('Account/RequestCreateAccount_Submit'),
type: 'Post',
data: data,
cache:false,
success: function (data) {
if(data.Success === false){
AjaxLog.HandleAjaxCallFail();
// this may not make as much sense though
// as the request didn't actually fail, just the action did
//TODO: code for name fail
return;//do not process next dialog
}
//Next Dialog
},
error: AjaxLog.HandleAjaxCallFail
});
The success = false of your result object doesn't means that the request failed. It stands only for data.success, nothing more. The resquest is still successful(HTTP 200), which I think is the right response code. If you return an error code like new HttpStatusCodeResult(404, "error message"); it means that your request failed, but it isn't true.
You request works whatever the result of the check is. So you may check this in your success callback, instead of the error callback:
success: function(data) {
if (data.success) {
//Next Dialog
}
else {
// error message
}
}

making ajax request in meteor helpers

How can i wait until the ajax request finishes when returning data to a meteor helpers method.
For example,
Template.item.helpers({
itemName:function () {
var user = Meteor.user();
$.when(reallyLongAjaxRequest()).done(function (a1) {
//tried using jquery when
return "Item Name should have this because it waited";
});
return " Doesnt wait at all";
}
});
I have a reallyLongAjaxRequest() running and i would like it to finish before continuing on with my itemName helper. The log statement to console always shows undefined but that's because the ajax request hasn't finished. I tried using the jquery when with no luck. Any ideas
Edit:
I should mention that i am inside the helper function for a reason. I need the item 'id' being rendered so that i can run the ajax request with that paramater. Using reactive sessions would be perfect but i don't know of a way to get currently rendering items outside of the helpers method definition?
An unnamed collection is one where null is passed for the name. It is an in-memory data structure, not saved to the database. (http://docs.meteor.com/#meteor_collection)
OK, given a Meteor collection called "items" and wanting to do an ajax request for each item based on the item _id, and then being able to reference the ajax result in a template, this is what I'd do:
(roughly)
var Items = new Meteor.Collection('items');
var Results = new Meteor.Collection(null);
Items.find().observeChanges({
added: function (id) {
$.get(url, {id: id}, function (data) {
if (Results.findOne(id))
Results.update(id, {$set: {result: data}});
else
Results.insert({_id: id, result: data});
});
}
});
Template.item.itemName = function (id) {
var doc = Results.findOne(id);
if (doc)
return doc.result;
else
return "";
};
inside your html you'll need to pass in the id to the helper:
{{itemName _id}}
Is there no way to just timeout for a few seconds when defining the helper so that my ajax request finishes without immediately returning.
No, with reactive programming things happen immediately, but you update when you have new stuff.
Make your ajax request separately, and when it completes, have it store the result in a Session variable. Then have your template helper return the value of the Session variable. Roughly...
$.get(url, function (data) {
Session.set('result', data);
});
Template.item.itemName = function () {
return Session.get('result');
};
Session is a reactive data source, so your template will automatically updated when the result of the ajax call comes in. (Naturally you can choose to call the Session variable anything you like, I just used "result" as an example).
This works and tested in MeteorJS > 1.3.x
Add the http package from the console meteor add http
Example POST call with data elements being sent to server and with custom headers.
HTTP.call('POST', tokenUri, {
data: {
"type": 'authorization_code',
//"client_id": clientId,
"code": code,
"redirect_uri" : redirectUri,
},
headers: {
"Access-Control-Allow-Origin" : "*",
"Access-Control-Allow-Credentials" : "true",
"Access-Control-Allow-Methods" : "GET,HEAD,OPTIONS,POST,PUT",
"Access-Control-Allow-Headers" : "Access-Control-Allow-Headers, Origin,Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers",
}
},function(error, response) {
if ( error ) {
console.log( error );
} else {
console.log( response );
}
});

Issues with handling http errors with jQuery AJAX webservice calls

I'm developing an jQuery application in where I've a requirement to capture HTTP errors as and when it occurs. Below is my snippet.
// Function to validate URL
function validateURL(url)
{
var pattern = new RegExp();
pattern.compile("^[A-Za-z]+://[A-Za-z0-9-_]+\\.[A-Za-z0-9-_%&\?\/.=]+$");
if (!pattern.test(url))
{
return false;
}
return true;
}
// Generic error handler for handling the webservice requests.
function initWebService(wstype, wsurl,jsonData)
{
// If the method parameter is not either "GET" or "POST" display an error message to the developer.
var msgValidateArgument;
var wsCallStatus;
var callbackData;
if ((arguments[0] != 'GET') && (arguments[0] != 'POST'))
{
//alert("Invalid");
//alert("You must provide a valid http method in your webservice call.");
msgValidateArgument = "You must provide a valid http method in your webservice call.";
return msgValidateArgument;
}
// Making sure whether the developer is passing the required number of parameters.
if(arguments.length < 3)
{
//alert("Some required arguments seems to be missing. Please check your webservice invocation.");
msgValidateArgument = "Some required arguments seems to be missing. Please check your webservice invocation.";
return msgValidateArgument;
}
if (!validateURL(arguments[1]))
{
msgValidateArgument = "You must provide a valid URL in your webservice call.";
return msgValidateArgument;
}
if(arguments[2] != ''){
var response=jQuery.parseJSON(arguments[2]);
if(typeof response =='object'){
//It is JSON
alert(response.toSource());
}
else{
msgValidateArgument = "The JSON data being passed is not in valid JSON format.";
return msgValidateArgument;
}
}
// Making the AJAX call with the parameters being passed. The error handler handles some of the possble http error codes as of now.
$.ajax({
type: arguments[0],
url: arguments[1],
data: arguments[2],
dataType: 'json',
async:false,
statusCode:{
404: function(){
alert('Page not found');
},
500: function(){
alert('Page not found');
},
504: function(){
alert('Unknown host');
}
},
success: function(data){
//alert('Data being returned from server: ' +data.toSource());
//alert('Data being returned from server: ' +data.toSource());
//alert(data);
callbackData = data;
}
});
return callbackData;
}
But, when I programatically change the webservice url to hold a wrong value, and upon calling the html page, I'm able to see an error message in the firebug console, but my snippet doesn't seem to be catching the error at all.
For e.g, While calling the GEONames API, I'm encountering an stating "407 Authorization required" in firebug's console.but even if I handle that status code in my error block, it is not firing.. What could be the reason?.
Don't we have any comprehensive solution for handling these HTTP errors effectively?.
I think there are a few problems with your code ... firstly how is handleError called ? because you call a method called handleError but pass nothing ... im assuming your using .ajax()
You should do it like this :
$.ajax({
statusCode: {
404: function() {
alert('page not found');
},
500: function() {
alert('server error');
}
},
success : {
alert('it working');
},
complete : {
alert('im complete');
});

Categories