I have an ajax post method to ad new records to a database, the process itself works ok and my server side code traps errors (duplicate input, etc). When an eror happens, the ajax method doesnt 'see' it, the 'success' function is always called. This is my ajax post method
$.ajax({
url: '#Url.Action("Add", "Organisation")',
data: $form.serialize(),
async: true,
type: 'POST',
error: function (returnval) {
$form.parents('.bootbox').modal('hide');
bootbox.alert('There was an error saving this organisation : ' + returnval['responseText']);
},
success: function (returnval) {
// Hide the dialog
$form.parents('.bootbox').modal('hide');
bootbox.alert('New Organisation successfully added');
}
})
and the actionmethod on my controller
[HttpPost]
[ValidateAntiForgeryToken]
public JsonResult Add(OrganisationEditCreateViewModel data)
{
InsertOrganisationRequest request = new InsertOrganisationRequest();
IEnumerable<ModelError> allErrors = ModelState.Values.SelectMany(v => v.Errors);
if (ModelState.IsValid)
{
var model = mapper.Map<OrganisationEditCreateViewModel, OrganisationDto>(data);
request.organisation = model;
var response = this._organisationService.InsertOrganisation(request);
if (response.isSuccess)
{
return Json(new { success = true, responseText = "New organisation added successfully" }, JsonRequestBehavior.AllowGet);
}
else
{
return Json(new { success = false, responseText = "Error adding new organisation : " + response.Message }, JsonRequestBehavior.AllowGet);
}
}
return Json(new { success = false, responseText = "Error adding new organisation : Invalid input" }, JsonRequestBehavior.AllowGet);
}
so when I insert a duplicate record, the serverside code traps this and this branch of code is returned back to my ajax call
return Json(new { success = false, responseText = "Error adding new organisation : " + response.Message }, JsonRequestBehavior.AllowGet);
but the ajax call always calls this bit of code
success: function (returnval) {
// Hide the dialog
$form.parents('.bootbox').modal('hide');
bootbox.alert('New Organisation successfully added');
}
the error part never gets called, what am I doing wrong ?
Update your success method!
success: function (returnval)
{
if(returnval.success=true)
{
// Hide the dialog
$form.parents('.bootbox').modal('hide');
bootbox.alert('New Organisation successfully added');
}
if(returnval.success=false)
{
$form.parents('.bootbox').modal('hide');
bootbox.alert('There was an error saving this organisation : ' + returnval['responseText']);
}
}
hope helps!
You are not doing anything wrong.Actually your code is also working fine,the
reason is Success function always getting executing because your AJAX call successfully happening.
If AJAX call failed then only error function will get execute.
Example suppose if you gave Ajax attribute contentType wrong
ex:- contentType:'xyzfds';
in some scenario or may be because of any another ajax method attribute wrong value.So no need to worry about it.
If you want to display your error message then follow below approach it may help you.Thank You
success: function (returnval) {
if(returnval!=null){
if(returnval.success){
// Hide the dialog
$form.parents('.bootbox').modal('hide');
bootbox.alert('New Organisation successfully added');
}
if(returnval.success==false){
$form.parents('.bootbox').modal('hide');
bootbox.alert('There was an error saving this organisation : ' + returnval['responseText']);
}
}
}
Related
I have just begun to work with ASP.NET Core MVC and web development in general, and I am struggling to understand how to show an error page from an AJAX call.
What I would like to do is to show a custom page with the error message on if the Ajax call fails. So far I have the following code which takes me to my 500 page when I throw an exception in the controller but how do I get it to show the exceptions message on that page?
StartUp.cs middleware:
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseStatusCodePagesWithReExecute("/Error/Error", "?Code={0}");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
Error controller:
public IActionResult Error(int? Code = null)
{
if (Code.HasValue)
{
if (Code.Value == 404 || Code.Value == 500)
{
var viewName = Code.ToString();
return View(viewName);
}
}
return View();
}
AJAX call:
// Use ajax call to post to the controller with the data
$.ajax({
type: "POST",
url: "/Renewals/GenerateQuotes",
data: { selectedContractIds: ids },
success: function (response) {
// Show success and refresh the page
Toast.fire({
icon: 'success',
title: 'Quotes Generated'
}).then(function () {
location.reload();
});
},
error: function (xhr, status, error) {
// Response message
var response = xhr.responseText;
window.location.href = '#Url.Action("Error", "Error")?Code=' + xhr.status;
}
})
I want to take both 'Blog Entry' and 'Blog Entry Photo' from controller with ajax. When taking only 'BlogEntry' there isnt any problem ,on the other hand, when taking both of them (BlogEntry and BlogEntryPhoto), there is a problem: "This request has been blocked because sensitive information could be disclosed to third party web sites when this is used in a GET request. To allow GET requests, set JsonRequestBehavior to AllowGet."
I think the problem is in 'Blog Entry Photo' because it has photopath column like "/Content/img/blog/25052017_2334_400x400.jpg".
I used JsonResult but it doesnt work
return Json(new { Success = true, BlogEntries = blogEntries, BlogEntryPhotos = blogEntryPhotos}, JsonRequestBehavior.AllowGet);
what should i do?
Finally, i eventually solved this issue arising from PhotoPath data. First, at controller, data of both BlogEntry and BlogEntryPhotos are serailized together then at view this data is parsed as object.
CONTROLLER
List<BlogEntry> blogEntries = _blogEntryRepo.GetAll(x => x.IsActive.Value && x.PlaceMarkerID == placeMarker.Id, null, "BlogEntryPhotoes").ToList();
JsonSerializerSettings jss = new JsonSerializerSettings { ReferenceLoopHandling = ReferenceLoopHandling.Ignore };
return Json(new { Success = true, BlogEntries = JsonConvert.SerializeObject(blogEntries, Formatting.Indented, jss) }, JsonRequestBehavior.AllowGet);
VIEW
$.ajax({
url: "/Map/GetBlogEntries",
type: "post",
datatype: "json",
data: placeMarker,
success: function (response) {
if (response.Success) {
var BlogEntries = JSON.parse( response.BlogEntries );
//BlogEntries[i].Title can be used
//BlogEntries[i].BlogEntryPhotoes[0].PhotoPath can be used
}
else {
//do something
}
},
error: function (xhr, status) {
//do something
}
});
From client side, I wanna send some data to server and receive some <div> tags which responding from View (another controller).
My ajax code looks like this:
var sortTopic = function () {
var $list = [],
$address = '',
$formData = new FormData();
/* do something here to set value to $list and $address */
$formData.append('Category', $list);
$formData.append('Address', $address);
$formData.append('Tags', '[KM]');
$formData.append('Skip', 0);
$.ajax({
url: '/Topic/Sort',
type: 'POST',
data: $formData,
dataType: 'json',
contentType: false,
processData: false,
success: function (data) {
if (!data.success) {
$('.jumbotron').html(data.ex);
} else {
$('.jumbotron').html(data);
}
},
error: function (xhr) {
alert(xhr.status); //xhr.status: 200
}
});
};
In TopicController, action Sort was:
[AllowAnonymous]
[HttpPost]
public ActionResult Sort(SortTopicViewModel model)
{
try
{
if (model.IsValidSortTopicModel())
{
return PartialView("../Home/_Timeline", new TopicMaster().Sort(model));
}
return Json(new { success = false, ex = "Invalid model." });
}
catch (Exception e) { return Json(new { success = false, ex = e.Message }); }
}
I'm sure that the model is valid and method new TopicMaster().Sort(model) was working fine (because I had put breakpoint to view the return data). And the partial view _Timeline is a partial view of HomeController.
My problem is: I don't understand why I get error with status code 200 in ajax:
error: function (xhr) {
alert(xhr.status); //xhr.status: 200
}
Can you explain to me?
Thank you!
as you told you receive <div> in response that is not json and you mention dataType:"json" in your ajax just remove it. this will solve your problem. error 200 occur when you did not get valid response which is you mention in ajax.
for mor information you can read it documentation
I'm trying to redirect to an Error page inside onexception method when an exception occurs. But the thing is I have Ajax function, so even if I redirect inside onexception class, it does not redirect to error page and it always end up with executing Ajax function. Please can anyone suggest a solution for this.
This is my controller method and when exception throws, it will call to base controller on exception method.
public ActionResult DeleteConfirmed(int id)
{
try
{
string displayMessage = string.Empty;
//Delete ward details and check successfulness of the function and return json result
if (wardManager.DeleteWard(id) == true)
{
displayMessage = CustomEnumMessage.GetStringValue(ConfirmationMessages.ConfirmationErrorMsg);
return Json(new { Message = displayMessage });
}
//Return json result if unsuccessfull
else
{
displayMessage = CustomEnumMessage.GetStringValue(ConfirmationMessages.ConfirmationRemovedMsg);
return Json(new { Message = displayMessage });
}
}
catch (System.Exception ex)
{
throw ex;
}
}
This is my base controller onexception method
protected override void OnException(ExceptionContext filterContext)
{
//Get exception type
System.Type ExceptionType = filterContext.Exception.GetType();
if (ExceptionType.Name == "DbUpdateException")
{
ViewData["ErrorMessage"] = filterContext.Exception.InnerException.Message;
this.View("DatabaseException", filterContext.Exception).ExecuteResult(this.ControllerContext);
}
else
{
ViewData["ErrorMessage"] = filterContext.Exception.Message;
this.View("ApplicationException", filterContext.Exception).ExecuteResult(this.ControllerContext);
}
}
This is my Ajax function
$.ajax({
type: "POST",
dataType: "json",
jsonpCallback: "onJSONPLoad",
url: '#Url.Action("Delete")',
data: $('#form').serialize(),
success: function (data) {
$('#submit').hide();
TriggerMsg(data.Message);
},
error: function (xhr) {
if (xhr.getResponseHeader('Content-Type').indexOf('application/json') > -1) {
var json = $.parseJSON(xhr.responseText);
alert(json.errorMessage);
}
}
});
I built this Ajax function for only displaying Successful messages and it avoids me to redirecting to error page. The problem is even if i redirect to error page inside onexception method, finally fire into Ajax error: function and it does not redirect into DatabaseException or ApplicationException views. Can anyone suggest a solution for this issue.
Thanks
Your problem is that when you do a post from an ajax function, whatever result you have in your controller will always end up coming back to the success function.
What you want to do is return a url to your ajax function and from there redirect the user.
In your controller return the following
result = Json(new { redirect = Url.Action("ActionName", "ControllerName", new { area = "" }) });
Then in your javascript you will look for this redirect variable and set the window.location to it
success: function (data) {
if (data.redirect) {
window.location.href = data.redirect;
}
},
If you also want to pass a message then you can probably put it in the session such as Session["ErrorMessage"] = error from the controller and use it the same way in your error view
What I am trying to achieve it to show messages on a dialog form as asked and answered here. However, while the example above used the default editGridRow in the code, I have a custom dialog form loaded in via JSON. For example the JSON error/validation message returned could be:
{"CustomerName":{"isEmpty":"\u201cthis value is - not to be left empty.\u201d"}}
I need to be able to output them as "Customer Name - this value is not to be left empty" - at the top of the dialog form.
I have tried the solutions in A, B, C and D but I have not been able to customize them to work in my scenario yet.
I have a function call like so:
function LaunchEditForm(dialog)
{
$('form', dialog).submit(function ()
{
$.ajax({
url: '/customer/update-customer/',
type: this.method,
reloadAfterSubmit: true,
data: $(this).serialize(),
success: function (result)
{
if (result.success)
{
console.log(result);
//can I call a function here to prepend modal form
//with success message? how please?
}
else
{
console.log(result);
// can I prepend the dialog to show model errors here?
//var errorDetail = jQuery.parseJSON(result.responseText);
}
}
});
return false;
});
}
I have tried using afterSubmit like so:
afterSubmit: function (response, postdata)
{
if (response.responseText == "Success")
{
jQuery("#success").show();
jQuery("#success").html("Customer successfully updated");
jQuery("#success").fadeOut(6000);
return [true, response.responseText]
}
else
{
return [false, response.responseText]
}
}
This has not worked yet - perhaps I have placed it in a different scope
and also tried errorTextFormat like so:
errorTextFormat: function (data)
{
if (data.responseText.substr(0, 6) == "<html ")
{
return jQuery(data.responseText).html();
}
else
{
return "Status: '" + data.statusText + "'. Error code: " + data.status;
}
}
Please help with this. I know I need some function that parses the JSON successfully and hopefully presents the errors and messages Oleg described