I'm having a similar problem as: Find operation (AJAX request) rejected, not seen in the wire
However, in my case, I am making one request. This request works on normal page load. It fails to load silently after a form submit (not through ember), that redirects back to the same page. There is no AJAX request being made.
My main question is: how do I go about debugging issues like this?
What I've Tried
I've added console.log statements in all sorts of places to understand the request lifecycle.
Since I've read that promises can get rejected if something throws an exception within it, I've tried switching the chrome debugger to "Pause on all exceptions" (as opposed to "Pause on uncaught exceptions"). Of course it breaks at a bunch of exceptions like:
// This should fail with an exception
// Gecko does not error, returns false instead
try {
matches.call( div, "[test!='']:sizzle" );
But since I have a way to get the request to work and a way to get it to not work, I can easily compare the difference. I expected there to be an uncaught exception when my request failed, but no such luck.
I've also added a
Ember.RSVP.configure('onerror', function(error) {
console.log(error.message);
console.log(error.stack);
});
block, but it does not get called.
I've also poked around at different objects in the console to try and understand my application state:
store = App.__container__.lookup('store:main')
b = store.find('bundle')
b.isRejected // => true
b.reason.statusText // => "error"
Update: More Details
The project I am working on is backed by rails. I am using:
DEBUG: -------------------------------
DEBUG: Ember.VERSION : 1.0.0
DEBUG: Handlebars.VERSION : 1.0.0
DEBUG: jQuery.VERSION : 1.8.3
DEBUG: -------------------------------
And it doesn't show up in the debug output, but I'm using ember-data 1.0 beta 3:
// Version: v1.0.0-beta.3
// Last commit: 2259c27 (2013-09-28 19:24:07 -0700)
The app loads all of the bundles to render them and a form, but the form submits directly to rails. Rails processes the post request and redirects back to /, where the ember app lives.
The first request to / loads everything fine, but when I submit the form, and it redirects back, that's when my ajax call my call to store.find('bundle') does nothing.
UPDATE
I've discovered that my issue is related to pusher (websockets).
The issue seems intermittent and I've only seen it in Chrome (I've only tested Firefox).
The issue went away when I disconnected from websockets before a page refresh.
In your case the fail handler is receiving the jQuery XMLHttpRequest. Try to see what responseText and status is returning.
App.__container__.lookup('store:main').find('bundle').then(null, function(reason) {
reason.responseText // response from the server, maybe can show an error page in html
reason.status // 404 page not found, 500 some server error you will need to chech the logs etc.
});
I hope it helps
Related
Background:
I'm setting up error handling in an ASP.NET Core 2.2 MVC app. When in development environment, I use the app.UseDeveloperExceptionPage();, and in production - app.UseExceptionHandler("/Error/Index");. I am navigated to the correct error page during non-AJAX (regular form submission) requests based on the environment.
If an exception occurs in the server during an AJAX request, I want the app to display the correct error page depending on the environment.
I have already set up all of what I described above, as you can see in my code examples below.
Problem/Concern:
While this works (though still have to complete the TODO in InitializeGlobalAjaxEventHandlers function), I have some concerns.
With non-AJAX calls in MVC, it feels like there is a "official/correct" way to do it with app.UseDeveloperExceptionPage(); and app.UseExceptionHandler("/Error/Index");, which automatically redirects the program to the error page. With the AJAX end of error handling, however, I don't feel as confident because I pieced it together with parts from different solutions I've researched. I'm worried I'm not aware of what could go wrong.
Question:
Is this the proper way to handle errors during AJAX requests in MVC? Could something possibly go wrong with this set up? Is this in any way improper or too far from common standards?
Code:
Startup.cs > Configure method:
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
//using build config to use the correct error page: https://stackoverflow.com/a/62177235/12300287
//Reason why we don't use environmental variables is because we can't guarantee access to clients'
//machines to create them.
#if (DEVELOPMENT || STAGING)
app.UseDeveloperExceptionPage();
#else
app.UseExceptionHandler("/Error/Index");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
#endif
app.UseHttpsRedirection();
app.UseStaticFiles();
//app.UseCookiePolicy();
app.UseAuthentication();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=UserAccess}/{action=Index}/{id?}");
});
}
ErrorController.cs:
public class ErrorController : Controller
{
[AllowAnonymous]
public IActionResult Index()
{
IExceptionHandlerPathFeature exceptionDetails = HttpContext.Features.Get<IExceptionHandlerPathFeature>();
Exception exception = exceptionDetails?.Error; // Here will be the exception details.
Error model = new Error();
model.ID = exception.HResult;
model.Message = exception.Message;
model.Path = exceptionDetails.Path;
return View(model);
}
}
Global AJAX error event handler (the if statement is to handle authentication):
function InitializeGlobalAjaxEventHandlers() {
$(document).ajaxError(function (event, xhr, ajaxSettings, thrownError) {
//status is set in the [AuthorizeAjax] action filter if user isn't authenticated
if (xhr.status == 403) {
var response = $.parseJSON(xhr.responseText);
window.location = response.redirectUrl;
}
//the document HTML is replaces by responseText value, which contains the HTML of error page
document.write(xhr.responseText);
//TODO: will need to display an error page if responseText is empty, which
//can happen if an AJAX request doesn't reach the server (for example: if URL is incorrect).
});
}
As you explain, there are two threads of code to consider. One is at the client and the other at the server.
Whilst the server can return codes and messages for non-expected results, the client must still be robust and stand-alone. For example, if the server cannot be reached, a time-out error can occur at the client which it must handle. As mentioned above, you can catch errors at the local and global Ajax level.
The server may also generate an error response that never reaches the client.
In some projects I have performed the following:-
If a non-expected result is generated on the server, it is logged in a database and returns an JSON message as an error.
If a non-expected result is generated on the client, a server service is called to log the error on the database.
In both cases, a message is displayed in the current page. A user can also navigate to an error page where recent errors (stored in the database) are displayed.
Working on many project of varying sizes, I've come to the conclusion that there isn't really a solution that fits everything
Is this the proper way to handle errors during AJAX requests in MVC? Could something possibly go wrong with this set up? Is this in any way improper or too far from common standards?
As far as I know, there are no unified/official way of handling Ajax errors in ASP.NET Core MVC project.
Normally we show specific confirm message/content through Ajax error callback function if the Ajax request fails rather than directly displaying detailed exception information to client user, which would help achieve a better customer experience.
If you have specific requirement that requires displaying the Developer Exception Page/custom error page while Ajax request fails, as you did, you can dynamically write the returned responseText to the HTML document using document.write(xhr.responseText); in global error handler.
Using Vue Resource with Vue.js v1
This is also running using vue-router and built with Browserfy.
I have vue-resource working on the whole for post and gets but I have one particular one which occasionally times out or so it seems. I confirm the server is getting the post request and then sending the response back but the webpage sits waiting as if it's missed the response. It seems to happen randomly. If i reload the page and resend then it works.
I've tried to replicate by pausing the server before the sending of the response, wait a bit then continue. In that case it works everytime and webpage continues as expected.
my post functions is as follows (slightly edited to shrink so easier to read)
this.saving = true;
// POST save to the database
this.$http.post('/api/savebr',
{
tNumber: parseInt(this.tNumber),
bNumber: parseInt(this.cNumber)
},
// I added the timeout for testing
{ timeout: 2000 }
).then((response) => {
this.completed.push(parseInt(this.cNumber));
this.saving = false;
}, (response) =>
{
// error callback
console.log(response);
this.saving = false;
alert('Could not save to server. Please try again.');
})
}
In above the timeout works if I pause the server. When the server continues the webpage ignores the response which I guess is correct.
When the webpage randomly misses the response the error callback is never done. It works if I alter response from server to be an error which is expected too.
The timeout option I added recently to see if that makes any odds and also tried with zero setting.
Is it possible to detect the timeout, cancel the current post and send a new one?
If I repeat the post, suddenly both seem to work and so the success code runs twice even though originally the first request seems to be stuck.
Sorry for long post and all pointers gratefully received.
I have opened asked this question on the Sails project, but it might not be related to Sails at all -- maybe related to Node.js, Express.js or my own code, so I wonder if anyone has ever experienced this:
I have noticed that the browser requests are "replayed" on the server. In order to test it, I did this:
Created a simple controller action that prints "this is a request" on the server -- but does nothing else: it doesn't even send a response to the browser.
When I hit that route, the server console prints "this is a request", as expected.
Keep waiting. The browser keeps looping. After 2.5 minutes, "this is a request" is printed again on the server. Is this an expected behavior?
Worst:
Reload the server.
Hit the route.
"this is a request" is printed on the console.
Now ctrl+c the server to shut it down and right away sails lift it again while the browser is still looping.
The browser will stop, and right after the server is lifted.... "this is a request" is printed on the console.
More info: I am using sails sockets-io and my code has a "reconnect" function:
io.socket.on('disconnect', function(){
socketCleanup();
io.socket.on('connect', function(){
socketConnect();
});
});
This is used to re-subscribe the user socket to special rooms ( io.socket.post(socketRooms... ) but I don't think it would be responsible for these "replays".
If anything of the above is not the expected behavior, could it be possible that, after an upload is cancelled, there is something trying to replay the upload, causing the server to crash?
I am running Sails on Windows 7.
Something I never knew:
node.js page refresh calling resources twice?
Could this all be caused by favicon???
It seems there is a known bug for Chrome regarding favicons causing duplicate requests: https://bugs.chromium.org/p/chromium/issues/detail?id=64810
However, this doesn't seem related, since the second request here is happening 2.5 minutes later. I have tested with Firefox and IE 9 and the issue is valid there.
My users, when on a SPA page, are getting logged out after a couple of hours. Though, if they use the older postback forms, they never time out. So you have context, I have included enough code to provide context for the description of the issue on the bottom.
Web.config for authentication
<authentication mode="Forms">
<forms loginUrl="~/Account/Login" timeout="480" slidingExpiration="true" defaultUrl="~" ticketCompatibilityMode="Framework40"/>
</authentication>
My api controller
namespace my.Controllers
{
public class ApiMotionController : ApiController
{
[Authorize(Roles = "Mover"]
public IQueryable<Motions> Get()
JavaScript code
(function () {
'use strict';
angular.module('app')
.controller('MotionManager', ['$scope', '$http', buildMotionManager]);
function buildMotionManager($scope, $http) {
/*Static Members*/
$scope._whoami = 'MotionManager'; //Used for troubleshooting controller
/*Initialization Code*/
getMotions($scope, $http)();
/*Scope methods*/
$scope.refreshMotionsList = getMotions($scope, $http);
$scope.addMotion = addMotion($scope, $http);
$scope.playMotion = playMotion($scope, $http);
}
function getMotions($scope, $http){
return function(){
$http.get('/api/getMotions')
.succeed(function(data){
$scope.motionList = data;
})
.error(function(data){
console.log('FAIL', data);
});
};
}
function addMotion($scope, $http){
//stub. Code not shown here.
};
function playMotion($scope, $http){
//stub. Code not shown here.
};
})();
There my be typos in the above code, since I retyped it from my original while sanitizing.
The code does work as expected, but the problem is that after hours of working, suddenly all web API calls are failing with a 401 error. That is, they are all acting like the user is now de-authenticated.
As above, I cannot duplicate this issue when I am using web forms, or even MVC forms, and re-posting whole pages. It is only when I am using SPA style coding. I haven't tried other SPA frameworks, since I have 6 months of angular directed code in this project, switching isn't an option.
I have considered putting an iframe, with a timer to fire off in the background against a form object, just to trick the browser into generating a proper form postback. I want to avoid doing that, because it seems to hacky.
The only other key issue I have found is that I am seeing a bunch of schannel errors being logged into my application event log on the IIS server. They are all 10,10 which isn't well documented. The 10 series is well documented outside of 10,10. But none of those suggestions seem to work, or are even relevant.
Server is IIS 7.5 and I have tried this on IIS 8.
Application Log Errors:
A fatal alert was generated and sent to the remote endpoint. This may result in termination of the connection. The TLS protocol defined fatal error code is 10. The Windows SChannel error state is 10.
Error State: 10, Alert Description: 10
A fatal alert was generated and sent to the remote endpoint. This may result in termination of the connection. The TLS protocol defined fatal error code is 40. The Windows SChannel error state is 1205.
An TLS 1.2 connection request was received from a remote client application, but none of the cipher suites supported by the client application are supported by the server. The SSL connection request has failed.
Discovery
Error Code 40 means that there is a handshake issue. Since State Management is custom for my platform, I decided to change it to inproc. So far, I have seen the error log reduce in new error frequency, but disappear. However, I am still testing for the 401 issue.
Post discovery follow up
Had the certs re-issued, and the schannel errors cleared, but the problem remained.
I had started exploring the header information with a fine tooth comb, even if it means that I had to add custom header information to accompany my server calls.
I have now included in all $http calls withCredentials: true, which has brought my failure rate down to around 15%. that means that the failures are down to once or twice a day.
I started watching my 'auth' cookie on the client, and something confusing happens occasionally. The cookie will change without prompt, then it has changed back. Almost like the session is bouncing from current, to a new one, then back to current. So I have killed my cleanup process on the session table on the server, and see what I am getting there.
I had also been checking the system logs for exceptions, or SQL timeouts, and nothing.
Started to convert all controllers to MVC controllers, but I have hit conversion problems after conversion problems, including the use of jSON serializer. I still don't understand the decision to stick with the MS serializer when the JSON.NET one work so much better.
Current Status
The last change I made was to add filters.Add(new AuthorizeAttribute()); to my FilterConfig.RegisterGlobalFilters function.
Everything is still failing. After investigating the IIS logs I am still seeing everything getting de-authenticated.
FF on Windows - Fail
Chrome on Windows - Fail
Chrome on Droid - Fail
Safari on iPad - Fail
IE on Windows - Fail
12/10 Discovery
I have found the real problem. The authentication in MVC controllers are just not compatible with the web API controllers. So when I authenticate with the MVC controller, the web API controllers basically ignore it, and eventually time out on the authentication.
Latest Discovery
Apparently when the asp.net worker process shut down, and restarted, it would get a false flag that the database schema didn't exists. So I removed the check, and all reads and writes started working fine. It is interesting that the api controller would forge a new cookie when the mvc controller would fail the authentication. It was like it was creating a new provider instance. However, I couldn't find a 2nd instance, so I have to assume the existing provider was being duplicated.
Fix that is being tested
Now that I have removed the DB test, I am now testing the issue in long run tests. Each long run is longer than the worker process stays alive, but shorter than the session timeout.
Cornerstone of finding this bug
Apparently IIS Express was hiding the bug in that it seems to act without an external worker process. So I moved the test environment to my local IIS server.
It looks like there are several issues that were causing my problem, each one broken down here:
IIS Express wasn't closing sessions the same way that full IIS would.
So I moved the application to my local IIS, and added logging to everything.
ASP.NET worker process would launch new provider instance every time the API Controllers were called.
This would cause a new schema check per call. MVC controllers would only cause this check once per initial launch.
Since my provider is marries to my application schema, I just disabled the schema check.
Angular must be told to marshal the cookies.
So I added: cfg: { withCredentials: true, responseType: "json" }
the response type was to cover the occasional issue where I would see 'text/text'. Now I always see 'application/json'. This seems to be a browser issue, mostly with IE.
I also had to add config.MapHttpAttributeRoutes(); to my register method of my WebApiConfig class.
Using all of this, I was able to discover that the core of the problem was that every api call was causing my security provider to re-test the schema, which my MVC controllers are set to suppress that test after first load. The test always fails, because I had to expand a couple of tables, but I didn't need the models changed.
Resolution: I removed the test from the provider. Since the provider is strongly tied into the rest of the application, it didn't seem logical to keep treating it as a typical ASP.NET Membership provider. And that was the top feature that I didn't need.
Second benefit, I gained back a little bit of performance.
It seems like something has changed on the Yammer side, because my app (not yet published to the Yammer Global App Directory) has stopped working, resulting in an obscure CORS error, that doesn't tell a thing about the problem.
So the workflow is very simple —
I'm ensuring that user is logged in by calling getLoginStatus() (which pops-up a window and immediately closes it. Irritating, but can live with that)
Sending a request to messages/in_group/ID.json wrapped in a yam.platform.request, as suggested by the Yammer JS SDK manual
Here's the console screenshot:
In the Yammer App settings there's a single Javascript Origin, which is https://buzztale.com, which is exactly the one, the request is made from.
This happened before, but then disappeared itself (really confusing). And now it seems to be back…
Hope somebody has any suggestions regarding this issue. In order to get to the app, here's the URL — https://buzztale.com/yammer.
Same here my dev app started failing sometime today.
It seems that all of the login end points are working as expected however the messages feed is giving me CORS errors.
yam.platform.request({
url: "https://api.yammer.com/api/v1/messages/my_feed.json",
method: "GET",
success: function (user) { //print message response information to the console
console.log("The request was successful." + user.messages);
},
error: function (user) {
console.log("There was an error with the request.");
}
});
Yeah, I'm seeing this on our end too. Seems to be just the GET requests with the messages api endpoint. Like POST / DELETE and Message POST seem to work correctly.
This issue appeared to me around 4PM PST yesterday (7/22/14).
This was a known issue with a recent change on our side, and we have
pushed a fix to production today. Please let me know if it still isn't
working for you. — Nick
So it is an issue on the Yammer side and we can just hope for it not to appear again.
I am seeing this with the notifications endpoint as well. I noticed that the CLIENT_ID is not being appended to the call
https://api.yammer.com/api/v1/streams/notifications.json?&_=xxxxxxxxxx