---
title: Handle and log an unhandled action exception
summary: Log an unhandled action exception with full diagnostic context and redirect non-AJAX requests.
status: draft
owner: SAIF Documentation
last_reviewed: 2026-09-17
library: SAIF.Framework.Web.Mvc
reference_type: package
operation_id: OP-08
trigger: Any unhandled exception in an action on a controller the filter is applied to
---

# Handle and log an unhandled action exception

Log an unhandled action exception with full diagnostic context and redirect non-AJAX requests. Trigger: Any unhandled exception in an action on a controller the filter is applied to.

| Field | Value |
| --- | --- |
| **Operation ID** | OP-08 |
| **Trigger** | Any unhandled exception in an action on a controller the filter is applied to |
| **Inputs** | `ExceptionContext` (request, controller, exception) |
| **Outputs** | Log entry via `ILogService`; redirect for non-AJAX requests |
| **Primary components** | `HandleExceptionAttribute.OnException(ExceptionContext)` |
| **Entry point** | `src/Web.Mvc/ActionFilters/HandleExceptionAttribute.cs` |

## Steps

1. Proceed only when both `LogService` and `filterContext` are non-null; otherwise do nothing at all — no logging and no redirect ([BR-11](../business-rules.md#br-11-exception-handling-requires-the-log-service-and-filter-context)).
2. Build state information (`BuildStateInformation`): when the controller is a `WebContextControllerBase`, append `WebContextAsString()`; then append every entry of `HttpContextExtensions.GetValuesAsDictionary(request)` as `key : value` lines — HttpMethod, IsAjaxRequest, RawUrl, Form, QueryString, ContentType, AnonymousID, browser version/type/gateway version, UserAgent, UserAddress, UserName, and UrlReferrer when present ([BR-12](../business-rules.md#br-12-logged-exception-state-includes-full-context-and-request-diagnostics)).
3. Call `LogService.LogException(applicationName, controllerAndActionName, state, exception)`, the first two values deriving from `Request.Url.ApplicationName()` and `Request.Url.ControllerAndActionName()`.
4. Swallow any exception raised while logging (`catch (System.Exception) { }`) so error handling never throws ([BR-13](../business-rules.md#br-13-logging-failures-never-surface-to-the-user)).
5. In the `finally` block, when the request is not an AJAX request, `Response.Redirect` to `{Constants.ErrorUrl}?MSG={UrlEncode(exception.Message)}`. AJAX requests are logged but receive no redirect ([BR-14](../business-rules.md#br-14-ajax-requests-are-logged-but-not-redirected)).

## Process flow

The following diagram visualizes this operation's control flow.

```mermaid
flowchart TD
	Start([Unhandled exception])
	Chk{LogService and filterContext present?}
	Skip(["No logging, no redirect"])
	Build[Build state information]
	Log[LogService.LogException]
	Catch[Swallow logging failures]
	Ajax{Is AJAX request?}
	NoRedir(["Logged, no redirect"])
	Redir([Redirect to error page])
	Start --> Chk
	Chk -->|No| Skip
	Chk -->|Yes| Build
	Build --> Log
	Log --> Catch
	Catch --> Ajax
	Ajax -->|Yes| NoRedir
	Ajax -->|No| Redir
```

## Failure and edge-case behavior

- `filterContext.ExceptionHandled` is never set, so MVC's default error handling still applies afterwards.*

## Related documentation
- [Operations and processes](../operations-processes.md)
- [Business rules](../business-rules.md)

> **Note:** Statements marked with `*` were inferred from code structure, naming
> conventions, or contextual evidence where direct confirmation was not available
> in source artifacts. Statements marked with `**` could not be confirmed; treat
> as unknown until verified.


## Sources
- `src/Web.Mvc/ActionFilters/HandleExceptionAttribute.cs`
