---
title: Controller throw helpers
summary: ControllerBaseExtensions converts error conditions to typed HTTP error responses.
status: draft
owner: Framework.NCore maintainers
last_reviewed: 2026-10-02
library: SAIF.NetCore.ServiceExtensions
reference_type: package
operation_id: OP-21
trigger: A controller derived from ControllerBase calls one of the Throw* extension methods.
---

# Controller throw helpers

This operation is a set of `ControllerBase` extension methods that convert error conditions in controller action code into typed HTTP error responses, by throwing `HttpStatusCodeException` and relying on [Dynamic error handler invocation](dynamic-error-handler-invoke.md) to translate the exception into a response.

| Field | Value |
| --- | --- |
| **Operation ID** | OP-21 |
| **Trigger** | A controller action calls one of the `Throw*` helpers (`ThrowBadRequest`, `ThrowUnauthorized`, `ThrowPaymentRequired`, `ThrowNotFound`, `ThrowMethodNotAllowed`, `ThrowNotAcceptable`, `ThrowConflict`, `ThrowInternalServerError`). |
| **Inputs** | A message (`string`, `Exception`, or `JObject`) describing the error. |
| **Outputs** | A thrown `HttpStatusCodeException` carrying the mapped status code and content type. |
| **Primary components** | `ControllerBaseExtensions` |
| **Entry point** | `src/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/ControllerBaseExtensions.cs` (L23–280) |

## Steps

1. The controller calls a `Throw*` helper mapped to its HTTP status: BadRequest (400), Unauthorized (401), PaymentRequired (402), NotFound (404), MethodNotAllowed (405), NotAcceptable (406), Conflict (409), InternalServerError (500) ([BR-SE-13](../business-rules.md#br-se-13-exception-to-http-response-mapping)), [BR-SE-26](../business-rules.md#br-se-26-controller-helpers-convert-to-http-errors-by-throwing)
2. The helper throws `new HttpStatusCodeException(message) { ContentType = contentType, StatusCode = StatusCodes.Status400BadRequest }` (shown for the 400 case; each helper sets its own mapped `StatusCode` constant, for example `Status404NotFound` for `ThrowNotFound`).
   - If called with an `Exception` overload: the client receives `ex.ToString()` (the full stack trace) as the response body — a potential information-disclosure concern*.
   - If called with a `JObject` overload: the content type is set to `application/json`.
3. The exception propagates up to [Dynamic error handler invocation](dynamic-error-handler-invoke.md), which maps `HttpStatusCodeException` to a response using the exception's own status/content type.

## Process flow

This diagram shows the per-call branching inside a single `Throw*` helper invocation, not a multi-request or asynchronous sequence.

```mermaid
flowchart TD
    Start(["Controller calls Throw* helper"]) --> S1[Select mapped HTTP status code]
    S1 --> S2{Overload used?}
    S2 -->|Exception| S2a["Body = ex.ToString - stack trace"]
    S2 -->|JObject| S2b["Content type = application/json"]
    S2 -->|string| S2c[Plain message body]
    S2a --> S3[Throw HttpStatusCodeException]
    S2b --> S3
    S2c --> S3
    S3 --> EndOk([Propagates to DynamicErrorHandler for response writing])
```

## Failure and edge-case behavior
- The `Exception` overload sends the full stack trace (`ex.ToString()`) to the HTTP client, which may expose internal implementation details to callers*.

## 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/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/ControllerBaseExtensions.cs`
