I have a controller with the following catch statement which returns a partial view and the error to display.
catch (Exception ex)
{
return PartialView("ErrorPartial", new ErrorModel(ex));
}
This controller is being invoked through an Ajax call like this...
$('#myID').ajaxSubmit({
url: buildUrl('MyController'),
beforeSubmit: function () {
toggleOverlay(true, 'Saving...');
},
success: function (responseText, statusText, xhr) {
successSave(responseText, statusText, xhr)
},
error: function (jqXHR, textStatus, errorThrown) {
}
});
If the exception is caught, then the code falls into the error block however I'm unable to pass the partial view data into this.
Is there anyway I can pass the partial data into the error block? If not, could you possibly recommend an alternative?
Thanks :)
You're probably looking for jqXHR.responseText. However, it's not very clear for me why does your js code fail into the error block - you've handled the exception so ajax request should be considered as successfull and success function should be triggered. Here's my C# code which leads to ajax request fail but passes the data along with the error.
Response.StatusCode = (int)System.Net.HttpStatusCode.BadRequest;
return PartialView("SomePartialView", model);
Related
I am trying to pass messages between content script and the extension
Here is what I have in content-script
chrome.runtime.sendMessage({type: "getUrls"}, function(response) {
console.log(response)
});
And in the background script I have
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
if (request.type == "getUrls"){
getUrls(request, sender, sendResponse)
}
});
function getUrls(request, sender, sendResponse){
var resp = sendResponse;
$.ajax({
url: "http://localhost:3000/urls",
method: 'GET',
success: function(d){
resp({urls: d})
}
});
}
Now if I send the response before the ajax call in the getUrls function, the response is sent successfully, but in the success method of the ajax call when I send the response it doesn't send it, when I go into debugging I can see that the port is null inside the code for sendResponse function.
From the documentation for chrome.runtime.onMessage.addListener:
This function becomes invalid when the event listener returns, unless you return true from the event listener to indicate you wish to send a response asynchronously (this will keep the message channel open to the other end until sendResponse is called).
So you just need to add return true; after the call to getUrls to indicate that you'll call the response function asynchronously.
The accepted answer is correct, I just wanted to add sample code that simplifies this.
The problem is that the API (in my view) is not well designed because it forces us developers to know if a particular message will be handled async or not. If you handle many different messages this becomes an impossible task because you never know if deep down some function a passed-in sendResponse will be called async or not.
Consider this:
chrome.extension.onMessage.addListener(function (request, sender, sendResponseParam) {
if (request.method == "method1") {
handleMethod1(sendResponse);
}
How can I know if deep down handleMethod1 the call will be async or not? How can someone that modifies handleMethod1 knows that it will break a caller by introducing something async?
My solution is this:
chrome.extension.onMessage.addListener(function (request, sender, sendResponseParam) {
var responseStatus = { bCalled: false };
function sendResponse(obj) { //dummy wrapper to deal with exceptions and detect async
try {
sendResponseParam(obj);
} catch (e) {
//error handling
}
responseStatus.bCalled= true;
}
if (request.method == "method1") {
handleMethod1(sendResponse);
}
else if (request.method == "method2") {
handleMethod2(sendResponse);
}
...
if (!responseStatus.bCalled) { //if its set, the call wasn't async, else it is.
return true;
}
});
This automatically handles the return value, regardless of how you choose to handle the message. Note that this assumes that you never forget to call the response function. Also note that chromium could have automated this for us, I don't see why they didn't.
You can use my library https://github.com/lawlietmester/webextension to make this work in both Chrome and FF with Firefox way without callbacks.
Your code will look like:
Browser.runtime.onMessage.addListener( request => new Promise( resolve => {
if( !request || typeof request !== 'object' || request.type !== "getUrls" ) return;
$.ajax({
'url': "http://localhost:3000/urls",
'method': 'GET'
}).then( urls => { resolve({ urls }); });
}) );
I need to detect if user session is gone when expanding Select2 combobox. When that condition occurs, response is redirected to login page.
The Select2 is populated using an ajax call, so I have added this to the "ajax" parameter:
transport: function (params, success, failure) {
var $request = $.ajax(params);
$request.then(success);
$request.fail(function (jqXHR, textStatus, errorThrown) {
alert(errorThrown);
});
return $request;
}
The problem is that the error reported is not in XHR format (in order to detect 401 HTTP code) but an error telling "SyntaxError: Unexpected end of JSON input".
When seeing the response using Chrome developer tools, I do see that the response was in XHR format with 401 HTTP code but Select2 transforms it in some way.
Is there a way to solve this?
Regards
Jaime
ajax: {
// ...
error: function (jqXHR, status, error) {
console.log(error + ": " + jqXHR.responseText);
return { results: [] }; // Return dataset to load after error
}
}
I've the following generic PostTo method which can be used to post data to an ASP.NET MVc Controller, without the need for repetitive mark-up, I'm pretty sure it was working at one point, but for some reason, the success callback (any of it) doesn't get called.
Any thoughts? Everything looks right, and the server is responding with a valid 200 OK response.
It is however, an empty response. I tried a different (and empty) dataType value, but nothing changed.
function PostTo(controller, action, data, successCallback) {
$.ajax({
url: Settings.HostPath + controller + "/" + action,
type: "POST",
cache: false,
dataType: "json",
data: data,
success: function (data, textStatus, jqXHR) {
if (typeof (successCallback) != "undefined")
successCallback.call(this, data);
}
});
}
ajax method in your script, excepts json data from the server, but as you told in comments, your actions returns nothing (i thinks it's returns EmptyResult).
So, add any json result in your action:
public ActionResult Test()
{
return Json(new {Success = true});
}
I have below script in asp.net mvc:
$.ajax({
url: "/MyController/MyAction/",
type: 'POST',
data: $("#Myform").serialize(),
success: function () {
// Do something
},
error: function () {
// Do something
},
complete: function () {
// Do something
},
beforeSend: function () {
// Do someting
}
});
This script calls to an action in the controller. The controller performs some actions and sometimes things go ok or not. If things went ok, I want success and complete options in the script get executed.No problem until here, but if in the controller there is an error or something I want to tell the script: "hey, there is an error!" and then the error option in the script to be executed. How to do this? Do I have to return something from the controller to the script to indicate an error has been generated in order to error option in the script gets executed?
Set the HTTP status code to 4xx or 5xx in the controller.
That will make you end up in the error callback.
As far as the AJAX request goes an error is an transfer/network error getting the page.
If you want to return an error either return it in the data then parse that and execute the error function inside the success part if you detect an error. Or as, Johan says, return an HTTP error code from the server.
Use try catch in your action like,
public ActionResult Sample()
{
try
{
return Json(new{status="success"},JsonRequestBehavior.AllowGet);
}
catch(Exception ex)
{
return Json(new{status="failed"},JsonRequestBehavior.AllowGet);
}
}
In your ajax call success check with condition like,
if(data.status=='success')
{
alert('All Happies');
}
else
{
alert('error came');
}
Hope this helps.
I am using MVC to pass JSON data to JsTree and show a hierarchical view of information.
Everything is working just fine, however, there are times when the user does not have access the the data or for some reason the MVC action throws an exception:
In these cases, the action passes a JSON error message and sets the HttpStatusCode to NotAccepted or InternalServerError.
However the jsTree's sinner keeps spinning and I don't seem to find a way to make it stop and show the error message.
Has anyone solved this issue before? How can one does error handling when using JsTree's JSON data plugin?
UPDATE:
I figured out how to capture the error:
$("#jstree1").jstree({
"json_data": {
"ajax": {
"url": serviceUrl,
"data": function (n) {
return { pid: n.attr ? n.attr("id") : "" };
},
"error": function (x, s, r) { var err = $.parseJSON(x.responseText); if (err!="") { alert(err); } }
}
}
It seems that JsTree does get the MVC http statusCode and the error, now I need to figure out how to tell the JsTree to stop waiting and remove the spinner image!
I am also looking for a good way of showing the error in JsTree, or should I manage the error message outside of it?
I've solved this problem.
Just a note- the code example above for handling ajax call errors is incorrect, please see a complete example below:
$('#YourTree').jstree({
"json_data": {
"ajax": {
"url": "/Controller/Action",
"data": function () {
return { Parameter1: "Value1", Parameter2: "Value2" }
},
"type": "POST",
"dataType": "json",
"error": function (jqXHR, textStatus, errorThrown) { $('#YourTree').html("<h3>There was an error while loading data for this tree</h3><p>" + jqXHR.responseText + "</p>"); }
}
}
});
And in the actual action, you need to set the http response status code to 1 and write the error. e.g.
Response.StatusCode = 1
Response.Write("Error you want to go into jqXHR.responseText here");
Enjoy :)
Maybe you should look into handling this error a layer above the .jstree. Maybe by handling the window.onerror event you can achieve this. In here you could call a function that will rebuild the tree or something? Be sure to include this script as the first one in your page.
<script type="text/javascript">
window.onerror = function(x, s, r){
alert('An error has occurred!')
}
</script>