From ec8984f6381a2055ada4787fc11060b4cc3f1d10 Mon Sep 17 00:00:00 2001 From: Marcin Szopa Date: Fri, 9 Oct 2026 20:21:55 +0200 Subject: [PATCH 1/3] [csharp][restsharp] throwOnAnyError: throw ApiException instead of raw RestSharp exceptions Setting RestSharp's ThrowOnAnyError makes RestSharp throw HttpRequestException for every non-2xx status as well, before ExceptionFactory runs. Callers that enable the option lose the ApiException contract (status code, body, headers) for ordinary 4xx/5xx responses, and transport failures surface as raw HttpRequestException. Keep the option opt-in but implement it in ApiClient: after the request, if RestSharp recorded an ErrorException and the status is below 400, throw ApiException carrying the status (0 for transport failures, the real 2xx for deserialization failures), the response body and headers. 4xx/5xx keep flowing to ExceptionFactory. The retry-policy path returns the error response so the same guard handles it. Co-authored-by: mrd4rkne --- docs/generators/csharp.md | 2 +- .../codegen/languages/CSharpClientCodegen.java | 2 +- .../src/main/resources/csharp/ApiClient.mustache | 16 +++++++++------- .../resources/csharp/ApiClient.v790.mustache | 13 ++++++++----- .../src/Org.OpenAPITools/Client/ApiClient.cs | 14 +++++++++++--- 5 files changed, 30 insertions(+), 17 deletions(-) diff --git a/docs/generators/csharp.md b/docs/generators/csharp.md index eb6fcdf5df13..85191739fac5 100644 --- a/docs/generators/csharp.md +++ b/docs/generators/csharp.md @@ -47,7 +47,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |returnICollection|Return ICollection<T> instead of the concrete type.| |false| |sourceFolder|source folder for generated code| |src| |targetFramework|The target .NET framework version. To target multiple frameworks, use `;` as the separator, e.g. `netstandard2.1;netcoreapp3.1`|
**netstandard1.3**
.NET Standard 1.3
**netstandard1.4**
.NET Standard 1.4
**netstandard1.5**
.NET Standard 1.5
**netstandard1.6**
.NET Standard 1.6
**netstandard2.0**
.NET Standard 2.0
**netstandard2.1**
.NET Standard 2.1
**net47**
.NET Framework 4.7
**net48**
.NET Framework 4.8
**net8.0**
.NET 8.0 (End of Support 10 November 2026)
**net9.0**
.NET 9.0 (End of Support 10 November 2026)
**net10.0**
.NET 10.0 (End of Support 14 November 2028)
|net10.0| -|throwOnAnyError|Configure RestSharp to rethrow deserialization and transport errors instead of swallowing them into RestResponse.ErrorException (which the default ToApiResponse<T> discards as null Data). Recommended for production use to surface bugs that would otherwise be invisible. (restsharp only)| |false| +|throwOnAnyError|Throw ApiException on deserialization and transport errors instead of swallowing them into RestResponse.ErrorException (which the default ToApiResponse<T> discards as null Data). HTTP error statuses keep going through ExceptionFactory. Recommended for production use to surface bugs that would otherwise be invisible. (restsharp only)| |false| |useCollection|Deserialize array types to Collection<T> instead of List<T>.| |false| |useDateTimeForDate|Use DateTime to model date properties even if DateOnly supported. (.net 6.0+ only)| |false| |useDateTimeOffset|Use DateTimeOffset to model date-time properties| |false| diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CSharpClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CSharpClientCodegen.java index 8c1bfffb2b39..f72bc24187d0 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CSharpClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CSharpClientCodegen.java @@ -255,7 +255,7 @@ public CSharpClientCodegen() { String.valueOf(this.useIntForTimeout)); addSwitch(CSharpClientCodegen.THROW_ON_ANY_ERROR, - "Configure RestSharp to rethrow deserialization and transport errors instead of swallowing them into RestResponse.ErrorException (which the default ToApiResponse discards as null Data). Recommended for production use to surface bugs that would otherwise be invisible. (restsharp only)", + "Throw ApiException on deserialization and transport errors instead of swallowing them into RestResponse.ErrorException (which the default ToApiResponse discards as null Data). HTTP error statuses keep going through ExceptionFactory. Recommended for production use to surface bugs that would otherwise be invisible. (restsharp only)", this.throwOnAnyError); CliOption framework = new CliOption( diff --git a/modules/openapi-generator/src/main/resources/csharp/ApiClient.mustache b/modules/openapi-generator/src/main/resources/csharp/ApiClient.mustache index d1946b37a38f..29cf8236935b 100644 --- a/modules/openapi-generator/src/main/resources/csharp/ApiClient.mustache +++ b/modules/openapi-generator/src/main/resources/csharp/ApiClient.mustache @@ -467,8 +467,7 @@ namespace {{packageName}}.Client Proxy = configuration.Proxy, UserAgent = configuration.UserAgent, UseDefaultCredentials = configuration.UseDefaultCredentials, - RemoteCertificateValidationCallback = configuration.RemoteCertificateValidationCallback{{#throwOnAnyError}}, - ThrowOnAnyError = true{{/throwOnAnyError}} + RemoteCertificateValidationCallback = configuration.RemoteCertificateValidationCallback }; setOptions(clientOptions); @@ -495,6 +494,14 @@ namespace {{packageName}}.Client InterceptRequest(request); RestResponse response = await getResponse(client).ConfigureAwait(false); + {{#throwOnAnyError}} + + // 4xx/5xx also carry ErrorException; those go through ExceptionFactory so the body is kept + if (response.ErrorException != null && (int)response.StatusCode < 400) + { + throw new ApiException((int)response.StatusCode, string.Format("Error calling {0}: {1}", request.Resource, response.ErrorMessage), response.Content, ToApiResponse(response).Headers); + } + {{/throwOnAnyError}} // if the response type is oneOf/anyOf, call FromJSON to deserialize the data if (typeof(AbstractOpenAPISchema).IsAssignableFrom(typeof(T))) @@ -567,15 +574,10 @@ namespace {{packageName}}.Client } else { - {{#throwOnAnyError}} - throw policyResult.FinalException ?? new InvalidOperationException("The retry policy failed without an exception."); - {{/throwOnAnyError}} - {{^throwOnAnyError}} return new RestResponse(request) { ErrorException = policyResult.FinalException }; - {{/throwOnAnyError}} } } diff --git a/modules/openapi-generator/src/main/resources/csharp/ApiClient.v790.mustache b/modules/openapi-generator/src/main/resources/csharp/ApiClient.v790.mustache index 6eb294e1aec0..22bf1e910d91 100644 --- a/modules/openapi-generator/src/main/resources/csharp/ApiClient.v790.mustache +++ b/modules/openapi-generator/src/main/resources/csharp/ApiClient.v790.mustache @@ -486,6 +486,14 @@ namespace {{packageName}}.Client InterceptRequest(request); RestResponse response = await getResponse(client); + {{#throwOnAnyError}} + + // 4xx/5xx also carry ErrorException; those go through ExceptionFactory so the body is kept + if (response.ErrorException != null && (int)response.StatusCode < 400) + { + throw new ApiException((int)response.StatusCode, string.Format("Error calling {0}: {1}", request.Resource, response.ErrorMessage), response.Content, ToApiResponse(response).Headers); + } + {{/throwOnAnyError}} // if the response type is oneOf/anyOf, call FromJSON to deserialize the data if (typeof(AbstractOpenAPISchema).IsAssignableFrom(typeof(T))) @@ -558,15 +566,10 @@ namespace {{packageName}}.Client } else { - {{#throwOnAnyError}} - throw policyResult.FinalException ?? new InvalidOperationException("The retry policy failed without an exception."); - {{/throwOnAnyError}} - {{^throwOnAnyError}} return new RestResponse(request) { ErrorException = policyResult.FinalException }; - {{/throwOnAnyError}} } } diff --git a/samples/client/petstore/csharp/restsharp/net4.7/MultipleFrameworks/src/Org.OpenAPITools/Client/ApiClient.cs b/samples/client/petstore/csharp/restsharp/net4.7/MultipleFrameworks/src/Org.OpenAPITools/Client/ApiClient.cs index 029798be3ae0..b741a64994f9 100644 --- a/samples/client/petstore/csharp/restsharp/net4.7/MultipleFrameworks/src/Org.OpenAPITools/Client/ApiClient.cs +++ b/samples/client/petstore/csharp/restsharp/net4.7/MultipleFrameworks/src/Org.OpenAPITools/Client/ApiClient.cs @@ -468,8 +468,7 @@ private async Task> ExecClientAsync(Func> ExecClientAsync(Func response = await getResponse(client).ConfigureAwait(false); + // 4xx/5xx also carry ErrorException; those go through ExceptionFactory so the body is kept + if (response.ErrorException != null && (int)response.StatusCode < 400) + { + throw new ApiException((int)response.StatusCode, string.Format("Error calling {0}: {1}", request.Resource, response.ErrorMessage), response.Content, ToApiResponse(response).Headers); + } + // if the response type is oneOf/anyOf, call FromJSON to deserialize the data if (typeof(AbstractOpenAPISchema).IsAssignableFrom(typeof(T))) { @@ -566,7 +571,10 @@ private async Task> DeserializeRestResponseFromPolicyAsync(Re } else { - throw policyResult.FinalException ?? new InvalidOperationException("The retry policy failed without an exception."); + return new RestResponse(request) + { + ErrorException = policyResult.FinalException + }; } } From c3cfea235ee6ca0d69e281c4700d4f9bfebfc8b7 Mon Sep 17 00:00:00 2001 From: Marcin Szopa Date: Mon, 12 Oct 2026 09:35:03 +0200 Subject: [PATCH 2/3] [csharp][restsharp] Preserve the original exception when throwOnAnyError wraps it Review follow-up: the retry-policy path sets only ErrorException, so the message was blank and the stack trace lost. Add an ApiException constructor that takes an inner exception and use the exception's own message. Co-authored-by: mrd4rkne --- .../src/main/resources/csharp/ApiClient.mustache | 2 +- .../main/resources/csharp/ApiClient.v790.mustache | 2 +- .../src/main/resources/csharp/ApiException.mustache | 12 +++++++++++- .../src/Org.OpenAPITools/Client/ApiException.cs | 12 +++++++++++- .../src/Org.OpenAPITools/Client/ApiException.cs | 12 +++++++++++- .../src/Org.OpenAPITools/Client/ApiException.cs | 12 +++++++++++- .../src/Org.OpenAPITools/Client/ApiException.cs | 12 +++++++++++- .../src/Org.OpenAPITools/Client/ApiException.cs | 12 +++++++++++- .../src/Org.OpenAPITools/Client/ApiException.cs | 12 +++++++++++- .../src/Org.OpenAPITools/Client/ApiException.cs | 12 +++++++++++- .../src/Org.OpenAPITools/Client/ApiException.cs | 12 +++++++++++- .../src/Org.OpenAPITools/Client/ApiException.cs | 12 +++++++++++- .../src/Org.OpenAPITools/Client/ApiClient.cs | 2 +- .../src/Org.OpenAPITools/Client/ApiException.cs | 12 +++++++++++- .../src/Org.OpenAPITools/Client/ApiException.cs | 12 +++++++++++- .../src/Org.OpenAPITools/Client/ApiException.cs | 12 +++++++++++- .../src/Org.OpenAPITools/Client/ApiException.cs | 12 +++++++++++- .../src/Org.OpenAPITools/Client/ApiException.cs | 12 +++++++++++- .../src/Org.OpenAPITools/Client/ApiException.cs | 12 +++++++++++- .../src/Org.OpenAPITools/Client/ApiException.cs | 12 +++++++++++- .../src/Org.OpenAPITools/Client/ApiException.cs | 12 +++++++++++- .../src/Org.OpenAPITools/Client/ApiException.cs | 12 +++++++++++- .../src/Org.OpenAPITools/Client/ApiException.cs | 12 +++++++++++- .../src/Org.OpenAPITools/Client/ApiException.cs | 12 +++++++++++- .../src/Org.OpenAPITools/Client/ApiException.cs | 12 +++++++++++- .../src/Org.OpenAPITools/Client/ApiException.cs | 12 +++++++++++- .../src/Org.OpenAPITools/Client/ApiException.cs | 12 +++++++++++- 27 files changed, 267 insertions(+), 27 deletions(-) diff --git a/modules/openapi-generator/src/main/resources/csharp/ApiClient.mustache b/modules/openapi-generator/src/main/resources/csharp/ApiClient.mustache index 29cf8236935b..053865e0c91a 100644 --- a/modules/openapi-generator/src/main/resources/csharp/ApiClient.mustache +++ b/modules/openapi-generator/src/main/resources/csharp/ApiClient.mustache @@ -499,7 +499,7 @@ namespace {{packageName}}.Client // 4xx/5xx also carry ErrorException; those go through ExceptionFactory so the body is kept if (response.ErrorException != null && (int)response.StatusCode < 400) { - throw new ApiException((int)response.StatusCode, string.Format("Error calling {0}: {1}", request.Resource, response.ErrorMessage), response.Content, ToApiResponse(response).Headers); + throw new ApiException((int)response.StatusCode, string.Format("Error calling {0}: {1}", request.Resource, response.ErrorException.Message), response.Content, ToApiResponse(response).Headers, response.ErrorException); } {{/throwOnAnyError}} diff --git a/modules/openapi-generator/src/main/resources/csharp/ApiClient.v790.mustache b/modules/openapi-generator/src/main/resources/csharp/ApiClient.v790.mustache index 22bf1e910d91..adcb2d15c8bc 100644 --- a/modules/openapi-generator/src/main/resources/csharp/ApiClient.v790.mustache +++ b/modules/openapi-generator/src/main/resources/csharp/ApiClient.v790.mustache @@ -491,7 +491,7 @@ namespace {{packageName}}.Client // 4xx/5xx also carry ErrorException; those go through ExceptionFactory so the body is kept if (response.ErrorException != null && (int)response.StatusCode < 400) { - throw new ApiException((int)response.StatusCode, string.Format("Error calling {0}: {1}", request.Resource, response.ErrorMessage), response.Content, ToApiResponse(response).Headers); + throw new ApiException((int)response.StatusCode, string.Format("Error calling {0}: {1}", request.Resource, response.ErrorException.Message), response.Content, ToApiResponse(response).Headers, response.ErrorException); } {{/throwOnAnyError}} diff --git a/modules/openapi-generator/src/main/resources/csharp/ApiException.mustache b/modules/openapi-generator/src/main/resources/csharp/ApiException.mustache index f7dadc5573c9..d27ab2a43993 100644 --- a/modules/openapi-generator/src/main/resources/csharp/ApiException.mustache +++ b/modules/openapi-generator/src/main/resources/csharp/ApiException.mustache @@ -49,7 +49,17 @@ namespace {{packageName}}.Client /// Error message. /// Error content. /// HTTP Headers. - public ApiException(int errorCode, string message, object errorContent = null, Multimap headers = null) : base(message) + public ApiException(int errorCode, string message, object errorContent = null, Multimap headers = null) : this(errorCode, message, errorContent, headers, null) { } + + /// + /// Initializes a new instance of the class. + /// + /// HTTP status code. + /// Error message. + /// Error content. + /// HTTP Headers. + /// The exception that caused this error. + public ApiException(int errorCode, string message, object errorContent, Multimap headers, Exception innerException) : base(message, innerException) { this.ErrorCode = errorCode; this.ErrorContent = errorContent; diff --git a/samples/client/echo_api/csharp/restsharp/net8/EchoApi/src/Org.OpenAPITools/Client/ApiException.cs b/samples/client/echo_api/csharp/restsharp/net8/EchoApi/src/Org.OpenAPITools/Client/ApiException.cs index 550576899c0e..cfddcf09a65d 100644 --- a/samples/client/echo_api/csharp/restsharp/net8/EchoApi/src/Org.OpenAPITools/Client/ApiException.cs +++ b/samples/client/echo_api/csharp/restsharp/net8/EchoApi/src/Org.OpenAPITools/Client/ApiException.cs @@ -58,7 +58,17 @@ public ApiException(int errorCode, string message) : base(message) /// Error message. /// Error content. /// HTTP Headers. - public ApiException(int errorCode, string message, object errorContent = null, Multimap headers = null) : base(message) + public ApiException(int errorCode, string message, object errorContent = null, Multimap headers = null) : this(errorCode, message, errorContent, headers, null) { } + + /// + /// Initializes a new instance of the class. + /// + /// HTTP status code. + /// Error message. + /// Error content. + /// HTTP Headers. + /// The exception that caused this error. + public ApiException(int errorCode, string message, object errorContent, Multimap headers, Exception innerException) : base(message, innerException) { this.ErrorCode = errorCode; this.ErrorContent = errorContent; diff --git a/samples/client/others/csharp-complex-files/src/Org.OpenAPITools/Client/ApiException.cs b/samples/client/others/csharp-complex-files/src/Org.OpenAPITools/Client/ApiException.cs index d0cc328420a5..e52f738711da 100644 --- a/samples/client/others/csharp-complex-files/src/Org.OpenAPITools/Client/ApiException.cs +++ b/samples/client/others/csharp-complex-files/src/Org.OpenAPITools/Client/ApiException.cs @@ -57,7 +57,17 @@ public ApiException(int errorCode, string message) : base(message) /// Error message. /// Error content. /// HTTP Headers. - public ApiException(int errorCode, string message, object errorContent = null, Multimap headers = null) : base(message) + public ApiException(int errorCode, string message, object errorContent = null, Multimap headers = null) : this(errorCode, message, errorContent, headers, null) { } + + /// + /// Initializes a new instance of the class. + /// + /// HTTP status code. + /// Error message. + /// Error content. + /// HTTP Headers. + /// The exception that caused this error. + public ApiException(int errorCode, string message, object errorContent, Multimap headers, Exception innerException) : base(message, innerException) { this.ErrorCode = errorCode; this.ErrorContent = errorContent; diff --git a/samples/client/petstore/csharp/httpclient/net10/Petstore-nonPublicApi/src/Org.OpenAPITools/Client/ApiException.cs b/samples/client/petstore/csharp/httpclient/net10/Petstore-nonPublicApi/src/Org.OpenAPITools/Client/ApiException.cs index a19e757f19ba..b41d02128238 100644 --- a/samples/client/petstore/csharp/httpclient/net10/Petstore-nonPublicApi/src/Org.OpenAPITools/Client/ApiException.cs +++ b/samples/client/petstore/csharp/httpclient/net10/Petstore-nonPublicApi/src/Org.OpenAPITools/Client/ApiException.cs @@ -57,7 +57,17 @@ public ApiException(int errorCode, string message) : base(message) /// Error message. /// Error content. /// HTTP Headers. - public ApiException(int errorCode, string message, object errorContent = null, Multimap headers = null) : base(message) + public ApiException(int errorCode, string message, object errorContent = null, Multimap headers = null) : this(errorCode, message, errorContent, headers, null) { } + + /// + /// Initializes a new instance of the class. + /// + /// HTTP status code. + /// Error message. + /// Error content. + /// HTTP Headers. + /// The exception that caused this error. + public ApiException(int errorCode, string message, object errorContent, Multimap headers, Exception innerException) : base(message, innerException) { this.ErrorCode = errorCode; this.ErrorContent = errorContent; diff --git a/samples/client/petstore/csharp/httpclient/net10/Petstore/src/Org.OpenAPITools/Client/ApiException.cs b/samples/client/petstore/csharp/httpclient/net10/Petstore/src/Org.OpenAPITools/Client/ApiException.cs index 67d9888d6a3c..7719824f0298 100644 --- a/samples/client/petstore/csharp/httpclient/net10/Petstore/src/Org.OpenAPITools/Client/ApiException.cs +++ b/samples/client/petstore/csharp/httpclient/net10/Petstore/src/Org.OpenAPITools/Client/ApiException.cs @@ -57,7 +57,17 @@ public ApiException(int errorCode, string message) : base(message) /// Error message. /// Error content. /// HTTP Headers. - public ApiException(int errorCode, string message, object errorContent = null, Multimap headers = null) : base(message) + public ApiException(int errorCode, string message, object errorContent = null, Multimap headers = null) : this(errorCode, message, errorContent, headers, null) { } + + /// + /// Initializes a new instance of the class. + /// + /// HTTP status code. + /// Error message. + /// Error content. + /// HTTP Headers. + /// The exception that caused this error. + public ApiException(int errorCode, string message, object errorContent, Multimap headers, Exception innerException) : base(message, innerException) { this.ErrorCode = errorCode; this.ErrorContent = errorContent; diff --git a/samples/client/petstore/csharp/httpclient/net9/Petstore-nonPublicApi/src/Org.OpenAPITools/Client/ApiException.cs b/samples/client/petstore/csharp/httpclient/net9/Petstore-nonPublicApi/src/Org.OpenAPITools/Client/ApiException.cs index a19e757f19ba..b41d02128238 100644 --- a/samples/client/petstore/csharp/httpclient/net9/Petstore-nonPublicApi/src/Org.OpenAPITools/Client/ApiException.cs +++ b/samples/client/petstore/csharp/httpclient/net9/Petstore-nonPublicApi/src/Org.OpenAPITools/Client/ApiException.cs @@ -57,7 +57,17 @@ public ApiException(int errorCode, string message) : base(message) /// Error message. /// Error content. /// HTTP Headers. - public ApiException(int errorCode, string message, object errorContent = null, Multimap headers = null) : base(message) + public ApiException(int errorCode, string message, object errorContent = null, Multimap headers = null) : this(errorCode, message, errorContent, headers, null) { } + + /// + /// Initializes a new instance of the class. + /// + /// HTTP status code. + /// Error message. + /// Error content. + /// HTTP Headers. + /// The exception that caused this error. + public ApiException(int errorCode, string message, object errorContent, Multimap headers, Exception innerException) : base(message, innerException) { this.ErrorCode = errorCode; this.ErrorContent = errorContent; diff --git a/samples/client/petstore/csharp/httpclient/net9/Petstore/src/Org.OpenAPITools/Client/ApiException.cs b/samples/client/petstore/csharp/httpclient/net9/Petstore/src/Org.OpenAPITools/Client/ApiException.cs index 67d9888d6a3c..7719824f0298 100644 --- a/samples/client/petstore/csharp/httpclient/net9/Petstore/src/Org.OpenAPITools/Client/ApiException.cs +++ b/samples/client/petstore/csharp/httpclient/net9/Petstore/src/Org.OpenAPITools/Client/ApiException.cs @@ -57,7 +57,17 @@ public ApiException(int errorCode, string message) : base(message) /// Error message. /// Error content. /// HTTP Headers. - public ApiException(int errorCode, string message, object errorContent = null, Multimap headers = null) : base(message) + public ApiException(int errorCode, string message, object errorContent = null, Multimap headers = null) : this(errorCode, message, errorContent, headers, null) { } + + /// + /// Initializes a new instance of the class. + /// + /// HTTP status code. + /// Error message. + /// Error content. + /// HTTP Headers. + /// The exception that caused this error. + public ApiException(int errorCode, string message, object errorContent, Multimap headers, Exception innerException) : base(message, innerException) { this.ErrorCode = errorCode; this.ErrorContent = errorContent; diff --git a/samples/client/petstore/csharp/httpclient/standard2.0/Petstore/src/Org.OpenAPITools/Client/ApiException.cs b/samples/client/petstore/csharp/httpclient/standard2.0/Petstore/src/Org.OpenAPITools/Client/ApiException.cs index 67d9888d6a3c..7719824f0298 100644 --- a/samples/client/petstore/csharp/httpclient/standard2.0/Petstore/src/Org.OpenAPITools/Client/ApiException.cs +++ b/samples/client/petstore/csharp/httpclient/standard2.0/Petstore/src/Org.OpenAPITools/Client/ApiException.cs @@ -57,7 +57,17 @@ public ApiException(int errorCode, string message) : base(message) /// Error message. /// Error content. /// HTTP Headers. - public ApiException(int errorCode, string message, object errorContent = null, Multimap headers = null) : base(message) + public ApiException(int errorCode, string message, object errorContent = null, Multimap headers = null) : this(errorCode, message, errorContent, headers, null) { } + + /// + /// Initializes a new instance of the class. + /// + /// HTTP status code. + /// Error message. + /// Error content. + /// HTTP Headers. + /// The exception that caused this error. + public ApiException(int errorCode, string message, object errorContent, Multimap headers, Exception innerException) : base(message, innerException) { this.ErrorCode = errorCode; this.ErrorContent = errorContent; diff --git a/samples/client/petstore/csharp/restsharp/net10/EnumMappings/src/Org.OpenAPITools/Client/ApiException.cs b/samples/client/petstore/csharp/restsharp/net10/EnumMappings/src/Org.OpenAPITools/Client/ApiException.cs index dcc378ad208d..8a7921bd6ff2 100644 --- a/samples/client/petstore/csharp/restsharp/net10/EnumMappings/src/Org.OpenAPITools/Client/ApiException.cs +++ b/samples/client/petstore/csharp/restsharp/net10/EnumMappings/src/Org.OpenAPITools/Client/ApiException.cs @@ -57,7 +57,17 @@ public ApiException(int errorCode, string message) : base(message) /// Error message. /// Error content. /// HTTP Headers. - public ApiException(int errorCode, string message, object errorContent = null, Multimap headers = null) : base(message) + public ApiException(int errorCode, string message, object errorContent = null, Multimap headers = null) : this(errorCode, message, errorContent, headers, null) { } + + /// + /// Initializes a new instance of the class. + /// + /// HTTP status code. + /// Error message. + /// Error content. + /// HTTP Headers. + /// The exception that caused this error. + public ApiException(int errorCode, string message, object errorContent, Multimap headers, Exception innerException) : base(message, innerException) { this.ErrorCode = errorCode; this.ErrorContent = errorContent; diff --git a/samples/client/petstore/csharp/restsharp/net10/Petstore/src/Org.OpenAPITools/Client/ApiException.cs b/samples/client/petstore/csharp/restsharp/net10/Petstore/src/Org.OpenAPITools/Client/ApiException.cs index 67d9888d6a3c..7719824f0298 100644 --- a/samples/client/petstore/csharp/restsharp/net10/Petstore/src/Org.OpenAPITools/Client/ApiException.cs +++ b/samples/client/petstore/csharp/restsharp/net10/Petstore/src/Org.OpenAPITools/Client/ApiException.cs @@ -57,7 +57,17 @@ public ApiException(int errorCode, string message) : base(message) /// Error message. /// Error content. /// HTTP Headers. - public ApiException(int errorCode, string message, object errorContent = null, Multimap headers = null) : base(message) + public ApiException(int errorCode, string message, object errorContent = null, Multimap headers = null) : this(errorCode, message, errorContent, headers, null) { } + + /// + /// Initializes a new instance of the class. + /// + /// HTTP status code. + /// Error message. + /// Error content. + /// HTTP Headers. + /// The exception that caused this error. + public ApiException(int errorCode, string message, object errorContent, Multimap headers, Exception innerException) : base(message, innerException) { this.ErrorCode = errorCode; this.ErrorContent = errorContent; diff --git a/samples/client/petstore/csharp/restsharp/net4.7/MultipleFrameworks/src/Org.OpenAPITools/Client/ApiClient.cs b/samples/client/petstore/csharp/restsharp/net4.7/MultipleFrameworks/src/Org.OpenAPITools/Client/ApiClient.cs index b741a64994f9..200d5edb6387 100644 --- a/samples/client/petstore/csharp/restsharp/net4.7/MultipleFrameworks/src/Org.OpenAPITools/Client/ApiClient.cs +++ b/samples/client/petstore/csharp/restsharp/net4.7/MultipleFrameworks/src/Org.OpenAPITools/Client/ApiClient.cs @@ -497,7 +497,7 @@ private async Task> ExecClientAsync(FuncError message. /// Error content. /// HTTP Headers. - public ApiException(int errorCode, string message, object errorContent = null, Multimap headers = null) : base(message) + public ApiException(int errorCode, string message, object errorContent = null, Multimap headers = null) : this(errorCode, message, errorContent, headers, null) { } + + /// + /// Initializes a new instance of the class. + /// + /// HTTP status code. + /// Error message. + /// Error content. + /// HTTP Headers. + /// The exception that caused this error. + public ApiException(int errorCode, string message, object errorContent, Multimap headers, Exception innerException) : base(message, innerException) { this.ErrorCode = errorCode; this.ErrorContent = errorContent; diff --git a/samples/client/petstore/csharp/restsharp/net4.7/Petstore/src/Org.OpenAPITools/Client/ApiException.cs b/samples/client/petstore/csharp/restsharp/net4.7/Petstore/src/Org.OpenAPITools/Client/ApiException.cs index 67d9888d6a3c..7719824f0298 100644 --- a/samples/client/petstore/csharp/restsharp/net4.7/Petstore/src/Org.OpenAPITools/Client/ApiException.cs +++ b/samples/client/petstore/csharp/restsharp/net4.7/Petstore/src/Org.OpenAPITools/Client/ApiException.cs @@ -57,7 +57,17 @@ public ApiException(int errorCode, string message) : base(message) /// Error message. /// Error content. /// HTTP Headers. - public ApiException(int errorCode, string message, object errorContent = null, Multimap headers = null) : base(message) + public ApiException(int errorCode, string message, object errorContent = null, Multimap headers = null) : this(errorCode, message, errorContent, headers, null) { } + + /// + /// Initializes a new instance of the class. + /// + /// HTTP status code. + /// Error message. + /// Error content. + /// HTTP Headers. + /// The exception that caused this error. + public ApiException(int errorCode, string message, object errorContent, Multimap headers, Exception innerException) : base(message, innerException) { this.ErrorCode = errorCode; this.ErrorContent = errorContent; diff --git a/samples/client/petstore/csharp/restsharp/net4.8/Petstore/src/Org.OpenAPITools/Client/ApiException.cs b/samples/client/petstore/csharp/restsharp/net4.8/Petstore/src/Org.OpenAPITools/Client/ApiException.cs index 67d9888d6a3c..7719824f0298 100644 --- a/samples/client/petstore/csharp/restsharp/net4.8/Petstore/src/Org.OpenAPITools/Client/ApiException.cs +++ b/samples/client/petstore/csharp/restsharp/net4.8/Petstore/src/Org.OpenAPITools/Client/ApiException.cs @@ -57,7 +57,17 @@ public ApiException(int errorCode, string message) : base(message) /// Error message. /// Error content. /// HTTP Headers. - public ApiException(int errorCode, string message, object errorContent = null, Multimap headers = null) : base(message) + public ApiException(int errorCode, string message, object errorContent = null, Multimap headers = null) : this(errorCode, message, errorContent, headers, null) { } + + /// + /// Initializes a new instance of the class. + /// + /// HTTP status code. + /// Error message. + /// Error content. + /// HTTP Headers. + /// The exception that caused this error. + public ApiException(int errorCode, string message, object errorContent, Multimap headers, Exception innerException) : base(message, innerException) { this.ErrorCode = errorCode; this.ErrorContent = errorContent; diff --git a/samples/client/petstore/csharp/restsharp/net8/EnumMappings/src/Org.OpenAPITools/Client/ApiException.cs b/samples/client/petstore/csharp/restsharp/net8/EnumMappings/src/Org.OpenAPITools/Client/ApiException.cs index 67d9888d6a3c..7719824f0298 100644 --- a/samples/client/petstore/csharp/restsharp/net8/EnumMappings/src/Org.OpenAPITools/Client/ApiException.cs +++ b/samples/client/petstore/csharp/restsharp/net8/EnumMappings/src/Org.OpenAPITools/Client/ApiException.cs @@ -57,7 +57,17 @@ public ApiException(int errorCode, string message) : base(message) /// Error message. /// Error content. /// HTTP Headers. - public ApiException(int errorCode, string message, object errorContent = null, Multimap headers = null) : base(message) + public ApiException(int errorCode, string message, object errorContent = null, Multimap headers = null) : this(errorCode, message, errorContent, headers, null) { } + + /// + /// Initializes a new instance of the class. + /// + /// HTTP status code. + /// Error message. + /// Error content. + /// HTTP Headers. + /// The exception that caused this error. + public ApiException(int errorCode, string message, object errorContent, Multimap headers, Exception innerException) : base(message, innerException) { this.ErrorCode = errorCode; this.ErrorContent = errorContent; diff --git a/samples/client/petstore/csharp/restsharp/net8/ParameterMappings/src/Org.OpenAPITools/Client/ApiException.cs b/samples/client/petstore/csharp/restsharp/net8/ParameterMappings/src/Org.OpenAPITools/Client/ApiException.cs index 3f66fe3d1987..f4c0e147249e 100644 --- a/samples/client/petstore/csharp/restsharp/net8/ParameterMappings/src/Org.OpenAPITools/Client/ApiException.cs +++ b/samples/client/petstore/csharp/restsharp/net8/ParameterMappings/src/Org.OpenAPITools/Client/ApiException.cs @@ -57,7 +57,17 @@ public ApiException(int errorCode, string message) : base(message) /// Error message. /// Error content. /// HTTP Headers. - public ApiException(int errorCode, string message, object errorContent = null, Multimap headers = null) : base(message) + public ApiException(int errorCode, string message, object errorContent = null, Multimap headers = null) : this(errorCode, message, errorContent, headers, null) { } + + /// + /// Initializes a new instance of the class. + /// + /// HTTP status code. + /// Error message. + /// Error content. + /// HTTP Headers. + /// The exception that caused this error. + public ApiException(int errorCode, string message, object errorContent, Multimap headers, Exception innerException) : base(message, innerException) { this.ErrorCode = errorCode; this.ErrorContent = errorContent; diff --git a/samples/client/petstore/csharp/restsharp/net8/Petstore/src/Org.OpenAPITools/Client/ApiException.cs b/samples/client/petstore/csharp/restsharp/net8/Petstore/src/Org.OpenAPITools/Client/ApiException.cs index 67d9888d6a3c..7719824f0298 100644 --- a/samples/client/petstore/csharp/restsharp/net8/Petstore/src/Org.OpenAPITools/Client/ApiException.cs +++ b/samples/client/petstore/csharp/restsharp/net8/Petstore/src/Org.OpenAPITools/Client/ApiException.cs @@ -57,7 +57,17 @@ public ApiException(int errorCode, string message) : base(message) /// Error message. /// Error content. /// HTTP Headers. - public ApiException(int errorCode, string message, object errorContent = null, Multimap headers = null) : base(message) + public ApiException(int errorCode, string message, object errorContent = null, Multimap headers = null) : this(errorCode, message, errorContent, headers, null) { } + + /// + /// Initializes a new instance of the class. + /// + /// HTTP status code. + /// Error message. + /// Error content. + /// HTTP Headers. + /// The exception that caused this error. + public ApiException(int errorCode, string message, object errorContent, Multimap headers, Exception innerException) : base(message, innerException) { this.ErrorCode = errorCode; this.ErrorContent = errorContent; diff --git a/samples/client/petstore/csharp/restsharp/net8/UseDateTimeForDate/src/Org.OpenAPITools/Client/ApiException.cs b/samples/client/petstore/csharp/restsharp/net8/UseDateTimeForDate/src/Org.OpenAPITools/Client/ApiException.cs index 64872847b838..d1f638b2301c 100644 --- a/samples/client/petstore/csharp/restsharp/net8/UseDateTimeForDate/src/Org.OpenAPITools/Client/ApiException.cs +++ b/samples/client/petstore/csharp/restsharp/net8/UseDateTimeForDate/src/Org.OpenAPITools/Client/ApiException.cs @@ -57,7 +57,17 @@ public ApiException(int errorCode, string message) : base(message) /// Error message. /// Error content. /// HTTP Headers. - public ApiException(int errorCode, string message, object errorContent = null, Multimap headers = null) : base(message) + public ApiException(int errorCode, string message, object errorContent = null, Multimap headers = null) : this(errorCode, message, errorContent, headers, null) { } + + /// + /// Initializes a new instance of the class. + /// + /// HTTP status code. + /// Error message. + /// Error content. + /// HTTP Headers. + /// The exception that caused this error. + public ApiException(int errorCode, string message, object errorContent, Multimap headers, Exception innerException) : base(message, innerException) { this.ErrorCode = errorCode; this.ErrorContent = errorContent; diff --git a/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/src/Org.OpenAPITools/Client/ApiException.cs b/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/src/Org.OpenAPITools/Client/ApiException.cs index dcc378ad208d..8a7921bd6ff2 100644 --- a/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/src/Org.OpenAPITools/Client/ApiException.cs +++ b/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/src/Org.OpenAPITools/Client/ApiException.cs @@ -57,7 +57,17 @@ public ApiException(int errorCode, string message) : base(message) /// Error message. /// Error content. /// HTTP Headers. - public ApiException(int errorCode, string message, object errorContent = null, Multimap headers = null) : base(message) + public ApiException(int errorCode, string message, object errorContent = null, Multimap headers = null) : this(errorCode, message, errorContent, headers, null) { } + + /// + /// Initializes a new instance of the class. + /// + /// HTTP status code. + /// Error message. + /// Error content. + /// HTTP Headers. + /// The exception that caused this error. + public ApiException(int errorCode, string message, object errorContent, Multimap headers, Exception innerException) : base(message, innerException) { this.ErrorCode = errorCode; this.ErrorContent = errorContent; diff --git a/samples/client/petstore/csharp/restsharp/net9/EnumMappings/src/Org.OpenAPITools/Client/ApiException.cs b/samples/client/petstore/csharp/restsharp/net9/EnumMappings/src/Org.OpenAPITools/Client/ApiException.cs index 67d9888d6a3c..7719824f0298 100644 --- a/samples/client/petstore/csharp/restsharp/net9/EnumMappings/src/Org.OpenAPITools/Client/ApiException.cs +++ b/samples/client/petstore/csharp/restsharp/net9/EnumMappings/src/Org.OpenAPITools/Client/ApiException.cs @@ -57,7 +57,17 @@ public ApiException(int errorCode, string message) : base(message) /// Error message. /// Error content. /// HTTP Headers. - public ApiException(int errorCode, string message, object errorContent = null, Multimap headers = null) : base(message) + public ApiException(int errorCode, string message, object errorContent = null, Multimap headers = null) : this(errorCode, message, errorContent, headers, null) { } + + /// + /// Initializes a new instance of the class. + /// + /// HTTP status code. + /// Error message. + /// Error content. + /// HTTP Headers. + /// The exception that caused this error. + public ApiException(int errorCode, string message, object errorContent, Multimap headers, Exception innerException) : base(message, innerException) { this.ErrorCode = errorCode; this.ErrorContent = errorContent; diff --git a/samples/client/petstore/csharp/restsharp/standard2.0/ConditionalSerialization/src/Org.OpenAPITools/Client/ApiException.cs b/samples/client/petstore/csharp/restsharp/standard2.0/ConditionalSerialization/src/Org.OpenAPITools/Client/ApiException.cs index 67d9888d6a3c..7719824f0298 100644 --- a/samples/client/petstore/csharp/restsharp/standard2.0/ConditionalSerialization/src/Org.OpenAPITools/Client/ApiException.cs +++ b/samples/client/petstore/csharp/restsharp/standard2.0/ConditionalSerialization/src/Org.OpenAPITools/Client/ApiException.cs @@ -57,7 +57,17 @@ public ApiException(int errorCode, string message) : base(message) /// Error message. /// Error content. /// HTTP Headers. - public ApiException(int errorCode, string message, object errorContent = null, Multimap headers = null) : base(message) + public ApiException(int errorCode, string message, object errorContent = null, Multimap headers = null) : this(errorCode, message, errorContent, headers, null) { } + + /// + /// Initializes a new instance of the class. + /// + /// HTTP status code. + /// Error message. + /// Error content. + /// HTTP Headers. + /// The exception that caused this error. + public ApiException(int errorCode, string message, object errorContent, Multimap headers, Exception innerException) : base(message, innerException) { this.ErrorCode = errorCode; this.ErrorContent = errorContent; diff --git a/samples/client/petstore/csharp/restsharp/standard2.0/Petstore/src/Org.OpenAPITools/Client/ApiException.cs b/samples/client/petstore/csharp/restsharp/standard2.0/Petstore/src/Org.OpenAPITools/Client/ApiException.cs index 67d9888d6a3c..7719824f0298 100644 --- a/samples/client/petstore/csharp/restsharp/standard2.0/Petstore/src/Org.OpenAPITools/Client/ApiException.cs +++ b/samples/client/petstore/csharp/restsharp/standard2.0/Petstore/src/Org.OpenAPITools/Client/ApiException.cs @@ -57,7 +57,17 @@ public ApiException(int errorCode, string message) : base(message) /// Error message. /// Error content. /// HTTP Headers. - public ApiException(int errorCode, string message, object errorContent = null, Multimap headers = null) : base(message) + public ApiException(int errorCode, string message, object errorContent = null, Multimap headers = null) : this(errorCode, message, errorContent, headers, null) { } + + /// + /// Initializes a new instance of the class. + /// + /// HTTP status code. + /// Error message. + /// Error content. + /// HTTP Headers. + /// The exception that caused this error. + public ApiException(int errorCode, string message, object errorContent, Multimap headers, Exception innerException) : base(message, innerException) { this.ErrorCode = errorCode; this.ErrorContent = errorContent; diff --git a/samples/client/petstore/csharp/unityWebRequest/net10/Petstore/src/Org.OpenAPITools/Client/ApiException.cs b/samples/client/petstore/csharp/unityWebRequest/net10/Petstore/src/Org.OpenAPITools/Client/ApiException.cs index 67d9888d6a3c..7719824f0298 100644 --- a/samples/client/petstore/csharp/unityWebRequest/net10/Petstore/src/Org.OpenAPITools/Client/ApiException.cs +++ b/samples/client/petstore/csharp/unityWebRequest/net10/Petstore/src/Org.OpenAPITools/Client/ApiException.cs @@ -57,7 +57,17 @@ public ApiException(int errorCode, string message) : base(message) /// Error message. /// Error content. /// HTTP Headers. - public ApiException(int errorCode, string message, object errorContent = null, Multimap headers = null) : base(message) + public ApiException(int errorCode, string message, object errorContent = null, Multimap headers = null) : this(errorCode, message, errorContent, headers, null) { } + + /// + /// Initializes a new instance of the class. + /// + /// HTTP status code. + /// Error message. + /// Error content. + /// HTTP Headers. + /// The exception that caused this error. + public ApiException(int errorCode, string message, object errorContent, Multimap headers, Exception innerException) : base(message, innerException) { this.ErrorCode = errorCode; this.ErrorContent = errorContent; diff --git a/samples/client/petstore/csharp/unityWebRequest/net9/Petstore/src/Org.OpenAPITools/Client/ApiException.cs b/samples/client/petstore/csharp/unityWebRequest/net9/Petstore/src/Org.OpenAPITools/Client/ApiException.cs index 67d9888d6a3c..7719824f0298 100644 --- a/samples/client/petstore/csharp/unityWebRequest/net9/Petstore/src/Org.OpenAPITools/Client/ApiException.cs +++ b/samples/client/petstore/csharp/unityWebRequest/net9/Petstore/src/Org.OpenAPITools/Client/ApiException.cs @@ -57,7 +57,17 @@ public ApiException(int errorCode, string message) : base(message) /// Error message. /// Error content. /// HTTP Headers. - public ApiException(int errorCode, string message, object errorContent = null, Multimap headers = null) : base(message) + public ApiException(int errorCode, string message, object errorContent = null, Multimap headers = null) : this(errorCode, message, errorContent, headers, null) { } + + /// + /// Initializes a new instance of the class. + /// + /// HTTP status code. + /// Error message. + /// Error content. + /// HTTP Headers. + /// The exception that caused this error. + public ApiException(int errorCode, string message, object errorContent, Multimap headers, Exception innerException) : base(message, innerException) { this.ErrorCode = errorCode; this.ErrorContent = errorContent; diff --git a/samples/client/petstore/csharp/unityWebRequest/standard2.0/Petstore/src/Org.OpenAPITools/Client/ApiException.cs b/samples/client/petstore/csharp/unityWebRequest/standard2.0/Petstore/src/Org.OpenAPITools/Client/ApiException.cs index 67d9888d6a3c..7719824f0298 100644 --- a/samples/client/petstore/csharp/unityWebRequest/standard2.0/Petstore/src/Org.OpenAPITools/Client/ApiException.cs +++ b/samples/client/petstore/csharp/unityWebRequest/standard2.0/Petstore/src/Org.OpenAPITools/Client/ApiException.cs @@ -57,7 +57,17 @@ public ApiException(int errorCode, string message) : base(message) /// Error message. /// Error content. /// HTTP Headers. - public ApiException(int errorCode, string message, object errorContent = null, Multimap headers = null) : base(message) + public ApiException(int errorCode, string message, object errorContent = null, Multimap headers = null) : this(errorCode, message, errorContent, headers, null) { } + + /// + /// Initializes a new instance of the class. + /// + /// HTTP status code. + /// Error message. + /// Error content. + /// HTTP Headers. + /// The exception that caused this error. + public ApiException(int errorCode, string message, object errorContent, Multimap headers, Exception innerException) : base(message, innerException) { this.ErrorCode = errorCode; this.ErrorContent = errorContent; From bbb5cbf2adf4ebb92f12944b739c3cedc0d73987 Mon Sep 17 00:00:00 2001 From: Marcin Szopa Date: Mon, 12 Oct 2026 13:03:35 +0200 Subject: [PATCH 3/3] [csharp][restsharp] Add throwOnAnyError tests to the MultipleFrameworks sample Transport failure and an unparseable 2xx body must surface as ApiException with status 0 / the real status, the body, and the original exception as InnerException. Both fail against the previous ThrowOnAnyError wiring. Co-authored-by: mrd4rkne --- .../Client/ThrowOnAnyErrorTests.cs | 59 +++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 samples/client/petstore/csharp/restsharp/net4.7/MultipleFrameworks/src/Org.OpenAPITools.Test/Client/ThrowOnAnyErrorTests.cs diff --git a/samples/client/petstore/csharp/restsharp/net4.7/MultipleFrameworks/src/Org.OpenAPITools.Test/Client/ThrowOnAnyErrorTests.cs b/samples/client/petstore/csharp/restsharp/net4.7/MultipleFrameworks/src/Org.OpenAPITools.Test/Client/ThrowOnAnyErrorTests.cs new file mode 100644 index 000000000000..1860dd4f7582 --- /dev/null +++ b/samples/client/petstore/csharp/restsharp/net4.7/MultipleFrameworks/src/Org.OpenAPITools.Test/Client/ThrowOnAnyErrorTests.cs @@ -0,0 +1,59 @@ +using System.Net; +using System.Net.Http; +using System.Net.Sockets; +using System.Text; +using System.Threading.Tasks; +using Org.OpenAPITools.Api; +using Org.OpenAPITools.Client; +using Xunit; + +namespace Org.OpenAPITools.Test.Client +{ + public sealed class ThrowOnAnyErrorTests + { + [Fact] + public void TransportFailure_ThrowsApiExceptionWithStatusZero() + { + var api = new PetApi("http://127.0.0.1:" + FreePort()); + + var ex = Assert.Throws(() => api.GetPetById(1)); + + Assert.Equal(0, ex.ErrorCode); + Assert.IsType(ex.InnerException); + } + + [Fact] + public void MalformedBody_ThrowsApiExceptionWithHttpStatus() + { + var port = FreePort(); + using (var server = new HttpListener()) + { + server.Prefixes.Add("http://127.0.0.1:" + port + "/"); + server.Start(); + Task.Run(() => + { + var ctx = server.GetContext(); + var body = Encoding.UTF8.GetBytes("not json"); + ctx.Response.ContentType = "application/json"; + ctx.Response.OutputStream.Write(body, 0, body.Length); + ctx.Response.Close(); + }); + var api = new PetApi("http://127.0.0.1:" + port); + + var ex = Assert.Throws(() => api.GetPetById(1)); + + Assert.Equal(200, ex.ErrorCode); + Assert.Equal("not json", ex.ErrorContent); + } + } + + private static int FreePort() + { + var listener = new TcpListener(IPAddress.Loopback, 0); + listener.Start(); + var port = ((IPEndPoint)listener.LocalEndpoint).Port; + listener.Stop(); + return port; + } + } +}