I am using angularJS and spring 3.2.4 for REST exception handling and handling exception like this
#ExceptionHandler(MethodArgumentNotValidException.class)
#ResponseStatus(value=HttpStatus.BAD_REQUEST)
#ResponseBody
public ErrorFormInfo handleMethodArgumentNotValid(HttpServletRequest req, MethodArgumentNotValidException ex, HttpServletResponse response) {
String errorMessage = "gender sring is out of range";
String errorURL = req.getRequestURL().toString();
System.out.println("Throwing exception from exception handler");
ErrorFormInfo errorInfo = new ErrorFormInfo(errorURL, errorMessage);
return errorInfo;
}
whenever sent argument validation fails it throws a MethodArgumentNotValidException and correct me if i am wrong that spring 3.2 converts the objects in json format automatically
but i am not able to get the object in error block of angularJs. It throws the error saying "Response is undefined" with this output
completeRequest(callback=done(status, response, headersString), status=400, response="{"errorMessage":"http:/...sring is out of range"}", headersString="Server: Apache-Coyote/1...MT\r\nConnection: close\r\n")angular-1.0.7.js (line 9333)
onreadystatechange()
I suspect that object is not being converted into JSON because is has strange header string.
Below is my JS code
$http.post('rest/create?cd=' + (new Date()).getTime(),
XYZ
.success(function(data) {
alert('Data added successfully');
}).error(function(data) {
var errorInfo = data;
alert("data from server side"+errorInfo.errorMessage);
alert("Unable to process");
});
Please help...Thanks in advance
There was an interceptor injected in $httpProvider service of angularJs which run only for success and error. so I wrote a the piece of code in promise to handle response 'undefined'
case. Code is as follows:
if(jsonStr.ERROR_URI != 'undefined')
{
var jsonStr = response.data;
console.log('inside error block');
console.log('response.status'+response.status);
console.log('response.data'+response.data);
console.log('response.data.ERROR_URI'+jsonStr.ERROR_URI);
return $q.reject(response);
}
it simply rejects the response if it is undefined. It solved my problem.
Related
I have a function that triggers on a button click that passes the following argument: insertSongPlay(newSong.songID); when I console.log the newSong.songID I see a value of 90, which is desired.
This function is called here which runs an ajax call:
function insertSongPlay(songID)
{
$.ajax
({
type: "POST",
contentType: "application/json; charset=utf-8",
dataType: "json",
url: "/Album/InsertSongPlay/",
data: JSON.stringify({ "songID": songID }),
success: function(data)
{
console.log("submitted");
console.log(songID);
//TODO: Indicate Success
},
error: function(jqXHR, textStatus, errorThrown)
{
//TODO: Indicate Error
console.log(errorThrown);
}
});
}
Here is the corresponding ajax url found in my AlbumController:
public JsonResult InsertSongPlay(int songID)
{
try
{
EntityDataAccess.InsertSongPlay(songID);
return Json(true);
}
catch(Exception ex)
{
return Json(ex);
}
}
Then in my EntityDataAccess.cs the following is run from the InsertSongPlay entity data access:
public static SongPlayDaily InsertSongPlay(int songID)
{
using(var Context = GetContext())
{
var currentSongPlay = Context.SongPlayDailies.FirstOrDefault(x => x.SongID == songID && x.PlayDate == DateTime.Now.Date);
if (currentSongPlay != null)
currentSongPlay.NumberOfPlays++;
else
{
currentSongPlay = new SongPlayDaily();
currentSongPlay.SongID = songID;
currentSongPlay.PlayDate = DateTime.Now.Date;
currentSongPlay.NumberOfPlays = 1;
Context.SongPlayDailies.Add(currentSongPlay);
}
Context.SaveChanges();
return currentSongPlay;
}
}
However, my ajax call always throws an error and prints Internal Server Error to the console log. The Visual Studio debug mode indicates some sort of circular reference error. I'm not quite sure where I'm going wrong.
Thanks!
As we figured out in comments - there are multiple problems here. First,
return Json(ex);
Is a bad idea. That will inspect all properties of exception and try to serialize them, and all properties of those properties, to json. As you see, that is not going well, and also completely unnecessary. If you want to return error response to client - prepare it (use ex.Message for example). Plus, you don't want to return sensetive information (like stack trace) to your clients on every error.
Besides that - by doing return Json() on exception - you violate HTTP conventions. Json() will return response with status code 200 OK. But in your case it's not really "ok" - so you should return another status code indicating error. If not that circular reference error - your code in ajax "error" handler would never has been triggered, even when there was really an error.
Easiest way to fix it is just remove try-catch completely and let framework handle that for you.
Second problem is
x.PlayDate == DateTime.Now.Date
filter in query. Entity Framework has problem with accessing Date property of DateTime objects and refuses to convert that into SQL query. You can either move that to another variable:
var today = DateTime.Now.Date;
Where(x => x.PlayDate == today)
or use DbFunctions.TruncateTime:
Where(x => x.PlayDate == DbFunctions.TruncateTime(DateTime.Now))
Note that those ways are not exactly equivalent. First will compare with exact date value, and second will use SQL SYSDATETIME() function. In this case that hardly matters though.
Is it because you're missing the [HttpPost] attribute over your controller action?
[HttpPost]
public JsonResult InsertSongPlay(int songID)
{
try
{
EntityDataAccess.InsertSongPlay(songID);
return Json(true);
}
catch(Exception ex)
{
return Json(ex);
}
}
in post action you should use complex type for receive data from client.
try this
[HttpPost]
public JsonResult InsertSongPlay(SongModel songModel)
{
try
{
EntityDataAccess.InsertSongPlay(songModel.songID);
return Json(true);
}
catch(Exception ex)
{
return Json(ex);
}
}
public class SongModel{
public int songID {get;set}
}
In my asp.net mvc application, I would like to show the user the error message that was used to throw an exception. The exception occurs in an ajax request. I have tried this:
In Global.asax.cs file, I have global application error handler:
protected void Application_Error(object sender, EventArgs e)
{
Exception exception = System.Web.HttpContext.Current.Server.GetLastError();
// do something so that client side gets the value exception.Message
// I have tried these, but no success
HttpContext.Current.Response.StatusDescription = exception.Message;
HttpContext.Current.Response.StatusCode = 1000; // custom status code
}
In javascript, I have global ajaxError handler:
$(document).ajaxError(function (xhr, props) {
// show the message in the exception thrown on the server side
});
I tried to get the exception message in JavaScript using props.statusText, props.responseText, but none of them had the exception message.
My question: What can I do in the Application_Error method so that I can get the message contained in exception.Message to the global ajaxError function on the client side? Please note that I can easily handle exception that occurs in any specific Action where an ajax request hits, but I would like to make a global exception handler, that will allow me to just throw an exception with a message from any part of my application, and the exception message gets shown to the user on the client side.
I have tried this, but this doesn't solve my problem, because I want to use jQuery global ajaxError, instead of handling error in just a specific ajax request. Can this be modified to achieve what I want?
You can create a basecontroller and override the OnException method
public class BaseController : Controller
{
protected override void OnException(ExceptionContext filterContext)
{
//your existing code to log errors here
filterContext.ExceptionHandled = true;
if (filterContext.HttpContext.Request.Headers["X-Requested-With"]
== "XMLHttpRequest")
{
filterContext.Result = new JsonResult
{
JsonRequestBehavior = JsonRequestBehavior.AllowGet,
Data = new
{
Error = true,
Message = filterContext.Exception.Message
}
};
filterContext.HttpContext.Response.StatusCode = 500;
filterContext.ExceptionHandled = true;
}
else
{
filterContext.Result = new RedirectToRouteResult(new RouteValueDictionary
{{"controller", "Error"}, {"action", "Index"}});
}
}
}
and have all your controllers inherit from this
public class HomeController : BaseController
{
}
So any time an exception happens in your controllers, this OnException method will be executed and if it is an ajax request, It returns a json response with the below structure
{
Error : true,
Message : "The message from the exception caught"
}
and now in your javascript, wire up the global ajaxError event and you can read the response coming from server and parse it to a js object and then read the Message property
$(document).ready(function() {
$(document).ajaxError(function (event, request, settings) {
var d = JSON.parse(request.responseText);
alert("Ajax error:"+d.Message);
});
});
I want to pass error message to Blueimp jQuery File Upload plugin. I use ASP.NET MVC and throw my own exception when some conditions are appeared (i.e. file is not real image, only image exception or image is too wide etc).
var file = Request.Files[i];
_service.ImageValidation(file.InputStream);
public void ImageValidation(System.IO.Stream fileStream)
{
Bitmap bmp = null;
try
{
bmp = new Bitmap(fileStream, false);
}
catch
{
throw new NoImageException();
}
if (bmp.Width > bmp.Height && (bmp.Width < 1024 || bmp.Height < 768))
throw new ImageDimensionTooSmall();
if ((bmp.Width <= bmp.Height) && (bmp.Width < 768 || bmp.Height < 1024))
throw new ImageDimensionTooSmall();
fileStream.Position = 0;
}
on client side I try to catch error by the following way:
$('#fileupload').fileupload({
url: '/SmartphonePhotographer/ManageFiles?ResponseID=' + ResponseID,
error: function (e, data) {
alert('error');
}
});
'data' variable always has 'error' value. 'e' has many properties, including statusText='Internal server error' and responseText (html page with exception). Question - how can I pass error message on server side to catch it on client side (maybe, there is an json format for errors, but I did not find it in documentation)
It goes to the error event because you are throwing an exception in your server side code. So the ajax call is getting a 500 internal error response.
What you can do is, instead of throwing an exception, return a json response with the error messages.
[HttpPost]
public ActionResult SaveImage()
{
if(IsFileNotValid()) //your method to validate the file
{
var customErrors = new List<string> {"File format is not good",
"File size is too bib"};
return Json(new { Status = "error", Errors = customErrors });
}
//Save/Process the image
return Json ( new { Status="success", Message="Uploaded successfully" });
}
And in the done() event, you can inspect the json response and show the error messages as needed.
$('#fileupload').fileupload({
url: '/SmartphonePhotographer/ManageFiles?ResponseID=' + ResponseID,
error: function (e, data,txt) {
alert('error' + txt);
}
}).done(function(response){
if(response.Status==="error")
{
$.each(services.Errors, function (a, b) {
alert(b);
});
}
});
With this approach, you can send multiple validation errors back to the client and client can process(show to user ?) it.
MVC 6
In MVC6, you can return an HttpStatusCode response directly from the MVC controller action. So no need to send a JSON response yourself.
[HttpPost]
public IActionResult SaveImage()
{
var customErrors = new List<string> { "File format is not good",
"File size is too bib" };
return HttpBadRequest(customErrors);
}
This will send a 400 Response to the caller with the data we passed(the list of errors) in the response. So you can access the responseJSON property of your error xHr object of the error event to get it
error: function (a, b, c) {
$.each(a.responseJSON, function (a, b) {
alert(b);
});
}
I agree your issue is that you are throwing an exception versus returning a controlled response. Most frameworks look for status codes in the 400x or 500x. So you want to return a friendly json object and a status code in those ranges. If you do that your data object in the error block will be what you returned.
MVC Land:
//get a reference to request and use the below.
return this.Request.CreateResponse(HttpStatusCode.BadRequest, "Your message here");
Web Api 2
Use an IHttpActionResult and return BadRequest("My error message"); If you do that it will set your status code and return the response as the data.
I am making an ajax call to the controller. The controller will return a string if the execution is successful or it will return a partial view if an error is found. I am forcing it to fail, but it still goes into the success event in the ajax.
How do I go about getting it to display the partial view when failed OR just alert the string value when successful?
Ajax call:
$.ajax({
url: '#Url.Action("GetItem","Home")',
data: { },
success: function (result) {
alert(result);
},
error: function (result) {
$(".MyDiv").html(result);
}
})
Controller:
public ActionResult GetItem([DataSourceRequest]DataSourceRequest request)
{
try
{
throw new Exception("ERROR");
//return Json("Success", JsonRequestBehavior.AllowGet);
}
catch (Exception ex)
{
AlertMessage alertMessage = new AlertMessage();
alertMessage.MessageText = "A critical error has occurred, please contact your administrator.";
alertMessage.ErrorMessageText = ex.ToString();
alertMessage.MessageHeading = "Critical Error";
return PartialView("~/Views/Common/ErrorMessageDisplay.cshtml", alertMessage);
}
}
Function you've provided as error argument of ajax call will be called if the request fails. This means response status code is one of 40* or 50* codes.
But when you're returning PartialView from your controller, actually response has status code 200 that is "OK" - that's why success function is being called.
You can modify your controller code by adding Response.StatusCode = 500; just before return PartialView(..., and this should do the trick.
I have an issue with my login request.
I get this error :
[object Object]
parsererror
SyntaxError: JSON Parse error: Unexpected EOF
The request is sent correctly (according to the network console) but when I'm receiving the response I get this error but I can't visualise the JSON object.
I'm using JavaScript, Ajax, jQuery and for the server side I'm using servlets in Java.
Here is my code
function connect(login, password){
$.ajax({
type : "GET",
url :"http://adress/log",
data : "login=" + login + "&pwd=" + password,
dataType : "json",
success : traiteReponseConnexion,
error : function(XHR, testStatus, errorThrown) {
console.log("echec");
alert(XHR + "\n" + testStatus + "\n" + errorThrown);}
});
}
function traiteReponseConnexion(el){
if(el.error != undefined){
console.log("ici" +el.id);
}else{
alert("I'm here");
window.location.href="main.jsp?id="+el.id+"&login="+el.login+"&key="+el.key+"";
}
}
In my servlet
public void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException{
Map<String,String[]> pars = req.getParameterMap();
if(pars.containsKey("log") && pars.containsKey("pwd")){
String log = req.getParameter("log");
String pwd = req.getParameter("pwd");
resp.addHeader("Access-Control-Allow-Origin", "*");
resp.setContentType("application/json");
JSONObject user = UserLogin.authentifiateUser(log, pwd);
resp.getWriter().println(user);
}
}
I don't understand where is the problem. I have no response from the server in
the network console but in others services I don't seem to have this problem (logout for instance).
You may need to send more than just Access-Control-Allow-Origin; you may well need Access-Control-Allow-Methods and/or Access-Control-Allow-Headers as well, if a preflight is happening. If so, I believe you'll need to handle those in doOptions (not doGet).