Skip to content

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 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), BR-SE-26
  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).
  3. If called with an Exception overload: the client receives ex.ToString() (the full stack trace) as the response body — a potential information-disclosure concern*.
  4. If called with a JObject overload: the content type is set to application/json.
  5. The exception propagates up to Dynamic error handler invocation, 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.

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*.

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