DNN API Controller中Task Canceled日志重复记录问题:如何优化页面离开时Ajax请求的错误处理
The core issue here is that when the browser triggers beforeunload, it will terminate any in-flight AJAX requests as the page unloads—this triggers a TaskCanceledException in your DNN Web API controller. Your existing try/catch blocks aren't catching this because:
- The exception is thrown after your synchronous
voidmethod completes, by DNN's Web API framework when it tries to process the canceled request context. - Browsers don't guarantee completion of standard AJAX requests during page unload, so the cancellation is an expected behavior, not an error.
Here's how to fix this properly, from frontend to backend:
Step 1: Update Frontend to Use Browser-Friendly Unload Requests
Replace your jQuery AJAX call with navigator.sendBeacon (or fetch with keepalive). These APIs are designed specifically for sending data during page unload—browsers will prioritize and complete these requests even as the page shuts down, reducing the chance of cancellation.
Modified Frontend Code:
$(window).on("beforeunload", function () { ClearTempUserSessionWhenLeavePage(); }); function ClearTempUserSessionWhenLeavePage() { if ($fromButtonEvent === false) { const url = $.fn.GetBaseURL() + 'DesktopModules/DNNCommon/API/Store/ClearTempUserSessionWhenLeavePage'; // Use sendBeacon for reliable unload requests navigator.sendBeacon(url); } $fromButtonEvent = false; }
If you need more control (e.g., POST requests or custom headers), use fetch with the keepalive flag:
fetch(url, { method: 'GET', keepalive: true, headers: { 'Content-Type': 'application/json' } });
Step 2: Fix Backend to Handle Cancellation Properly
Change your controller method to return a Task (async) instead of void. This lets you catch the TaskCanceledException directly, and tells DNN's framework you're handling async operations correctly. We'll also explicitly ignore cancellation exceptions since they're expected, and only log actual errors.
Modified Backend C# Code:
[AllowAnonymous] [HttpGet] public async Task ClearTempUserSessionWhenLeavePage() { try { if (SessionManager.GetSessionObject("NewCreatedWebUser") != null) { System.Web.HttpContext.Current.Session["DoNotRemoveSessionIfNotAuthenticated"] = false; SessionManager.SetSessionObject("NewCreatedWebUser", null); SessionManager.SetSessionObject("UserInfo", null); SessionManager.SetSessionObject("NewCustomerCode", null); } await Task.CompletedTask; // Explicit async completion } catch (TaskCanceledException) { // This is expected when the page unloads early—DO NOT log this return; } catch (Exception ex) { // Only log genuine errors (e.g., session access issues) var logController = new EventLogController(); logController.AddLog( "Genuine Error Clearing Temp User Session", ex.ToString(), EventLogController.EventLogType.ADMIN_ALERT ); } }
Step 3: Optional - DNN Global Exception Filter (For Edge Cases)
If you still see cancellation logs, you can add a global exception filter to DNN's Web API to ignore TaskCanceledException entirely. Create a filter class:
public class IgnoreTaskCanceledFilter : ExceptionFilterAttribute { public override void OnException(HttpActionExecutedContext context) { if (context.Exception is TaskCanceledException) { context.Response = new HttpResponseMessage(HttpStatusCode.OK); } else { base.OnException(context); } } }
Then register it in your module's Web API config (or DNN's global config if applicable):
GlobalConfiguration.Configuration.Filters.Add(new IgnoreTaskCanceledFilter());
Why This Works
- Frontend:
sendBeacon/fetch keepaliveensure the request is queued for background completion, avoiding immediate cancellation by the browser. - Backend: Async
Taskreturn type aligns with DNN's Web API async handling, letting you catch and ignore expected cancellation exceptions instead of letting the framework log them.
内容的提问来源于stack exchange,提问作者Tig7r

