MVC Rethrow custom exception as JSON - c#

I am calling a web service from my MVC view and wanting to use the jquery ajax error functionality on exception throw.
I am trying to throw a custom created exception from my MVC business layer into my presentation layer controller and rethrow it as a json response.
I can successfully throw my custom exception, the issue is it comes as a HTML view. I have seen ways to declare a custom error response, but I was hoping to be able to directly rethrow the exception as JSON.
Any ideas?
Javascript:
$.ajax({
type: "POST",
url: 'create',
data: "{userDetails:" + JSON.stringify(details) + "}",
contentType: "application/json; charset=utf-8",
success: function (data) {
data = data.d;
redirectSuccess();
},
error: function(err) {
//display thrown exception here
}
});
CS
public JsonResult create(MyModel.New details)
{
try
{
Library.insert(details);
return Json(true);
}
catch (Exception ex)
{
throw;
}
}
Thanks in advance for any help!

I ended up working out a solution appropriate.
For anyone wanting a similar answer to the question I asked, what i did was declare a custom filter. The main parts of this is setting the filter result to return as JSON, but even then it would return as success in the jquery ajax call because it returned a status of 200 which jquery ajax reads as success.
Jquery ajax reads any status outside of 200 as an error so as you can see I changed the status code to a custom number that i created and will document and therefore the jquery ajax sees an error and throws it to ajax error.
public class MyErrorHandlerAttribute : FilterAttribute, IExceptionFilter
{
public void OnException(ExceptionContext filterContext)
{
filterContext.HttpContext.Response.StatusCode = 11001;
filterContext.ExceptionHandled = true;
filterContext.Result = new JsonResult
{
Data = new { success = false, error = filterContext.Exception.ToString() },
JsonRequestBehavior = JsonRequestBehavior.AllowGet
};
}
}
To reference the current filter, you just add the error handler attribute to the function as shown in the first line below:
[MyErrorHandler]
public JsonResult create(MyModel.New details)
{
try
{
Library.insert(details);
return Json(true);
}
catch (Exception ex)
{
return Json(ex.Message);
}
}

I don't think it works the way you think it does you need to pass exception to frontend as responce.
public JsonResult create(MyModel.New details)
{
try
{
Library.insert(details);
return Json(true);
}
catch (Exception ex)
{
return Json(ex.Message);
}
}
And then handle it with JS as success.
$.ajax({
type: "POST",
url: 'create',
data: "{userDetails:" + JSON.stringify(details) + "}",
contentType: "application/json; charset=utf-8",
success: function (data) {
if (data.Message)
{
//display error
}else{
data = data.d;
redirectSuccess();}
},
error: function(err) {
//display thrown exception here
}
});

Related

A circular reference was detected while serializing an object of type 'System.Data.Entity.DynamicProxies.Item

I am trying to do a simple JSON return but I am having issues I have the following below.
[HttpGet]
public JsonResult GetItemsEdit()
{
try
{
var data = _unitOfWork.Items.GetItems();
return Json(new
{
data
}, JsonRequestBehavior.AllowGet);
}
catch (Exception ex)
{
Response.StatusCode = (int)HttpStatusCode.BadRequest;
return Json(ex.Message);
}
}
and this is my ajax call code:
// Gets Items on Dropdown
$.ajax({
type: "GET",
url: "/Payments/GetItemsEdit",
datatype: "application/json",
success: function (data) {
debugger
alert("ok");
$.each(data, function (index, value) {
$('#Item').append('<option value="' + value.Id + '">' + value.itemName + '</option>');
});
},
error: function (err) {
console.log("AJAX error in request: " + JSON.stringify(err, null, 2));
}
});
I get a HTTP 500 with the exception as shown in the title of this question.
Is this a bug or my implementation?
No, it's not a bug and actually the problem isn't your implementation. The problem is the structure of the returned model.
You can either convert your model into a different model without the references by hand, eg.
var data = _unitOfWork.Items.GetItems().Select(x => new { ... });
or depending on the json serializer you use you could turn on ignoring circular references.
sample for Newtonsoft.json
services
.AddMvc()
.AddJsonOptions(jsonOptions => { jsonOptions.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore; } );
Some more insight for the System.Text.Json library.

How to show alert, popup or message if file is not created in MVC?

I have a action method:
public ActionResult Export(int? protocol, int? visitno)
{
SetViewBagItems();
if(protocl.hasValue)
{
// code create file
if (!string.IsNullOrEmpty(csvData))
{
return File(new System.Text.UTF8Encoding().GetBytes(csvData), "text/csv", "Report.csv");
}
else
{
// need to show something in ui like, not able to create file, or any popup or any alert....
}
}
return view();
}
So in the code as mentioned, I need to show something like an alert or message when able to create the file.
Now the behavior is:
if file gets created, it will get directly downloaded and wont reload the page.
if no file is created, then the entire page will refresh.
I need to show some message instead of that.
Same controller method is used for the page to load for the first time.
How can I achieve this?
Using $.ajax() to call that function in controller. Likes:
$.ajax({
url: "/controller/action",
type: "GET",
data: {protocol: protocol, visitno: visitno},
success: function(e) {
if(e != null)
{
//Alert
}
else {
//Alert
}
}
})
You can return a JSON result from your action method as:
return Json(new {
success = true,
status = "Failure"
}, JsonRequestBehavior.AllowGet);
The ajax method from where the action method is called, check for the return status and show the error or success message in the dialog box or through alert:
$.ajax({
type: "POST",
url: "/Controller/Action",
data: { "ID": $('#id').val() },
success: function (data) {
if (data.status == "Failure")
{
$('#dialog-Add-Success').dialog({
modal: true,
opacity: 1,
buttons: {
Ok: function () {
$(this).dialog('close');
}
},
})
}

.NET (ApiController) / jQuery .ajax : what to return from POST?

In a Post method within a Controller derived from ApiController what should I return to indicate success to jQuery ?
I've tried HttpResponseMessage but jQuery sees this as an error (even though the argument the jQuery error handler clearly has a 200 status).
The jQuery looks like this :
processParticipantEvent: function(parID, evtType, evtNotes, successFunction, errorFunction){
debugger;
var requestURL = '/api/participantevent';
var json = {"parId" : parID, "evtType": evtType, "evtNotes": evtNotes};
var jsonArray=JSON.stringify(json);
$.ajax({
type: "POST",
contentType: "application/json; charset=utf-8",
url: requestURL,
data: jsonArray ,
dataType: "json",
success: function (data) { successFunction(data); },
error: function (data) { errorFunction(data); }
});
},
I've read this : Ajax request returns 200 OK, but an error event is fired instead of success which seems like it's touching on the same issue but I suspect it's out of data as it won't work for me ?
Just to be clear all I want to do is to return a plain old 2xx with no data.
As per the documentation:
"json": Evaluates the response as JSON and returns a JavaScript
object. Cross-domain "json" requests are converted to "jsonp" unless
the request includes jsonp: false in its request options. The JSON
data is parsed in a strict manner; any malformed JSON is rejected and
a parse error is thrown. As of jQuery 1.9, an empty response is also
rejected; the server should return a response of null or {} instead.
So if you want to use jQuery ajax you have to return a valid json string, just use the following in your API controller:
return Ok(new {});
Note this is a jQuery ajax "feature", using Angular for example to do an ajax post I can use return Ok(); inside my controller and everything works as expected.
As mentioned by #Beyers the return with OK() just works.
I've created the same structure here and worked.
My Controller has this:
[Route("api/participantevent")]
public IHttpActionResult Test()
{
return Ok("");
}
And at client I've changed your function just to simplify:
processParticipantEvent= function(){
debugger;
var requestURL = '/api/participantevent';
$.ajax({
type: "POST",
contentType: "application/json; charset=utf-8",
url: requestURL,
data: [{'test': '1'}] ,
dataType: "json",
success: function (data) { alert('success'); },
error: function (data) { alert('error'); }
});
}
Your error is with the requestURL. Its value is absolute and http://api/participantevent does not exist. Try using a relative value.
var requestURL = './api/participantevent';
It seems that if you get an OK response, It is probably not a valid JSON.
I would recommend to you to check the HTTP response in the browser and try to run the JSON.parse function with the responseText and see whether it fails.
I usually declare a class like below:
public class AjaxResult
{
private bool success = true;
private List<string> messages;
public bool Success { get { return success; } set { success = value; } }
public List<string> Messages { get { return messages; } }
public AjaxResult()
{
messages = new List<string>();
}
}
In the controller, the action(to which the ajax request is made) should have JsonResult as return type.
[HttpPost]
public JsonResult Action(string id)
{
AjaxResult result = new AjaxResult();
//Set the properties of result here...
result.Success = true;
result.messages.Add("Success");
return Json(result);
}
3.And your ajax call will look like this:
$.ajax({
type: "POST",
dataType: 'json',
url: /ControllerName/Action,
data: { id: "Test"},
success: function (data) { alert('success'); },
error: function (data) { alert('error'); }
});

jquery Ajax error function is not triggered

Below is my function (1st Code piece), when I run below function, it goes into to my code through my handler and in my code it throws exception (2nd Code piece), after exception is catched, it goes back to my handler and get's inside the catch area, and finally turns back to javascript success function, but error it doesn't run the error part.
BenefitOperations.performBenefitOperation = function(data) {
$.ajax({
type: "POST",
url: "BenefitOperation.axd",
data: JSON.stringify(data.BenefitOperationJson),
dataType: "json",
contentType: "application/json; charset=utf-8",
beforeSend: function() { PageMask.show(); },
success: function(response) {
if (response.Success == true)
performPostBack();
else
window.alert(Res.BenefitOperationFailure);
},
error: function(e, x, y) { window.alert(Res.BenefitOperationError + y); } }); }
This is my function
else
{
throw new ApplicationException(string.Format("Benefit operation type {0} for benefit type {1} is not registered", Enum.GetName(typeof(EmployeeBenefitData.BenefitOperationType), parameters.OperationTypeID), Enum.GetName(typeof(EmployeeBenefitData.BenefitTypeEnum), parameters.BenefitTypeID)));
}
this is my handler's catch
catch
{
jsonOutput = JsonConvert.SerializeObject(new
{
Success = false
});
}
finally
{
context.Response.Clear();
context.Response.ContentEncoding = Encoding.UTF8;
context.Response.ContentType = "application/json";
context.Response.Write(jsonOutput);
}
The error callback of $.ajax() doesn't get called in your code because there is no error. error means there was an issue retrieving the response, eg. a 500 error from the server.
In your code you're catching the ApplicationException yourself and returning JSON. If you'd prefer to use the error handler, raise the exception and don't catch it in your C# code - however it should be noted your current code is a better method.
Rory is right,
just set HTTP 500 status code when you hit error / Exception or operation faild.
you can set HTTP 500 status code like...
context.Response.StatusCode = 200;

Success Message in Ajax Jquery

I am developing an app in asp.net in which I have jquery code in my asp page
var strdata = {
problemID: $("#problemID").val(),
commentText: $("#_1").val(),
empID: $("#empID").val(),
agree: 0,
disagree: 0
};
$.ajax({
type: "POST",
url: "<%= Url.Action("PostComment", "Discussion") %>",
data: strdata,
dataType: "JSON",
success: function (msg) {
if ( msg == 1)
alert("Success" + msg );
}
});
and my controller has code
public bool PostComment(string problemID, string commentText, string empID, string agree, string disagree)
{
return _discussionRepository.postComment(Convert.ToInt32(problemID), commentText, Convert.ToInt32(empID), Convert.ToInt32(agree),Convert.ToInt32( disagree));
}
and model has code
public bool postComment(int problemID, string commentText, int empID, int agree, int disagree)
{
bool result = false;
Comment c = new Comment();
c.ProblemID = problemID;
c.CommentText = commentText;
c.EmpID = empID;
c.Agree = agree;
c.DisAgree = disagree;
_objectModel.Comments.InsertOnSubmit(c);
try
{
_objectModel.SubmitChanges();
result = true;
}
catch (Exception ex)
{
}
return result;
}
Data is saving in database through ajax and jquery but the success message is not showing
If the alert is not running with or without the condition that means the datatype being returned is not the datatype the $.ajax function is expecting.
2 ways to get to the bottom of it:
First open up chrome or firebug and check out the network traffic. If you are getting the result back (the request is being made and the content looks accurate) then your data type is definitely the cause. Try changing the datatype in the request.
Next you could try adding functions other than just success. There is also error, status codes (404,500 etc), beforeSend, etc check the docs.
There are other ways as well :). Fiddler might help too.
To get the result of your AJAX request use the following code in your success handler:
success: function (msg) {
if ( msg.d === true) {
alert("Success" + msg.d );
}
}
You have to access the result via the "d" property.
To get the error message use the following error handler:
error: function(jqXHR, textStatus, errorThrown){
alert(errorThrown);
}
i think the result returned in 'msg' isnt the number 1. maybe msg == true ?

Categories