diff --git a/.github/workflows/samples-dotnet8-client.yaml b/.github/workflows/samples-dotnet8-client.yaml
index a5cec7eab10..4bb9e894bdd 100644
--- a/.github/workflows/samples-dotnet8-client.yaml
+++ b/.github/workflows/samples-dotnet8-client.yaml
@@ -16,6 +16,7 @@ jobs:
matrix:
sample:
- samples/client/petstore/csharp/restsharp/net8/ParameterMappings/
+ - samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/
steps:
- uses: actions/checkout@v4
- uses: actions/setup-dotnet@v4.3.0
diff --git a/bin/configs/csharp-restsharp-useVirtualForHooks.yaml b/bin/configs/csharp-restsharp-useVirtualForHooks.yaml
new file mode 100644
index 00000000000..cc1675f5518
--- /dev/null
+++ b/bin/configs/csharp-restsharp-useVirtualForHooks.yaml
@@ -0,0 +1,10 @@
+# for .net standard
+generatorName: csharp
+library: restsharp
+outputDir: samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks
+inputSpec: modules/openapi-generator/src/test/resources/3_0/petstore-addpet-only.yaml
+templateDir: modules/openapi-generator/src/main/resources/csharp
+additionalProperties:
+ packageGuid: '{D0A67E81-4061-48EB-B4B8-C73BDF8B2D95}'
+ targetFramework: net8.0
+ useVirtualForHooks: true
diff --git a/docs/generators/csharp.md b/docs/generators/csharp.md
index 5b131b6e67c..8f9ed666354 100644
--- a/docs/generators/csharp.md
+++ b/docs/generators/csharp.md
@@ -54,6 +54,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|useIntForTimeout|Use int for Timeout (fall back to v7.9.0 templates). This option (for restsharp only) will be deprecated so please migrated to TimeSpan instead.| |false|
|useOneOfDiscriminatorLookup|Use the discriminator's mapping in oneOf to speed up the model lookup. IMPORTANT: Validation (e.g. one and only one match in oneOf's schemas) will be skipped.| |false|
|useSourceGeneration|Use source generation where available (only `generichost` library supports this option).| |false|
+|useVirtualForHooks|Generate code that exposes public virtual hooks on ApiClient to customize low-level HTTP requests (only `restsharp`. `httpclient` libraries support this option).| |false|
|validatable|Generates self-validatable models.| |true|
|zeroBasedEnums|Enumerations with string values will start from 0 when true, 1 when false. If not set, enumerations with string values will start from 0 if the first value is 'unknown', case insensitive.| |null|
diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenConstants.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenConstants.java
index 58a29c2d672..ae52412b7d2 100644
--- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenConstants.java
+++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenConstants.java
@@ -287,7 +287,7 @@ public class CodegenConstants {
public static final String SUPPORTS_ASYNC_DESC = "Generate code that supports async operations.";
public static final String USE_VIRTUAL_FOR_HOOKS = "useVirtualForHooks";
- public static final String USE_VIRTUAL_FOR_HOOKS_DESC = "Generate code that exposes public virtual hooks on ApiClient to customize low-level HTTP requests.";
+ public static final String USE_VIRTUAL_FOR_HOOKS_DESC = "Generate code that exposes public virtual hooks on ApiClient to customize low-level HTTP requests (only `restsharp`. `httpclient` libraries support this option).";
public static final String EXCLUDE_TESTS = "excludeTests";
public static final String EXCLUDE_TESTS_DESC = "Specifies that no tests are to be generated.";
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 46f51531eb4..4eb82fe1c84 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
@@ -357,6 +357,10 @@ public class CSharpClientCodegen extends AbstractCSharpCodegen {
"Use source generation where available (only `generichost` library supports this option).",
this.getUseSourceGeneration());
+ addSwitch(CodegenConstants.USE_VIRTUAL_FOR_HOOKS,
+ CodegenConstants.USE_VIRTUAL_FOR_HOOKS_DESC,
+ this.useVirtualForHooks);
+
supportedLibraries.put(GENERICHOST, "HttpClient, Generic Host integration, and System.Text.Json (https://docs.microsoft.com/en-us/dotnet/core/extensions/generic-host)");
supportedLibraries.put(HTTPCLIENT, "HttpClient and Newtonsoft (https://docs.microsoft.com/en-us/dotnet/api/system.net.http.httpclient) "
+ "(Experimental. Subject to breaking changes without notice.)");
diff --git a/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/.gitignore b/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/.gitignore
new file mode 100644
index 00000000000..1ee53850b84
--- /dev/null
+++ b/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/.gitignore
@@ -0,0 +1,362 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+
+# User-specific files
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Mono auto generated files
+mono_crash.*
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+[Ww][Ii][Nn]32/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+[Ll]ogs/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUnit
+*.VisualState.xml
+TestResult.xml
+nunit-*.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# ASP.NET Scaffolding
+ScaffoldingReadMe.txt
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Coverlet is a free, cross platform Code Coverage Tool
+coverage*.json
+coverage*.xml
+coverage*.info
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# NuGet Symbol Packages
+*.snupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+*.appxbundle
+*.appxupload
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!?*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+*- [Bb]ackup.rdl
+*- [Bb]ackup ([0-9]).rdl
+*- [Bb]ackup ([0-9][0-9]).rdl
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
+
+# BeatPulse healthcheck temp database
+healthchecksdb
+
+# Backup folder for Package Reference Convert tool in Visual Studio 2017
+MigrationBackup/
+
+# Ionide (cross platform F# VS Code tools) working folder
+.ionide/
+
+# Fody - auto-generated XML schema
+FodyWeavers.xsd
diff --git a/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/.openapi-generator-ignore b/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/.openapi-generator-ignore
new file mode 100644
index 00000000000..7484ee590a3
--- /dev/null
+++ b/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/.openapi-generator-ignore
@@ -0,0 +1,23 @@
+# OpenAPI Generator Ignore
+# Generated by openapi-generator https://github.com/openapitools/openapi-generator
+
+# Use this file to prevent files from being overwritten by the generator.
+# The patterns follow closely to .gitignore or .dockerignore.
+
+# As an example, the C# client generator defines ApiClient.cs.
+# You can make changes and tell OpenAPI Generator to ignore just this file by uncommenting the following line:
+#ApiClient.cs
+
+# You can match any string of characters against a directory, file or extension with a single asterisk (*):
+#foo/*/qux
+# The above matches foo/bar/qux and foo/baz/qux, but not foo/bar/baz/qux
+
+# You can recursively match patterns against a directory, file or extension with a double asterisk (**):
+#foo/**/qux
+# This matches foo/bar/qux, foo/baz/qux, and foo/bar/baz/qux
+
+# You can also negate patterns with an exclamation (!).
+# For example, you can ignore all files in a docs folder with the file extension .md:
+#docs/*.md
+# Then explicitly reverse the ignore rule for a single file:
+#!docs/README.md
diff --git a/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/.openapi-generator/FILES b/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/.openapi-generator/FILES
new file mode 100644
index 00000000000..e80c6162ae1
--- /dev/null
+++ b/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/.openapi-generator/FILES
@@ -0,0 +1,36 @@
+.gitignore
+Org.OpenAPITools.sln
+README.md
+api/openapi.yaml
+appveyor.yml
+docs/Category.md
+docs/Pet.md
+docs/PetApi.md
+docs/Tag.md
+git_push.sh
+src/Org.OpenAPITools.Test/Org.OpenAPITools.Test.csproj
+src/Org.OpenAPITools/Api/PetApi.cs
+src/Org.OpenAPITools/Client/ApiClient.cs
+src/Org.OpenAPITools/Client/ApiException.cs
+src/Org.OpenAPITools/Client/ApiResponse.cs
+src/Org.OpenAPITools/Client/Auth/OAuthAuthenticator.cs
+src/Org.OpenAPITools/Client/Auth/OAuthFlow.cs
+src/Org.OpenAPITools/Client/Auth/TokenResponse.cs
+src/Org.OpenAPITools/Client/ClientUtils.cs
+src/Org.OpenAPITools/Client/Configuration.cs
+src/Org.OpenAPITools/Client/ExceptionFactory.cs
+src/Org.OpenAPITools/Client/GlobalConfiguration.cs
+src/Org.OpenAPITools/Client/HttpMethod.cs
+src/Org.OpenAPITools/Client/IApiAccessor.cs
+src/Org.OpenAPITools/Client/IAsynchronousClient.cs
+src/Org.OpenAPITools/Client/IReadableConfiguration.cs
+src/Org.OpenAPITools/Client/ISynchronousClient.cs
+src/Org.OpenAPITools/Client/Multimap.cs
+src/Org.OpenAPITools/Client/OpenAPIDateConverter.cs
+src/Org.OpenAPITools/Client/RequestOptions.cs
+src/Org.OpenAPITools/Client/RetryConfiguration.cs
+src/Org.OpenAPITools/Model/AbstractOpenAPISchema.cs
+src/Org.OpenAPITools/Model/Category.cs
+src/Org.OpenAPITools/Model/Pet.cs
+src/Org.OpenAPITools/Model/Tag.cs
+src/Org.OpenAPITools/Org.OpenAPITools.csproj
diff --git a/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/.openapi-generator/VERSION b/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/.openapi-generator/VERSION
new file mode 100644
index 00000000000..96cfbb19ae2
--- /dev/null
+++ b/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/.openapi-generator/VERSION
@@ -0,0 +1 @@
+7.13.0-SNAPSHOT
diff --git a/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/Org.OpenAPITools.sln b/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/Org.OpenAPITools.sln
new file mode 100644
index 00000000000..ae868d9e2be
--- /dev/null
+++ b/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/Org.OpenAPITools.sln
@@ -0,0 +1,27 @@
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2012
+VisualStudioVersion = 12.0.0.0
+MinimumVisualStudioVersion = 10.0.0.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Org.OpenAPITools", "src\Org.OpenAPITools\Org.OpenAPITools.csproj", "{D0A67E81-4061-48EB-B4B8-C73BDF8B2D95}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Org.OpenAPITools.Test", "src\Org.OpenAPITools.Test\Org.OpenAPITools.Test.csproj", "{19F1DEBC-DE5E-4517-8062-F000CD499087}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {D0A67E81-4061-48EB-B4B8-C73BDF8B2D95}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {D0A67E81-4061-48EB-B4B8-C73BDF8B2D95}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {D0A67E81-4061-48EB-B4B8-C73BDF8B2D95}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {D0A67E81-4061-48EB-B4B8-C73BDF8B2D95}.Release|Any CPU.Build.0 = Release|Any CPU
+ {19F1DEBC-DE5E-4517-8062-F000CD499087}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {19F1DEBC-DE5E-4517-8062-F000CD499087}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {19F1DEBC-DE5E-4517-8062-F000CD499087}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {19F1DEBC-DE5E-4517-8062-F000CD499087}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
\ No newline at end of file
diff --git a/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/README.md b/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/README.md
new file mode 100644
index 00000000000..4712a5bd212
--- /dev/null
+++ b/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/README.md
@@ -0,0 +1,145 @@
+# Org.OpenAPITools - the C# library for the OpenAPI Petstore
+
+This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
+
+This C# SDK is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project:
+
+- API version: 1.0.0
+- SDK version: 1.0.0
+- Generator version: 7.13.0-SNAPSHOT
+- Build package: org.openapitools.codegen.languages.CSharpClientCodegen
+
+
+## Frameworks supported
+
+
+## Dependencies
+
+- [RestSharp](https://www.nuget.org/packages/RestSharp) - 112.0.0 or later
+- [Json.NET](https://www.nuget.org/packages/Newtonsoft.Json/) - 13.0.2 or later
+- [JsonSubTypes](https://www.nuget.org/packages/JsonSubTypes/) - 1.8.0 or later
+- [System.ComponentModel.Annotations](https://www.nuget.org/packages/System.ComponentModel.Annotations) - 5.0.0 or later
+
+The DLLs included in the package may not be the latest version. We recommend using [NuGet](https://docs.nuget.org/consume/installing-nuget) to obtain the latest version of the packages:
+```
+Install-Package RestSharp
+Install-Package Newtonsoft.Json
+Install-Package JsonSubTypes
+Install-Package System.ComponentModel.Annotations
+```
+
+NOTE: RestSharp versions greater than 105.1.0 have a bug which causes file uploads to fail. See [RestSharp#742](https://github.com/restsharp/RestSharp/issues/742).
+NOTE: RestSharp for .Net Core creates a new socket for each api call, which can lead to a socket exhaustion problem. See [RestSharp#1406](https://github.com/restsharp/RestSharp/issues/1406).
+
+
+## Installation
+Run the following command to generate the DLL
+- [Mac/Linux] `/bin/sh build.sh`
+- [Windows] `build.bat`
+
+Then include the DLL (under the `bin` folder) in the C# project, and use the namespaces:
+```csharp
+using Org.OpenAPITools.Api;
+using Org.OpenAPITools.Client;
+using Org.OpenAPITools.Model;
+```
+
+## Packaging
+
+A `.nuspec` is included with the project. You can follow the Nuget quickstart to [create](https://docs.microsoft.com/en-us/nuget/quickstart/create-and-publish-a-package#create-the-package) and [publish](https://docs.microsoft.com/en-us/nuget/quickstart/create-and-publish-a-package#publish-the-package) packages.
+
+This `.nuspec` uses placeholders from the `.csproj`, so build the `.csproj` directly:
+
+```
+nuget pack -Build -OutputDirectory out Org.OpenAPITools.csproj
+```
+
+Then, publish to a [local feed](https://docs.microsoft.com/en-us/nuget/hosting-packages/local-feeds) or [other host](https://docs.microsoft.com/en-us/nuget/hosting-packages/overview) and consume the new package via Nuget as usual.
+
+
+## Usage
+
+To use the API client with a HTTP proxy, setup a `System.Net.WebProxy`
+```csharp
+Configuration c = new Configuration();
+System.Net.WebProxy webProxy = new System.Net.WebProxy("http://myProxyUrl:80/");
+webProxy.Credentials = System.Net.CredentialCache.DefaultCredentials;
+c.Proxy = webProxy;
+```
+
+
+## Getting Started
+
+```csharp
+using System.Collections.Generic;
+using System.Diagnostics;
+using Org.OpenAPITools.Api;
+using Org.OpenAPITools.Client;
+using Org.OpenAPITools.Model;
+
+namespace Example
+{
+ public class Example
+ {
+ public static void Main()
+ {
+
+ Configuration config = new Configuration();
+ config.BasePath = "http://petstore.swagger.io/v2";
+ // Configure OAuth2 access token for authorization: petstore_auth
+ config.AccessToken = "YOUR_ACCESS_TOKEN";
+
+ var apiInstance = new PetApi(config);
+ var pet = new Pet(); // Pet | Pet object that needs to be added to the store
+
+ try
+ {
+ // Add a new pet to the store
+ Pet result = apiInstance.AddPet(pet);
+ Debug.WriteLine(result);
+ }
+ catch (ApiException e)
+ {
+ Debug.Print("Exception when calling PetApi.AddPet: " + e.Message );
+ Debug.Print("Status Code: "+ e.ErrorCode);
+ Debug.Print(e.StackTrace);
+ }
+
+ }
+ }
+}
+```
+
+
+## Documentation for API Endpoints
+
+All URIs are relative to *http://petstore.swagger.io/v2*
+
+Class | Method | HTTP request | Description
+------------ | ------------- | ------------- | -------------
+*PetApi* | [**AddPet**](docs/PetApi.md#addpet) | **POST** /pet | Add a new pet to the store
+
+
+
+## Documentation for Models
+
+ - [Model.Category](docs/Category.md)
+ - [Model.Pet](docs/Pet.md)
+ - [Model.Tag](docs/Tag.md)
+
+
+
+## Documentation for Authorization
+
+
+Authentication schemes defined for the API:
+
+### petstore_auth
+
+- **Type**: OAuth
+- **Flow**: implicit
+- **Authorization URL**: http://petstore.swagger.io/api/oauth/dialog
+- **Scopes**:
+ - write:pets: modify pets in your account
+ - read:pets: read your pets
+
diff --git a/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/api/openapi.yaml b/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/api/openapi.yaml
new file mode 100644
index 00000000000..8a5ffeb52ca
--- /dev/null
+++ b/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/api/openapi.yaml
@@ -0,0 +1,152 @@
+openapi: 3.0.0
+info:
+ description: "This is a sample server Petstore server. For this sample, you can\
+ \ use the api key `special-key` to test the authorization filters."
+ license:
+ name: Apache-2.0
+ url: https://www.apache.org/licenses/LICENSE-2.0.html
+ title: OpenAPI Petstore
+ version: 1.0.0
+externalDocs:
+ description: Find out more about Swagger
+ url: http://swagger.io
+servers:
+- url: http://petstore.swagger.io/v2
+tags:
+- description: Everything about your Pets
+ name: pet
+paths:
+ /pet:
+ post:
+ description: ""
+ operationId: addPet
+ requestBody:
+ $ref: '#/components/requestBodies/Pet'
+ responses:
+ "200":
+ content:
+ application/xml:
+ schema:
+ $ref: '#/components/schemas/Pet'
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Pet'
+ description: successful operation
+ "405":
+ description: Invalid input
+ security:
+ - petstore_auth:
+ - write:pets
+ - read:pets
+ summary: Add a new pet to the store
+ tags:
+ - pet
+components:
+ requestBodies:
+ Pet:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Pet'
+ application/xml:
+ schema:
+ $ref: '#/components/schemas/Pet'
+ description: Pet object that needs to be added to the store
+ required: true
+ schemas:
+ Category:
+ description: A category for a pet
+ example:
+ name: name
+ id: 6
+ properties:
+ id:
+ format: int64
+ type: integer
+ name:
+ pattern: "^[a-zA-Z0-9]+[a-zA-Z0-9\\.\\-_]*[a-zA-Z0-9]+$"
+ type: string
+ title: Pet category
+ type: object
+ xml:
+ name: Category
+ Tag:
+ description: A tag for a pet
+ example:
+ name: name
+ id: 1
+ properties:
+ id:
+ format: int64
+ type: integer
+ name:
+ type: string
+ title: Pet Tag
+ type: object
+ xml:
+ name: Tag
+ Pet:
+ description: A pet for sale in the pet store
+ example:
+ photoUrls:
+ - photoUrls
+ - photoUrls
+ name: doggie
+ id: 0
+ category:
+ name: name
+ id: 6
+ tags:
+ - name: name
+ id: 1
+ - name: name
+ id: 1
+ status: available
+ properties:
+ id:
+ format: int64
+ type: integer
+ category:
+ $ref: '#/components/schemas/Category'
+ name:
+ example: doggie
+ type: string
+ photoUrls:
+ items:
+ type: string
+ type: array
+ xml:
+ name: photoUrl
+ wrapped: true
+ tags:
+ items:
+ $ref: '#/components/schemas/Tag'
+ type: array
+ xml:
+ name: tag
+ wrapped: true
+ status:
+ deprecated: true
+ description: pet status in the store
+ enum:
+ - available
+ - pending
+ - sold
+ type: string
+ required:
+ - name
+ - photoUrls
+ title: a Pet
+ type: object
+ xml:
+ name: Pet
+ securitySchemes:
+ petstore_auth:
+ flows:
+ implicit:
+ authorizationUrl: http://petstore.swagger.io/api/oauth/dialog
+ scopes:
+ write:pets: modify pets in your account
+ read:pets: read your pets
+ type: oauth2
+
diff --git a/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/appveyor.yml b/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/appveyor.yml
new file mode 100644
index 00000000000..f76f63cee50
--- /dev/null
+++ b/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/appveyor.yml
@@ -0,0 +1,9 @@
+# auto-generated by OpenAPI Generator (https://github.com/OpenAPITools/openapi-generator)
+#
+image: Visual Studio 2019
+clone_depth: 1
+build_script:
+- dotnet build -c Release
+- dotnet test -c Release
+after_build:
+- dotnet pack .\src\Org.OpenAPITools\Org.OpenAPITools.csproj -o ../../output -c Release --no-build
diff --git a/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/docs/Category.md b/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/docs/Category.md
new file mode 100644
index 00000000000..64e7948bbc7
--- /dev/null
+++ b/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/docs/Category.md
@@ -0,0 +1,12 @@
+# Org.OpenAPITools.Model.Category
+A category for a pet
+
+## Properties
+
+Name | Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+**Id** | **long** | | [optional]
+**Name** | **string** | | [optional]
+
+[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
+
diff --git a/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/docs/Pet.md b/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/docs/Pet.md
new file mode 100644
index 00000000000..914a070b220
--- /dev/null
+++ b/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/docs/Pet.md
@@ -0,0 +1,16 @@
+# Org.OpenAPITools.Model.Pet
+A pet for sale in the pet store
+
+## Properties
+
+Name | Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+**Id** | **long** | | [optional]
+**Category** | [**Category**](Category.md) | | [optional]
+**Name** | **string** | |
+**PhotoUrls** | **List<string>** | |
+**Tags** | [**List<Tag>**](Tag.md) | | [optional]
+**Status** | **string** | pet status in the store | [optional]
+
+[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
+
diff --git a/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/docs/PetApi.md b/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/docs/PetApi.md
new file mode 100644
index 00000000000..150093927ed
--- /dev/null
+++ b/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/docs/PetApi.md
@@ -0,0 +1,101 @@
+# Org.OpenAPITools.Api.PetApi
+
+All URIs are relative to *http://petstore.swagger.io/v2*
+
+| Method | HTTP request | Description |
+|--------|--------------|-------------|
+| [**AddPet**](PetApi.md#addpet) | **POST** /pet | Add a new pet to the store |
+
+
+# **AddPet**
+> Pet AddPet (Pet pet)
+
+Add a new pet to the store
+
+### Example
+```csharp
+using System.Collections.Generic;
+using System.Diagnostics;
+using Org.OpenAPITools.Api;
+using Org.OpenAPITools.Client;
+using Org.OpenAPITools.Model;
+
+namespace Example
+{
+ public class AddPetExample
+ {
+ public static void Main()
+ {
+ Configuration config = new Configuration();
+ config.BasePath = "http://petstore.swagger.io/v2";
+ // Configure OAuth2 access token for authorization: petstore_auth
+ config.AccessToken = "YOUR_ACCESS_TOKEN";
+
+ var apiInstance = new PetApi(config);
+ var pet = new Pet(); // Pet | Pet object that needs to be added to the store
+
+ try
+ {
+ // Add a new pet to the store
+ Pet result = apiInstance.AddPet(pet);
+ Debug.WriteLine(result);
+ }
+ catch (ApiException e)
+ {
+ Debug.Print("Exception when calling PetApi.AddPet: " + e.Message);
+ Debug.Print("Status Code: " + e.ErrorCode);
+ Debug.Print(e.StackTrace);
+ }
+ }
+ }
+}
+```
+
+#### Using the AddPetWithHttpInfo variant
+This returns an ApiResponse object which contains the response data, status code and headers.
+
+```csharp
+try
+{
+ // Add a new pet to the store
+ ApiResponse response = apiInstance.AddPetWithHttpInfo(pet);
+ Debug.Write("Status Code: " + response.StatusCode);
+ Debug.Write("Response Headers: " + response.Headers);
+ Debug.Write("Response Body: " + response.Data);
+}
+catch (ApiException e)
+{
+ Debug.Print("Exception when calling PetApi.AddPetWithHttpInfo: " + e.Message);
+ Debug.Print("Status Code: " + e.ErrorCode);
+ Debug.Print(e.StackTrace);
+}
+```
+
+### Parameters
+
+| Name | Type | Description | Notes |
+|------|------|-------------|-------|
+| **pet** | [**Pet**](Pet.md) | Pet object that needs to be added to the store | |
+
+### Return type
+
+[**Pet**](Pet.md)
+
+### Authorization
+
+[petstore_auth](../README.md#petstore_auth)
+
+### HTTP request headers
+
+ - **Content-Type**: application/json, application/xml
+ - **Accept**: application/xml, application/json
+
+
+### HTTP response details
+| Status code | Description | Response headers |
+|-------------|-------------|------------------|
+| **200** | successful operation | - |
+| **405** | Invalid input | - |
+
+[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
+
diff --git a/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/docs/Tag.md b/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/docs/Tag.md
new file mode 100644
index 00000000000..14e602a9c11
--- /dev/null
+++ b/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/docs/Tag.md
@@ -0,0 +1,12 @@
+# Org.OpenAPITools.Model.Tag
+A tag for a pet
+
+## Properties
+
+Name | Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+**Id** | **long** | | [optional]
+**Name** | **string** | | [optional]
+
+[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
+
diff --git a/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/git_push.sh b/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/git_push.sh
new file mode 100644
index 00000000000..f53a75d4fab
--- /dev/null
+++ b/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/git_push.sh
@@ -0,0 +1,57 @@
+#!/bin/sh
+# ref: https://help.github.com/articles/adding-an-existing-project-to-github-using-the-command-line/
+#
+# Usage example: /bin/sh ./git_push.sh wing328 openapi-petstore-perl "minor update" "gitlab.com"
+
+git_user_id=$1
+git_repo_id=$2
+release_note=$3
+git_host=$4
+
+if [ "$git_host" = "" ]; then
+ git_host="github.com"
+ echo "[INFO] No command line input provided. Set \$git_host to $git_host"
+fi
+
+if [ "$git_user_id" = "" ]; then
+ git_user_id="GIT_USER_ID"
+ echo "[INFO] No command line input provided. Set \$git_user_id to $git_user_id"
+fi
+
+if [ "$git_repo_id" = "" ]; then
+ git_repo_id="GIT_REPO_ID"
+ echo "[INFO] No command line input provided. Set \$git_repo_id to $git_repo_id"
+fi
+
+if [ "$release_note" = "" ]; then
+ release_note="Minor update"
+ echo "[INFO] No command line input provided. Set \$release_note to $release_note"
+fi
+
+# Initialize the local directory as a Git repository
+git init
+
+# Adds the files in the local repository and stages them for commit.
+git add .
+
+# Commits the tracked changes and prepares them to be pushed to a remote repository.
+git commit -m "$release_note"
+
+# Sets the new remote
+git_remote=$(git remote)
+if [ "$git_remote" = "" ]; then # git remote not defined
+
+ if [ "$GIT_TOKEN" = "" ]; then
+ echo "[INFO] \$GIT_TOKEN (environment variable) is not set. Using the git credential in your environment."
+ git remote add origin https://${git_host}/${git_user_id}/${git_repo_id}.git
+ else
+ git remote add origin https://${git_user_id}:"${GIT_TOKEN}"@${git_host}/${git_user_id}/${git_repo_id}.git
+ fi
+
+fi
+
+git pull origin master
+
+# Pushes (Forces) the changes in the local repository up to the remote repository
+echo "Git pushing to https://${git_host}/${git_user_id}/${git_repo_id}.git"
+git push origin master 2>&1 | grep -v 'To https'
diff --git a/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/src/Org.OpenAPITools.Test/Api/PetApiTests.cs b/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/src/Org.OpenAPITools.Test/Api/PetApiTests.cs
new file mode 100644
index 00000000000..6ff7c900eac
--- /dev/null
+++ b/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/src/Org.OpenAPITools.Test/Api/PetApiTests.cs
@@ -0,0 +1,69 @@
+/*
+ * OpenAPI Petstore
+ *
+ * This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
+ *
+ * The version of the OpenAPI document: 1.0.0
+ * Generated by: https://github.com/openapitools/openapi-generator.git
+ */
+
+using System;
+using System.IO;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Linq;
+using System.Reflection;
+using RestSharp;
+using Xunit;
+
+using Org.OpenAPITools.Client;
+using Org.OpenAPITools.Api;
+// uncomment below to import models
+//using Org.OpenAPITools.Model;
+
+namespace Org.OpenAPITools.Test.Api
+{
+ ///
+ /// Class for testing PetApi
+ ///
+ ///
+ /// This file is automatically generated by OpenAPI Generator (https://openapi-generator.tech).
+ /// Please update the test case below to test the API endpoint.
+ ///
+ public class PetApiTests : IDisposable
+ {
+ private PetApi instance;
+
+ public PetApiTests()
+ {
+ instance = new PetApi();
+ }
+
+ public void Dispose()
+ {
+ // Cleanup when everything is done.
+ }
+
+ ///
+ /// Test an instance of PetApi
+ ///
+ [Fact]
+ public void InstanceTest()
+ {
+ // TODO uncomment below to test 'IsType' PetApi
+ //Assert.IsType(instance);
+ }
+
+ ///
+ /// Test AddPet
+ ///
+ [Fact]
+ public void AddPetTest()
+ {
+ // TODO uncomment below to test the method and replace null with proper value
+ //Pet pet = null;
+ //var response = instance.AddPet(pet);
+ //Assert.IsType(response);
+ }
+ }
+}
diff --git a/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/src/Org.OpenAPITools.Test/Model/CategoryTests.cs b/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/src/Org.OpenAPITools.Test/Model/CategoryTests.cs
new file mode 100644
index 00000000000..8c6fc5d10db
--- /dev/null
+++ b/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/src/Org.OpenAPITools.Test/Model/CategoryTests.cs
@@ -0,0 +1,75 @@
+/*
+ * OpenAPI Petstore
+ *
+ * This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
+ *
+ * The version of the OpenAPI document: 1.0.0
+ * Generated by: https://github.com/openapitools/openapi-generator.git
+ */
+
+
+using Xunit;
+
+using System;
+using System.Linq;
+using System.IO;
+using System.Collections.Generic;
+using Org.OpenAPITools.Model;
+using Org.OpenAPITools.Client;
+using System.Reflection;
+using Newtonsoft.Json;
+
+namespace Org.OpenAPITools.Test.Model
+{
+ ///
+ /// Class for testing Category
+ ///
+ ///
+ /// This file is automatically generated by OpenAPI Generator (https://openapi-generator.tech).
+ /// Please update the test case below to test the model.
+ ///
+ public class CategoryTests : IDisposable
+ {
+ // TODO uncomment below to declare an instance variable for Category
+ //private Category instance;
+
+ public CategoryTests()
+ {
+ // TODO uncomment below to create an instance of Category
+ //instance = new Category();
+ }
+
+ public void Dispose()
+ {
+ // Cleanup when everything is done.
+ }
+
+ ///
+ /// Test an instance of Category
+ ///
+ [Fact]
+ public void CategoryInstanceTest()
+ {
+ // TODO uncomment below to test "IsType" Category
+ //Assert.IsType(instance);
+ }
+
+ ///
+ /// Test the property 'Id'
+ ///
+ [Fact]
+ public void IdTest()
+ {
+ // TODO unit test for the property 'Id'
+ }
+
+ ///
+ /// Test the property 'Name'
+ ///
+ [Fact]
+ public void NameTest()
+ {
+ // TODO unit test for the property 'Name'
+ }
+ }
+}
diff --git a/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/src/Org.OpenAPITools.Test/Model/PetTests.cs b/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/src/Org.OpenAPITools.Test/Model/PetTests.cs
new file mode 100644
index 00000000000..1b7f6c02349
--- /dev/null
+++ b/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/src/Org.OpenAPITools.Test/Model/PetTests.cs
@@ -0,0 +1,111 @@
+/*
+ * OpenAPI Petstore
+ *
+ * This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
+ *
+ * The version of the OpenAPI document: 1.0.0
+ * Generated by: https://github.com/openapitools/openapi-generator.git
+ */
+
+
+using Xunit;
+
+using System;
+using System.Linq;
+using System.IO;
+using System.Collections.Generic;
+using Org.OpenAPITools.Model;
+using Org.OpenAPITools.Client;
+using System.Reflection;
+using Newtonsoft.Json;
+
+namespace Org.OpenAPITools.Test.Model
+{
+ ///
+ /// Class for testing Pet
+ ///
+ ///
+ /// This file is automatically generated by OpenAPI Generator (https://openapi-generator.tech).
+ /// Please update the test case below to test the model.
+ ///
+ public class PetTests : IDisposable
+ {
+ // TODO uncomment below to declare an instance variable for Pet
+ //private Pet instance;
+
+ public PetTests()
+ {
+ // TODO uncomment below to create an instance of Pet
+ //instance = new Pet();
+ }
+
+ public void Dispose()
+ {
+ // Cleanup when everything is done.
+ }
+
+ ///
+ /// Test an instance of Pet
+ ///
+ [Fact]
+ public void PetInstanceTest()
+ {
+ // TODO uncomment below to test "IsType" Pet
+ //Assert.IsType(instance);
+ }
+
+ ///
+ /// Test the property 'Id'
+ ///
+ [Fact]
+ public void IdTest()
+ {
+ // TODO unit test for the property 'Id'
+ }
+
+ ///
+ /// Test the property 'Category'
+ ///
+ [Fact]
+ public void CategoryTest()
+ {
+ // TODO unit test for the property 'Category'
+ }
+
+ ///
+ /// Test the property 'Name'
+ ///
+ [Fact]
+ public void NameTest()
+ {
+ // TODO unit test for the property 'Name'
+ }
+
+ ///
+ /// Test the property 'PhotoUrls'
+ ///
+ [Fact]
+ public void PhotoUrlsTest()
+ {
+ // TODO unit test for the property 'PhotoUrls'
+ }
+
+ ///
+ /// Test the property 'Tags'
+ ///
+ [Fact]
+ public void TagsTest()
+ {
+ // TODO unit test for the property 'Tags'
+ }
+
+ ///
+ /// Test the property 'Status'
+ ///
+ [Fact]
+ public void StatusTest()
+ {
+ // TODO unit test for the property 'Status'
+ }
+ }
+}
diff --git a/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/src/Org.OpenAPITools.Test/Model/TagTests.cs b/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/src/Org.OpenAPITools.Test/Model/TagTests.cs
new file mode 100644
index 00000000000..c994710b0e5
--- /dev/null
+++ b/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/src/Org.OpenAPITools.Test/Model/TagTests.cs
@@ -0,0 +1,75 @@
+/*
+ * OpenAPI Petstore
+ *
+ * This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
+ *
+ * The version of the OpenAPI document: 1.0.0
+ * Generated by: https://github.com/openapitools/openapi-generator.git
+ */
+
+
+using Xunit;
+
+using System;
+using System.Linq;
+using System.IO;
+using System.Collections.Generic;
+using Org.OpenAPITools.Model;
+using Org.OpenAPITools.Client;
+using System.Reflection;
+using Newtonsoft.Json;
+
+namespace Org.OpenAPITools.Test.Model
+{
+ ///
+ /// Class for testing Tag
+ ///
+ ///
+ /// This file is automatically generated by OpenAPI Generator (https://openapi-generator.tech).
+ /// Please update the test case below to test the model.
+ ///
+ public class TagTests : IDisposable
+ {
+ // TODO uncomment below to declare an instance variable for Tag
+ //private Tag instance;
+
+ public TagTests()
+ {
+ // TODO uncomment below to create an instance of Tag
+ //instance = new Tag();
+ }
+
+ public void Dispose()
+ {
+ // Cleanup when everything is done.
+ }
+
+ ///
+ /// Test an instance of Tag
+ ///
+ [Fact]
+ public void TagInstanceTest()
+ {
+ // TODO uncomment below to test "IsType" Tag
+ //Assert.IsType(instance);
+ }
+
+ ///
+ /// Test the property 'Id'
+ ///
+ [Fact]
+ public void IdTest()
+ {
+ // TODO unit test for the property 'Id'
+ }
+
+ ///
+ /// Test the property 'Name'
+ ///
+ [Fact]
+ public void NameTest()
+ {
+ // TODO unit test for the property 'Name'
+ }
+ }
+}
diff --git a/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/src/Org.OpenAPITools.Test/Org.OpenAPITools.Test.csproj b/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/src/Org.OpenAPITools.Test/Org.OpenAPITools.Test.csproj
new file mode 100644
index 00000000000..64ebed26518
--- /dev/null
+++ b/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/src/Org.OpenAPITools.Test/Org.OpenAPITools.Test.csproj
@@ -0,0 +1,20 @@
+
+
+
+ Org.OpenAPITools.Test
+ Org.OpenAPITools.Test
+ net8.0
+ false
+ annotations
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/src/Org.OpenAPITools/Api/PetApi.cs b/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/src/Org.OpenAPITools/Api/PetApi.cs
new file mode 100644
index 00000000000..dc8e64f72b9
--- /dev/null
+++ b/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/src/Org.OpenAPITools/Api/PetApi.cs
@@ -0,0 +1,388 @@
+/*
+ * OpenAPI Petstore
+ *
+ * This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
+ *
+ * The version of the OpenAPI document: 1.0.0
+ * Generated by: https://github.com/openapitools/openapi-generator.git
+ */
+
+
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Linq;
+using System.Net;
+using System.Net.Mime;
+using Org.OpenAPITools.Client;
+using Org.OpenAPITools.Client.Auth;
+using Org.OpenAPITools.Model;
+
+namespace Org.OpenAPITools.Api
+{
+
+ ///
+ /// Represents a collection of functions to interact with the API endpoints
+ ///
+ public interface IPetApiSync : IApiAccessor
+ {
+ #region Synchronous Operations
+ ///
+ /// Add a new pet to the store
+ ///
+ /// Thrown when fails to make API call
+ /// Pet object that needs to be added to the store
+ /// Index associated with the operation.
+ /// Pet
+ Pet AddPet(Pet pet, int operationIndex = 0);
+
+ ///
+ /// Add a new pet to the store
+ ///
+ ///
+ ///
+ ///
+ /// Thrown when fails to make API call
+ /// Pet object that needs to be added to the store
+ /// Index associated with the operation.
+ /// ApiResponse of Pet
+ ApiResponse AddPetWithHttpInfo(Pet pet, int operationIndex = 0);
+ #endregion Synchronous Operations
+ }
+
+ ///
+ /// Represents a collection of functions to interact with the API endpoints
+ ///
+ public interface IPetApiAsync : IApiAccessor
+ {
+ #region Asynchronous Operations
+ ///
+ /// Add a new pet to the store
+ ///
+ ///
+ ///
+ ///
+ /// Thrown when fails to make API call
+ /// Pet object that needs to be added to the store
+ /// Index associated with the operation.
+ /// Cancellation Token to cancel the request.
+ /// Task of Pet
+ System.Threading.Tasks.Task AddPetAsync(Pet pet, int operationIndex = 0, System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken));
+
+ ///
+ /// Add a new pet to the store
+ ///
+ ///
+ ///
+ ///
+ /// Thrown when fails to make API call
+ /// Pet object that needs to be added to the store
+ /// Index associated with the operation.
+ /// Cancellation Token to cancel the request.
+ /// Task of ApiResponse (Pet)
+ System.Threading.Tasks.Task> AddPetWithHttpInfoAsync(Pet pet, int operationIndex = 0, System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken));
+ #endregion Asynchronous Operations
+ }
+
+ ///
+ /// Represents a collection of functions to interact with the API endpoints
+ ///
+ public interface IPetApi : IPetApiSync, IPetApiAsync
+ {
+
+ }
+
+ ///
+ /// Represents a collection of functions to interact with the API endpoints
+ ///
+ public partial class PetApi : IPetApi
+ {
+ private Org.OpenAPITools.Client.ExceptionFactory _exceptionFactory = (name, response) => null;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ ///
+ public PetApi() : this((string)null)
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ ///
+ public PetApi(string basePath)
+ {
+ this.Configuration = Org.OpenAPITools.Client.Configuration.MergeConfigurations(
+ Org.OpenAPITools.Client.GlobalConfiguration.Instance,
+ new Org.OpenAPITools.Client.Configuration { BasePath = basePath }
+ );
+ this.Client = new Org.OpenAPITools.Client.ApiClient(this.Configuration.BasePath);
+ this.AsynchronousClient = new Org.OpenAPITools.Client.ApiClient(this.Configuration.BasePath);
+ this.ExceptionFactory = Org.OpenAPITools.Client.Configuration.DefaultExceptionFactory;
+ }
+
+ ///
+ /// Initializes a new instance of the class
+ /// using Configuration object
+ ///
+ /// An instance of Configuration
+ ///
+ public PetApi(Org.OpenAPITools.Client.Configuration configuration)
+ {
+ if (configuration == null) throw new ArgumentNullException("configuration");
+
+ this.Configuration = Org.OpenAPITools.Client.Configuration.MergeConfigurations(
+ Org.OpenAPITools.Client.GlobalConfiguration.Instance,
+ configuration
+ );
+ this.Client = new Org.OpenAPITools.Client.ApiClient(this.Configuration.BasePath);
+ this.AsynchronousClient = new Org.OpenAPITools.Client.ApiClient(this.Configuration.BasePath);
+ ExceptionFactory = Org.OpenAPITools.Client.Configuration.DefaultExceptionFactory;
+ }
+
+ ///
+ /// Initializes a new instance of the class
+ /// using a Configuration object and client instance.
+ ///
+ /// The client interface for synchronous API access.
+ /// The client interface for asynchronous API access.
+ /// The configuration object.
+ public PetApi(Org.OpenAPITools.Client.ISynchronousClient client, Org.OpenAPITools.Client.IAsynchronousClient asyncClient, Org.OpenAPITools.Client.IReadableConfiguration configuration)
+ {
+ if (client == null) throw new ArgumentNullException("client");
+ if (asyncClient == null) throw new ArgumentNullException("asyncClient");
+ if (configuration == null) throw new ArgumentNullException("configuration");
+
+ this.Client = client;
+ this.AsynchronousClient = asyncClient;
+ this.Configuration = configuration;
+ this.ExceptionFactory = Org.OpenAPITools.Client.Configuration.DefaultExceptionFactory;
+ }
+
+ ///
+ /// The client for accessing this underlying API asynchronously.
+ ///
+ public Org.OpenAPITools.Client.IAsynchronousClient AsynchronousClient { get; set; }
+
+ ///
+ /// The client for accessing this underlying API synchronously.
+ ///
+ public Org.OpenAPITools.Client.ISynchronousClient Client { get; set; }
+
+ ///
+ /// Gets the base path of the API client.
+ ///
+ /// The base path
+ public string GetBasePath()
+ {
+ return this.Configuration.BasePath;
+ }
+
+ ///
+ /// Gets or sets the configuration object
+ ///
+ /// An instance of the Configuration
+ public Org.OpenAPITools.Client.IReadableConfiguration Configuration { get; set; }
+
+ ///
+ /// Provides a factory method hook for the creation of exceptions.
+ ///
+ public Org.OpenAPITools.Client.ExceptionFactory ExceptionFactory
+ {
+ get
+ {
+ if (_exceptionFactory != null && _exceptionFactory.GetInvocationList().Length > 1)
+ {
+ throw new InvalidOperationException("Multicast delegate for ExceptionFactory is unsupported.");
+ }
+ return _exceptionFactory;
+ }
+ set { _exceptionFactory = value; }
+ }
+
+ ///
+ /// Add a new pet to the store
+ ///
+ /// Thrown when fails to make API call
+ /// Pet object that needs to be added to the store
+ /// Index associated with the operation.
+ /// Pet
+ public Pet AddPet(Pet pet, int operationIndex = 0)
+ {
+ Org.OpenAPITools.Client.ApiResponse localVarResponse = AddPetWithHttpInfo(pet);
+ return localVarResponse.Data;
+ }
+
+ ///
+ /// Add a new pet to the store
+ ///
+ /// Thrown when fails to make API call
+ /// Pet object that needs to be added to the store
+ /// Index associated with the operation.
+ /// ApiResponse of Pet
+ public Org.OpenAPITools.Client.ApiResponse AddPetWithHttpInfo(Pet pet, int operationIndex = 0)
+ {
+ // verify the required parameter 'pet' is set
+ if (pet == null)
+ {
+ throw new Org.OpenAPITools.Client.ApiException(400, "Missing required parameter 'pet' when calling PetApi->AddPet");
+ }
+
+ Org.OpenAPITools.Client.RequestOptions localVarRequestOptions = new Org.OpenAPITools.Client.RequestOptions();
+
+ string[] _contentTypes = new string[] {
+ "application/json",
+ "application/xml"
+ };
+
+ // to determine the Accept header
+ string[] _accepts = new string[] {
+ "application/xml",
+ "application/json"
+ };
+
+ var localVarContentType = Org.OpenAPITools.Client.ClientUtils.SelectHeaderContentType(_contentTypes);
+ var localVarMultipartFormData = localVarContentType == "multipart/form-data";
+ if (localVarContentType != null)
+ {
+ localVarRequestOptions.HeaderParameters.Add("Content-Type", localVarContentType);
+ }
+
+ var localVarAccept = Org.OpenAPITools.Client.ClientUtils.SelectHeaderAccept(_accepts);
+ if (localVarAccept != null)
+ {
+ localVarRequestOptions.HeaderParameters.Add("Accept", localVarAccept);
+ }
+
+ localVarRequestOptions.Data = pet;
+
+ localVarRequestOptions.Operation = "PetApi.AddPet";
+ localVarRequestOptions.OperationIndex = operationIndex;
+
+ // authentication (petstore_auth) required
+ // oauth required
+ if (!localVarRequestOptions.HeaderParameters.ContainsKey("Authorization"))
+ {
+ if (!string.IsNullOrEmpty(this.Configuration.AccessToken))
+ {
+ localVarRequestOptions.HeaderParameters.Add("Authorization", "Bearer " + this.Configuration.AccessToken);
+ }
+ else if (!string.IsNullOrEmpty(this.Configuration.OAuthTokenUrl) &&
+ !string.IsNullOrEmpty(this.Configuration.OAuthClientId) &&
+ !string.IsNullOrEmpty(this.Configuration.OAuthClientSecret) &&
+ this.Configuration.OAuthFlow != null)
+ {
+ localVarRequestOptions.OAuth = true;
+ }
+ }
+
+ // make the HTTP request
+ var localVarResponse = this.Client.Post("/pet", localVarRequestOptions, this.Configuration);
+ if (this.ExceptionFactory != null)
+ {
+ Exception _exception = this.ExceptionFactory("AddPet", localVarResponse);
+ if (_exception != null)
+ {
+ throw _exception;
+ }
+ }
+
+ return localVarResponse;
+ }
+
+ ///
+ /// Add a new pet to the store
+ ///
+ /// Thrown when fails to make API call
+ /// Pet object that needs to be added to the store
+ /// Index associated with the operation.
+ /// Cancellation Token to cancel the request.
+ /// Task of Pet
+ public async System.Threading.Tasks.Task AddPetAsync(Pet pet, int operationIndex = 0, System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken))
+ {
+ Org.OpenAPITools.Client.ApiResponse localVarResponse = await AddPetWithHttpInfoAsync(pet, operationIndex, cancellationToken).ConfigureAwait(false);
+ return localVarResponse.Data;
+ }
+
+ ///
+ /// Add a new pet to the store
+ ///
+ /// Thrown when fails to make API call
+ /// Pet object that needs to be added to the store
+ /// Index associated with the operation.
+ /// Cancellation Token to cancel the request.
+ /// Task of ApiResponse (Pet)
+ public async System.Threading.Tasks.Task> AddPetWithHttpInfoAsync(Pet pet, int operationIndex = 0, System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken))
+ {
+ // verify the required parameter 'pet' is set
+ if (pet == null)
+ {
+ throw new Org.OpenAPITools.Client.ApiException(400, "Missing required parameter 'pet' when calling PetApi->AddPet");
+ }
+
+
+ Org.OpenAPITools.Client.RequestOptions localVarRequestOptions = new Org.OpenAPITools.Client.RequestOptions();
+
+ string[] _contentTypes = new string[] {
+ "application/json",
+ "application/xml"
+ };
+
+ // to determine the Accept header
+ string[] _accepts = new string[] {
+ "application/xml",
+ "application/json"
+ };
+
+ var localVarContentType = Org.OpenAPITools.Client.ClientUtils.SelectHeaderContentType(_contentTypes);
+ if (localVarContentType != null)
+ {
+ localVarRequestOptions.HeaderParameters.Add("Content-Type", localVarContentType);
+ }
+
+ var localVarAccept = Org.OpenAPITools.Client.ClientUtils.SelectHeaderAccept(_accepts);
+ if (localVarAccept != null)
+ {
+ localVarRequestOptions.HeaderParameters.Add("Accept", localVarAccept);
+ }
+
+ localVarRequestOptions.Data = pet;
+
+ localVarRequestOptions.Operation = "PetApi.AddPet";
+ localVarRequestOptions.OperationIndex = operationIndex;
+
+ // authentication (petstore_auth) required
+ // oauth required
+ if (!localVarRequestOptions.HeaderParameters.ContainsKey("Authorization"))
+ {
+ if (!string.IsNullOrEmpty(this.Configuration.AccessToken))
+ {
+ localVarRequestOptions.HeaderParameters.Add("Authorization", "Bearer " + this.Configuration.AccessToken);
+ }
+ else if (!string.IsNullOrEmpty(this.Configuration.OAuthTokenUrl) &&
+ !string.IsNullOrEmpty(this.Configuration.OAuthClientId) &&
+ !string.IsNullOrEmpty(this.Configuration.OAuthClientSecret) &&
+ this.Configuration.OAuthFlow != null)
+ {
+ localVarRequestOptions.OAuth = true;
+ }
+ }
+
+ // make the HTTP request
+ var localVarResponse = await this.AsynchronousClient.PostAsync("/pet", localVarRequestOptions, this.Configuration, cancellationToken).ConfigureAwait(false);
+
+ if (this.ExceptionFactory != null)
+ {
+ Exception _exception = this.ExceptionFactory("AddPet", localVarResponse);
+ if (_exception != null)
+ {
+ throw _exception;
+ }
+ }
+
+ return localVarResponse;
+ }
+
+ }
+}
diff --git a/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/src/Org.OpenAPITools/Client/ApiClient.cs b/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/src/Org.OpenAPITools/Client/ApiClient.cs
new file mode 100644
index 00000000000..a2d3ebd524e
--- /dev/null
+++ b/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/src/Org.OpenAPITools/Client/ApiClient.cs
@@ -0,0 +1,838 @@
+/*
+ * OpenAPI Petstore
+ *
+ * This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
+ *
+ * The version of the OpenAPI document: 1.0.0
+ * Generated by: https://github.com/openapitools/openapi-generator.git
+ */
+
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Globalization;
+using System.IO;
+using System.Linq;
+using System.Net;
+using System.Reflection;
+using System.Runtime.Serialization;
+using System.Runtime.Serialization.Formatters;
+using System.Text;
+using System.Threading;
+using System.Text.RegularExpressions;
+using System.Threading.Tasks;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Serialization;
+using RestSharp;
+using RestSharp.Serializers;
+using RestSharpMethod = RestSharp.Method;
+using FileIO = System.IO.File;
+using Polly;
+using Org.OpenAPITools.Client.Auth;
+using Org.OpenAPITools.Model;
+
+namespace Org.OpenAPITools.Client
+{
+ ///
+ /// Allows RestSharp to Serialize/Deserialize JSON using our custom logic, but only when ContentType is JSON.
+ ///
+ internal class CustomJsonCodec : IRestSerializer, ISerializer, IDeserializer
+ {
+ private readonly IReadableConfiguration _configuration;
+ private readonly JsonSerializerSettings _serializerSettings = new JsonSerializerSettings
+ {
+ // OpenAPI generated types generally hide default constructors.
+ ConstructorHandling = ConstructorHandling.AllowNonPublicDefaultConstructor,
+ ContractResolver = new DefaultContractResolver
+ {
+ NamingStrategy = new CamelCaseNamingStrategy
+ {
+ OverrideSpecifiedNames = false
+ }
+ }
+ };
+
+ public CustomJsonCodec(IReadableConfiguration configuration)
+ {
+ _configuration = configuration;
+ }
+
+ public CustomJsonCodec(JsonSerializerSettings serializerSettings, IReadableConfiguration configuration)
+ {
+ _serializerSettings = serializerSettings;
+ _configuration = configuration;
+ }
+
+ ///
+ /// Serialize the object into a JSON string.
+ ///
+ /// Object to be serialized.
+ /// A JSON string.
+ public string Serialize(object obj)
+ {
+ if (obj != null && obj is AbstractOpenAPISchema)
+ {
+ // the object to be serialized is an oneOf/anyOf schema
+ return ((AbstractOpenAPISchema)obj).ToJson();
+ }
+ else
+ {
+ return JsonConvert.SerializeObject(obj, _serializerSettings);
+ }
+ }
+
+ public string Serialize(Parameter bodyParameter) => Serialize(bodyParameter.Value);
+
+ public T Deserialize(RestResponse response)
+ {
+ var result = (T)Deserialize(response, typeof(T));
+ return result;
+ }
+
+ ///
+ /// Deserialize the JSON string into a proper object.
+ ///
+ /// The HTTP response.
+ /// Object type.
+ /// Object representation of the JSON string.
+ internal object Deserialize(RestResponse response, Type type)
+ {
+ if (type == typeof(byte[])) // return byte array
+ {
+ return response.RawBytes;
+ }
+
+ // TODO: ? if (type.IsAssignableFrom(typeof(Stream)))
+ if (type == typeof(Stream))
+ {
+ var bytes = response.RawBytes;
+ if (response.Headers != null)
+ {
+ var filePath = string.IsNullOrEmpty(_configuration.TempFolderPath)
+ ? global::System.IO.Path.GetTempPath()
+ : _configuration.TempFolderPath;
+ var regex = new Regex(@"Content-Disposition=.*filename=['""]?([^'""\s]+)['""]?$");
+ foreach (var header in response.Headers)
+ {
+ var match = regex.Match(header.ToString());
+ if (match.Success)
+ {
+ string fileName = filePath + ClientUtils.SanitizeFilename(match.Groups[1].Value.Replace("\"", "").Replace("'", ""));
+ FileIO.WriteAllBytes(fileName, bytes);
+ return new FileStream(fileName, FileMode.Open);
+ }
+ }
+ }
+ var stream = new MemoryStream(bytes);
+ return stream;
+ }
+
+ if (type.Name.StartsWith("System.Nullable`1[[System.DateTime")) // return a datetime object
+ {
+ return DateTime.Parse(response.Content, null, DateTimeStyles.RoundtripKind);
+ }
+
+ if (type == typeof(string) || type.Name.StartsWith("System.Nullable")) // return primitive type
+ {
+ return Convert.ChangeType(response.Content, type);
+ }
+
+ // at this point, it must be a model (json)
+ try
+ {
+ return JsonConvert.DeserializeObject(response.Content, type, _serializerSettings);
+ }
+ catch (Exception e)
+ {
+ throw new ApiException(500, e.Message);
+ }
+ }
+
+ public ISerializer Serializer => this;
+ public IDeserializer Deserializer => this;
+
+ public string[] AcceptedContentTypes => ContentType.JsonAccept;
+
+ public SupportsContentType SupportsContentType => contentType =>
+ contentType.Value.EndsWith("json", StringComparison.InvariantCultureIgnoreCase) ||
+ contentType.Value.EndsWith("javascript", StringComparison.InvariantCultureIgnoreCase);
+
+ public ContentType ContentType { get; set; } = ContentType.Json;
+
+ public DataFormat DataFormat => DataFormat.Json;
+ }
+ ///
+ /// Provides a default implementation of an Api client (both synchronous and asynchronous implementations),
+ /// encapsulating general REST accessor use cases.
+ ///
+ public partial class ApiClient : ISynchronousClient, IAsynchronousClient
+ {
+ private readonly string _baseUrl;
+
+ ///
+ /// Specifies the settings on a object.
+ /// These settings can be adjusted to accommodate custom serialization rules.
+ ///
+ public JsonSerializerSettings SerializerSettings { get; set; } = new JsonSerializerSettings
+ {
+ // OpenAPI generated types generally hide default constructors.
+ ConstructorHandling = ConstructorHandling.AllowNonPublicDefaultConstructor,
+ ContractResolver = new DefaultContractResolver
+ {
+ NamingStrategy = new CamelCaseNamingStrategy
+ {
+ OverrideSpecifiedNames = false
+ }
+ }
+ };
+
+ ///
+ /// Allows for extending request processing for generated code.
+ ///
+ /// The RestSharp request object
+ public virtual void InterceptRequest(RestRequest request) { }
+
+ ///
+ /// Allows for extending response processing for generated code.
+ ///
+ /// The RestSharp request object
+ /// The RestSharp response object
+ public virtual void InterceptResponse(RestRequest request, RestResponse response) { }
+
+ ///
+ /// Initializes a new instance of the , defaulting to the global configurations' base url.
+ ///
+ public ApiClient()
+ {
+ _baseUrl = GlobalConfiguration.Instance.BasePath;
+ }
+
+ ///
+ /// Initializes a new instance of the
+ ///
+ /// The target service's base path in URL format.
+ ///
+ public ApiClient(string basePath)
+ {
+ if (string.IsNullOrEmpty(basePath))
+ throw new ArgumentException("basePath cannot be empty");
+
+ _baseUrl = basePath;
+ }
+
+ ///
+ /// Constructs the RestSharp version of an http method
+ ///
+ /// Swagger Client Custom HttpMethod
+ /// RestSharp's HttpMethod instance.
+ ///
+ private RestSharpMethod Method(HttpMethod method)
+ {
+ RestSharpMethod other;
+ switch (method)
+ {
+ case HttpMethod.Get:
+ other = RestSharpMethod.Get;
+ break;
+ case HttpMethod.Post:
+ other = RestSharpMethod.Post;
+ break;
+ case HttpMethod.Put:
+ other = RestSharpMethod.Put;
+ break;
+ case HttpMethod.Delete:
+ other = RestSharpMethod.Delete;
+ break;
+ case HttpMethod.Head:
+ other = RestSharpMethod.Head;
+ break;
+ case HttpMethod.Options:
+ other = RestSharpMethod.Options;
+ break;
+ case HttpMethod.Patch:
+ other = RestSharpMethod.Patch;
+ break;
+ default:
+ throw new ArgumentOutOfRangeException("method", method, null);
+ }
+
+ return other;
+ }
+
+ ///
+ /// Provides all logic for constructing a new RestSharp .
+ /// At this point, all information for querying the service is known.
+ /// Here, it is simply mapped into the RestSharp request.
+ ///
+ /// The http verb.
+ /// The target path (or resource).
+ /// The additional request options.
+ /// A per-request configuration object.
+ /// It is assumed that any merge with GlobalConfiguration has been done before calling this method.
+ /// [private] A new RestRequest instance.
+ ///
+ private RestRequest NewRequest(
+ HttpMethod method,
+ string path,
+ RequestOptions options,
+ IReadableConfiguration configuration)
+ {
+ if (path == null) throw new ArgumentNullException("path");
+ if (options == null) throw new ArgumentNullException("options");
+ if (configuration == null) throw new ArgumentNullException("configuration");
+
+ RestRequest request = new RestRequest(path, Method(method));
+
+ if (options.PathParameters != null)
+ {
+ foreach (var pathParam in options.PathParameters)
+ {
+ request.AddParameter(pathParam.Key, pathParam.Value, ParameterType.UrlSegment);
+ }
+ }
+
+ if (options.QueryParameters != null)
+ {
+ foreach (var queryParam in options.QueryParameters)
+ {
+ foreach (var value in queryParam.Value)
+ {
+ request.AddQueryParameter(queryParam.Key, value);
+ }
+ }
+ }
+
+ if (configuration.DefaultHeaders != null)
+ {
+ foreach (var headerParam in configuration.DefaultHeaders)
+ {
+ request.AddHeader(headerParam.Key, headerParam.Value);
+ }
+ }
+
+ if (options.HeaderParameters != null)
+ {
+ foreach (var headerParam in options.HeaderParameters)
+ {
+ foreach (var value in headerParam.Value)
+ {
+ request.AddOrUpdateHeader(headerParam.Key, value);
+ }
+ }
+ }
+
+ if (options.FormParameters != null)
+ {
+ foreach (var formParam in options.FormParameters)
+ {
+ request.AddParameter(formParam.Key, formParam.Value);
+ }
+ }
+
+ if (options.Data != null)
+ {
+ if (options.Data is Stream stream)
+ {
+ var contentType = "application/octet-stream";
+ if (options.HeaderParameters != null)
+ {
+ var contentTypes = options.HeaderParameters["Content-Type"];
+ contentType = contentTypes[0];
+ }
+
+ var bytes = ClientUtils.ReadAsBytes(stream);
+ request.AddParameter(contentType, bytes, ParameterType.RequestBody);
+ }
+ else
+ {
+ if (options.HeaderParameters != null)
+ {
+ var contentTypes = options.HeaderParameters["Content-Type"];
+ if (contentTypes == null || contentTypes.Any(header => header.Contains("application/json")))
+ {
+ request.RequestFormat = DataFormat.Json;
+ }
+ else
+ {
+ // TODO: Generated client user should add additional handlers. RestSharp only supports XML and JSON, with XML as default.
+ }
+ }
+ else
+ {
+ // Here, we'll assume JSON APIs are more common. XML can be forced by adding produces/consumes to openapi spec explicitly.
+ request.RequestFormat = DataFormat.Json;
+ }
+
+ request.AddJsonBody(options.Data);
+ }
+ }
+
+ if (options.FileParameters != null)
+ {
+ foreach (var fileParam in options.FileParameters)
+ {
+ foreach (var file in fileParam.Value)
+ {
+ var bytes = ClientUtils.ReadAsBytes(file);
+ var fileStream = file as FileStream;
+ if (fileStream != null)
+ request.AddFile(fileParam.Key, bytes, global::System.IO.Path.GetFileName(fileStream.Name));
+ else
+ request.AddFile(fileParam.Key, bytes, "no_file_name_provided");
+ }
+ }
+ }
+
+ if (options.HeaderParameters != null)
+ {
+ if (options.HeaderParameters.TryGetValue("Content-Type", out var contentTypes) && contentTypes.Any(header => header.Contains("multipart/form-data")))
+ {
+ request.AlwaysMultipartFormData = true;
+ }
+ }
+
+ return request;
+ }
+
+ ///
+ /// Transforms a RestResponse instance into a new ApiResponse instance.
+ /// At this point, we have a concrete http response from the service.
+ /// Here, it is simply mapped into the [public] ApiResponse object.
+ ///
+ /// The RestSharp response object
+ /// A new ApiResponse instance.
+ private ApiResponse ToApiResponse(RestResponse response)
+ {
+ T result = response.Data;
+ string rawContent = response.Content;
+
+ var transformed = new ApiResponse(response.StatusCode, new Multimap(), result, rawContent)
+ {
+ ErrorText = response.ErrorMessage,
+ Cookies = new List()
+ };
+
+ if (response.Headers != null)
+ {
+ foreach (var responseHeader in response.Headers)
+ {
+ transformed.Headers.Add(responseHeader.Name, ClientUtils.ParameterToString(responseHeader.Value));
+ }
+ }
+
+ if (response.ContentHeaders != null)
+ {
+ foreach (var responseHeader in response.ContentHeaders)
+ {
+ transformed.Headers.Add(responseHeader.Name, ClientUtils.ParameterToString(responseHeader.Value));
+ }
+ }
+
+ if (response.Cookies != null)
+ {
+ foreach (var responseCookies in response.Cookies.Cast())
+ {
+ transformed.Cookies.Add(
+ new Cookie(
+ responseCookies.Name,
+ responseCookies.Value,
+ responseCookies.Path,
+ responseCookies.Domain)
+ );
+ }
+ }
+
+ return transformed;
+ }
+
+ ///
+ /// Executes the HTTP request for the current service.
+ /// Based on functions received it can be async or sync.
+ ///
+ /// Local function that executes http request and returns http response.
+ /// Local function to specify options for the service.
+ /// The RestSharp request object
+ /// The RestSharp options object
+ /// A per-request configuration object.
+ /// It is assumed that any merge with GlobalConfiguration has been done before calling this method.
+ /// A new ApiResponse instance.
+ private async Task> ExecClientAsync(Func>> getResponse, Action setOptions, RestRequest request, RequestOptions options, IReadableConfiguration configuration)
+ {
+ var baseUrl = configuration.GetOperationServerUrl(options.Operation, options.OperationIndex) ?? _baseUrl;
+ var clientOptions = new RestClientOptions(baseUrl)
+ {
+ ClientCertificates = configuration.ClientCertificates,
+ Timeout = configuration.Timeout,
+ Proxy = configuration.Proxy,
+ UserAgent = configuration.UserAgent,
+ UseDefaultCredentials = configuration.UseDefaultCredentials,
+ RemoteCertificateValidationCallback = configuration.RemoteCertificateValidationCallback
+ };
+ setOptions(clientOptions);
+
+ if (!string.IsNullOrEmpty(configuration.OAuthTokenUrl) &&
+ !string.IsNullOrEmpty(configuration.OAuthClientId) &&
+ !string.IsNullOrEmpty(configuration.OAuthClientSecret) &&
+ configuration.OAuthFlow != null)
+ {
+ clientOptions.Authenticator = new OAuthAuthenticator(
+ configuration.OAuthTokenUrl,
+ configuration.OAuthClientId,
+ configuration.OAuthClientSecret,
+ configuration.OAuthScope,
+ configuration.OAuthFlow,
+ SerializerSettings,
+ configuration);
+ }
+
+ using (RestClient client = new RestClient(clientOptions,
+ configureSerialization: serializerConfig => serializerConfig.UseSerializer(() => new CustomJsonCodec(SerializerSettings, configuration))))
+ {
+ InterceptRequest(request);
+
+ RestResponse response = await getResponse(client);
+
+ // if the response type is oneOf/anyOf, call FromJSON to deserialize the data
+ if (typeof(AbstractOpenAPISchema).IsAssignableFrom(typeof(T)))
+ {
+ try
+ {
+ response.Data = (T)typeof(T).GetMethod("FromJson").Invoke(null, new object[] { response.Content });
+ }
+ catch (Exception ex)
+ {
+ throw ex.InnerException != null ? ex.InnerException : ex;
+ }
+ }
+ else if (typeof(T).Name == "Stream") // for binary response
+ {
+ response.Data = (T)(object)new MemoryStream(response.RawBytes);
+ }
+ else if (typeof(T).Name == "Byte[]") // for byte response
+ {
+ response.Data = (T)(object)response.RawBytes;
+ }
+ else if (typeof(T).Name == "String") // for string response
+ {
+ response.Data = (T)(object)response.Content;
+ }
+
+ InterceptResponse(request, response);
+
+ var result = ToApiResponse(response);
+ if (response.ErrorMessage != null)
+ {
+ result.ErrorText = response.ErrorMessage;
+ }
+
+ if (response.Cookies != null && response.Cookies.Count > 0)
+ {
+ if (result.Cookies == null) result.Cookies = new List();
+ foreach (var restResponseCookie in response.Cookies.Cast())
+ {
+ var cookie = new Cookie(
+ restResponseCookie.Name,
+ restResponseCookie.Value,
+ restResponseCookie.Path,
+ restResponseCookie.Domain
+ )
+ {
+ Comment = restResponseCookie.Comment,
+ CommentUri = restResponseCookie.CommentUri,
+ Discard = restResponseCookie.Discard,
+ Expired = restResponseCookie.Expired,
+ Expires = restResponseCookie.Expires,
+ HttpOnly = restResponseCookie.HttpOnly,
+ Port = restResponseCookie.Port,
+ Secure = restResponseCookie.Secure,
+ Version = restResponseCookie.Version
+ };
+
+ result.Cookies.Add(cookie);
+ }
+ }
+ return result;
+ }
+ }
+
+ private async Task> DeserializeRestResponseFromPolicyAsync(RestClient client, RestRequest request, PolicyResult policyResult, CancellationToken cancellationToken = default)
+ {
+ if (policyResult.Outcome == OutcomeType.Successful)
+ {
+ return await client.Deserialize(policyResult.Result, cancellationToken);
+ }
+ else
+ {
+ return new RestResponse(request)
+ {
+ ErrorException = policyResult.FinalException
+ };
+ }
+ }
+
+ private ApiResponse Exec(RestRequest request, RequestOptions options, IReadableConfiguration configuration)
+ {
+ Action setOptions = (clientOptions) =>
+ {
+ var cookies = new CookieContainer();
+
+ if (options.Cookies != null && options.Cookies.Count > 0)
+ {
+ foreach (var cookie in options.Cookies)
+ {
+ cookies.Add(new Cookie(cookie.Name, cookie.Value));
+ }
+ }
+ clientOptions.CookieContainer = cookies;
+ };
+
+ Func>> getResponse = (client) =>
+ {
+ if (RetryConfiguration.RetryPolicy != null)
+ {
+ var policy = RetryConfiguration.RetryPolicy;
+ var policyResult = policy.ExecuteAndCapture(() => client.Execute(request));
+ return DeserializeRestResponseFromPolicyAsync(client, request, policyResult);
+ }
+ else
+ {
+ return Task.FromResult(client.Execute(request));
+ }
+ };
+
+ return ExecClientAsync(getResponse, setOptions, request, options, configuration).GetAwaiter().GetResult();
+ }
+
+ private Task> ExecAsync(RestRequest request, RequestOptions options, IReadableConfiguration configuration, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ Action setOptions = (clientOptions) =>
+ {
+ //no extra options
+ };
+
+ Func>> getResponse = async (client) =>
+ {
+ if (RetryConfiguration.AsyncRetryPolicy != null)
+ {
+ var policy = RetryConfiguration.AsyncRetryPolicy;
+ var policyResult = await policy.ExecuteAndCaptureAsync((ct) => client.ExecuteAsync(request, ct), cancellationToken).ConfigureAwait(false);
+ return await DeserializeRestResponseFromPolicyAsync(client, request, policyResult, cancellationToken);
+ }
+ else
+ {
+ return await client.ExecuteAsync(request, cancellationToken).ConfigureAwait(false);
+ }
+ };
+
+ return ExecClientAsync(getResponse, setOptions, request, options, configuration);
+ }
+
+ #region IAsynchronousClient
+ ///
+ /// Make a HTTP GET request (async).
+ ///
+ /// The target path (or resource).
+ /// The additional request options.
+ /// A per-request configuration object. It is assumed that any merge with
+ /// GlobalConfiguration has been done before calling this method.
+ /// Token that enables callers to cancel the request.
+ /// A Task containing ApiResponse
+ public Task> GetAsync(string path, RequestOptions options, IReadableConfiguration configuration = null, CancellationToken cancellationToken = default)
+ {
+ var config = configuration ?? GlobalConfiguration.Instance;
+ return ExecAsync(NewRequest(HttpMethod.Get, path, options, config), options, config, cancellationToken);
+ }
+
+ ///
+ /// Make a HTTP POST request (async).
+ ///
+ /// The target path (or resource).
+ /// The additional request options.
+ /// A per-request configuration object. It is assumed that any merge with
+ /// GlobalConfiguration has been done before calling this method.
+ /// Token that enables callers to cancel the request.
+ /// A Task containing ApiResponse
+ public Task> PostAsync(string path, RequestOptions options, IReadableConfiguration configuration = null, CancellationToken cancellationToken = default)
+ {
+ var config = configuration ?? GlobalConfiguration.Instance;
+ return ExecAsync(NewRequest(HttpMethod.Post, path, options, config), options, config, cancellationToken);
+ }
+
+ ///
+ /// Make a HTTP PUT request (async).
+ ///
+ /// The target path (or resource).
+ /// The additional request options.
+ /// A per-request configuration object. It is assumed that any merge with
+ /// GlobalConfiguration has been done before calling this method.
+ /// Token that enables callers to cancel the request.
+ /// A Task containing ApiResponse
+ public Task> PutAsync(string path, RequestOptions options, IReadableConfiguration configuration = null, CancellationToken cancellationToken = default)
+ {
+ var config = configuration ?? GlobalConfiguration.Instance;
+ return ExecAsync(NewRequest(HttpMethod.Put, path, options, config), options, config, cancellationToken);
+ }
+
+ ///
+ /// Make a HTTP DELETE request (async).
+ ///
+ /// The target path (or resource).
+ /// The additional request options.
+ /// A per-request configuration object. It is assumed that any merge with
+ /// GlobalConfiguration has been done before calling this method.
+ /// Token that enables callers to cancel the request.
+ /// A Task containing ApiResponse
+ public Task> DeleteAsync(string path, RequestOptions options, IReadableConfiguration configuration = null, CancellationToken cancellationToken = default)
+ {
+ var config = configuration ?? GlobalConfiguration.Instance;
+ return ExecAsync(NewRequest(HttpMethod.Delete, path, options, config), options, config, cancellationToken);
+ }
+
+ ///
+ /// Make a HTTP HEAD request (async).
+ ///
+ /// The target path (or resource).
+ /// The additional request options.
+ /// A per-request configuration object. It is assumed that any merge with
+ /// GlobalConfiguration has been done before calling this method.
+ /// Token that enables callers to cancel the request.
+ /// A Task containing ApiResponse
+ public Task> HeadAsync(string path, RequestOptions options, IReadableConfiguration configuration = null, CancellationToken cancellationToken = default)
+ {
+ var config = configuration ?? GlobalConfiguration.Instance;
+ return ExecAsync(NewRequest(HttpMethod.Head, path, options, config), options, config, cancellationToken);
+ }
+
+ ///
+ /// Make a HTTP OPTION request (async).
+ ///
+ /// The target path (or resource).
+ /// The additional request options.
+ /// A per-request configuration object. It is assumed that any merge with
+ /// GlobalConfiguration has been done before calling this method.
+ /// Token that enables callers to cancel the request.
+ /// A Task containing ApiResponse
+ public Task> OptionsAsync(string path, RequestOptions options, IReadableConfiguration configuration = null, CancellationToken cancellationToken = default)
+ {
+ var config = configuration ?? GlobalConfiguration.Instance;
+ return ExecAsync(NewRequest(HttpMethod.Options, path, options, config), options, config, cancellationToken);
+ }
+
+ ///
+ /// Make a HTTP PATCH request (async).
+ ///
+ /// The target path (or resource).
+ /// The additional request options.
+ /// A per-request configuration object. It is assumed that any merge with
+ /// GlobalConfiguration has been done before calling this method.
+ /// Token that enables callers to cancel the request.
+ /// A Task containing ApiResponse
+ public Task> PatchAsync(string path, RequestOptions options, IReadableConfiguration configuration = null, CancellationToken cancellationToken = default)
+ {
+ var config = configuration ?? GlobalConfiguration.Instance;
+ return ExecAsync(NewRequest(HttpMethod.Patch, path, options, config), options, config, cancellationToken);
+ }
+ #endregion IAsynchronousClient
+
+ #region ISynchronousClient
+ ///
+ /// Make a HTTP GET request (synchronous).
+ ///
+ /// The target path (or resource).
+ /// The additional request options.
+ /// A per-request configuration object. It is assumed that any merge with
+ /// GlobalConfiguration has been done before calling this method.
+ /// A Task containing ApiResponse
+ public ApiResponse Get(string path, RequestOptions options, IReadableConfiguration configuration = null)
+ {
+ var config = configuration ?? GlobalConfiguration.Instance;
+ return Exec(NewRequest(HttpMethod.Get, path, options, config), options, config);
+ }
+
+ ///
+ /// Make a HTTP POST request (synchronous).
+ ///
+ /// The target path (or resource).
+ /// The additional request options.
+ /// A per-request configuration object. It is assumed that any merge with
+ /// GlobalConfiguration has been done before calling this method.
+ /// A Task containing ApiResponse
+ public ApiResponse Post(string path, RequestOptions options, IReadableConfiguration configuration = null)
+ {
+ var config = configuration ?? GlobalConfiguration.Instance;
+ return Exec(NewRequest(HttpMethod.Post, path, options, config), options, config);
+ }
+
+ ///
+ /// Make a HTTP PUT request (synchronous).
+ ///
+ /// The target path (or resource).
+ /// The additional request options.
+ /// A per-request configuration object. It is assumed that any merge with
+ /// GlobalConfiguration has been done before calling this method.
+ /// A Task containing ApiResponse
+ public ApiResponse Put(string path, RequestOptions options, IReadableConfiguration configuration = null)
+ {
+ var config = configuration ?? GlobalConfiguration.Instance;
+ return Exec(NewRequest(HttpMethod.Put, path, options, config), options, config);
+ }
+
+ ///
+ /// Make a HTTP DELETE request (synchronous).
+ ///
+ /// The target path (or resource).
+ /// The additional request options.
+ /// A per-request configuration object. It is assumed that any merge with
+ /// GlobalConfiguration has been done before calling this method.
+ /// A Task containing ApiResponse
+ public ApiResponse Delete(string path, RequestOptions options, IReadableConfiguration configuration = null)
+ {
+ var config = configuration ?? GlobalConfiguration.Instance;
+ return Exec(NewRequest(HttpMethod.Delete, path, options, config), options, config);
+ }
+
+ ///
+ /// Make a HTTP HEAD request (synchronous).
+ ///
+ /// The target path (or resource).
+ /// The additional request options.
+ /// A per-request configuration object. It is assumed that any merge with
+ /// GlobalConfiguration has been done before calling this method.
+ /// A Task containing ApiResponse
+ public ApiResponse Head(string path, RequestOptions options, IReadableConfiguration configuration = null)
+ {
+ var config = configuration ?? GlobalConfiguration.Instance;
+ return Exec(NewRequest(HttpMethod.Head, path, options, config), options, config);
+ }
+
+ ///
+ /// Make a HTTP OPTION request (synchronous).
+ ///
+ /// The target path (or resource).
+ /// The additional request options.
+ /// A per-request configuration object. It is assumed that any merge with
+ /// GlobalConfiguration has been done before calling this method.
+ /// A Task containing ApiResponse
+ public ApiResponse Options(string path, RequestOptions options, IReadableConfiguration configuration = null)
+ {
+ var config = configuration ?? GlobalConfiguration.Instance;
+ return Exec(NewRequest(HttpMethod.Options, path, options, config), options, config);
+ }
+
+ ///
+ /// Make a HTTP PATCH request (synchronous).
+ ///
+ /// The target path (or resource).
+ /// The additional request options.
+ /// A per-request configuration object. It is assumed that any merge with
+ /// GlobalConfiguration has been done before calling this method.
+ /// A Task containing ApiResponse
+ public ApiResponse Patch(string path, RequestOptions options, IReadableConfiguration configuration = null)
+ {
+ var config = configuration ?? GlobalConfiguration.Instance;
+ return Exec(NewRequest(HttpMethod.Patch, path, options, config), options, config);
+ }
+ #endregion ISynchronousClient
+ }
+}
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
new file mode 100644
index 00000000000..dcc378ad208
--- /dev/null
+++ b/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/src/Org.OpenAPITools/Client/ApiException.cs
@@ -0,0 +1,68 @@
+/*
+ * OpenAPI Petstore
+ *
+ * This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
+ *
+ * The version of the OpenAPI document: 1.0.0
+ * Generated by: https://github.com/openapitools/openapi-generator.git
+ */
+
+
+using System;
+
+namespace Org.OpenAPITools.Client
+{
+ ///
+ /// API Exception
+ ///
+ public class ApiException : Exception
+ {
+ ///
+ /// Gets or sets the error code (HTTP status code)
+ ///
+ /// The error code (HTTP status code).
+ public int ErrorCode { get; set; }
+
+ ///
+ /// Gets or sets the error content (body json object)
+ ///
+ /// The error content (Http response body).
+ public object ErrorContent { get; private set; }
+
+ ///
+ /// Gets or sets the HTTP headers
+ ///
+ /// HTTP headers
+ public Multimap Headers { get; private set; }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public ApiException() { }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// HTTP status code.
+ /// Error message.
+ public ApiException(int errorCode, string message) : base(message)
+ {
+ this.ErrorCode = errorCode;
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// HTTP status code.
+ /// Error message.
+ /// Error content.
+ /// HTTP Headers.
+ public ApiException(int errorCode, string message, object errorContent = null, Multimap headers = null) : base(message)
+ {
+ this.ErrorCode = errorCode;
+ this.ErrorContent = errorContent;
+ this.Headers = headers;
+ }
+ }
+
+}
diff --git a/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/src/Org.OpenAPITools/Client/ApiResponse.cs b/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/src/Org.OpenAPITools/Client/ApiResponse.cs
new file mode 100644
index 00000000000..6d91a6f7a47
--- /dev/null
+++ b/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/src/Org.OpenAPITools/Client/ApiResponse.cs
@@ -0,0 +1,166 @@
+/*
+ * OpenAPI Petstore
+ *
+ * This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
+ *
+ * The version of the OpenAPI document: 1.0.0
+ * Generated by: https://github.com/openapitools/openapi-generator.git
+ */
+
+
+using System;
+using System.Collections.Generic;
+using System.Net;
+
+namespace Org.OpenAPITools.Client
+{
+ ///
+ /// Provides a non-generic contract for the ApiResponse wrapper.
+ ///
+ public interface IApiResponse
+ {
+ ///
+ /// The data type of
+ ///
+ Type ResponseType { get; }
+
+ ///
+ /// The content of this response
+ ///
+ Object Content { get; }
+
+ ///
+ /// Gets or sets the status code (HTTP status code)
+ ///
+ /// The status code.
+ HttpStatusCode StatusCode { get; }
+
+ ///
+ /// Gets or sets the HTTP headers
+ ///
+ /// HTTP headers
+ Multimap Headers { get; }
+
+ ///
+ /// Gets or sets any error text defined by the calling client.
+ ///
+ string ErrorText { get; set; }
+
+ ///
+ /// Gets or sets any cookies passed along on the response.
+ ///
+ List Cookies { get; set; }
+
+ ///
+ /// The raw content of this response
+ ///
+ string RawContent { get; }
+ }
+
+ ///
+ /// API Response
+ ///
+ public class ApiResponse : IApiResponse
+ {
+ #region Properties
+
+ ///
+ /// Gets or sets the status code (HTTP status code)
+ ///
+ /// The status code.
+ public HttpStatusCode StatusCode { get; }
+
+ ///
+ /// Gets or sets the HTTP headers
+ ///
+ /// HTTP headers
+ public Multimap Headers { get; }
+
+ ///
+ /// Gets or sets the data (parsed HTTP body)
+ ///
+ /// The data.
+ public T Data { get; }
+
+ ///
+ /// Gets or sets any error text defined by the calling client.
+ ///
+ public string ErrorText { get; set; }
+
+ ///
+ /// Gets or sets any cookies passed along on the response.
+ ///
+ public List Cookies { get; set; }
+
+ ///
+ /// The content of this response
+ ///
+ public Type ResponseType
+ {
+ get { return typeof(T); }
+ }
+
+ ///
+ /// The data type of
+ ///
+ public object Content
+ {
+ get { return Data; }
+ }
+
+ ///
+ /// The raw content
+ ///
+ public string RawContent { get; }
+
+ #endregion Properties
+
+ #region Constructors
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// HTTP status code.
+ /// HTTP headers.
+ /// Data (parsed HTTP body)
+ /// Raw content.
+ public ApiResponse(HttpStatusCode statusCode, Multimap headers, T data, string rawContent)
+ {
+ StatusCode = statusCode;
+ Headers = headers;
+ Data = data;
+ RawContent = rawContent;
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// HTTP status code.
+ /// HTTP headers.
+ /// Data (parsed HTTP body)
+ public ApiResponse(HttpStatusCode statusCode, Multimap headers, T data) : this(statusCode, headers, data, null)
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// HTTP status code.
+ /// Data (parsed HTTP body)
+ /// Raw content.
+ public ApiResponse(HttpStatusCode statusCode, T data, string rawContent) : this(statusCode, null, data, rawContent)
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// HTTP status code.
+ /// Data (parsed HTTP body)
+ public ApiResponse(HttpStatusCode statusCode, T data) : this(statusCode, data, null)
+ {
+ }
+
+ #endregion Constructors
+ }
+}
diff --git a/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/src/Org.OpenAPITools/Client/Auth/OAuthAuthenticator.cs b/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/src/Org.OpenAPITools/Client/Auth/OAuthAuthenticator.cs
new file mode 100644
index 00000000000..39498419f39
--- /dev/null
+++ b/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/src/Org.OpenAPITools/Client/Auth/OAuthAuthenticator.cs
@@ -0,0 +1,144 @@
+/*
+ * OpenAPI Petstore
+ *
+ * This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
+ *
+ * The version of the OpenAPI document: 1.0.0
+ * Generated by: https://github.com/openapitools/openapi-generator.git
+ */
+
+
+using System;
+using System.Threading.Tasks;
+using Newtonsoft.Json;
+using RestSharp;
+using RestSharp.Authenticators;
+
+namespace Org.OpenAPITools.Client.Auth
+{
+ ///
+ /// An authenticator for OAuth2 authentication flows
+ ///
+ public class OAuthAuthenticator : IAuthenticator
+ {
+ private TokenResponse? _token;
+
+ ///
+ /// Returns the current authentication token. Can return null if there is no authentication token, or it has expired.
+ ///
+ public string? Token
+ {
+ get
+ {
+ if (_token == null) return null;
+ if (_token.ExpiresIn == null) return _token.AccessToken;
+ if (_token.ExpiresAt < DateTime.Now) return null;
+
+ return _token.AccessToken;
+ }
+ }
+
+ readonly string _tokenUrl;
+ readonly string _clientId;
+ readonly string _clientSecret;
+ readonly string? _scope;
+ readonly string _grantType;
+ readonly JsonSerializerSettings _serializerSettings;
+ readonly IReadableConfiguration _configuration;
+
+ ///
+ /// Initialize the OAuth2 Authenticator
+ ///
+ public OAuthAuthenticator(
+ string tokenUrl,
+ string clientId,
+ string clientSecret,
+ string? scope,
+ OAuthFlow? flow,
+ JsonSerializerSettings serializerSettings,
+ IReadableConfiguration configuration)
+ {
+ _tokenUrl = tokenUrl;
+ _clientId = clientId;
+ _clientSecret = clientSecret;
+ _scope = scope;
+ _serializerSettings = serializerSettings;
+ _configuration = configuration;
+
+ switch (flow)
+ {
+ /*case OAuthFlow.ACCESS_CODE:
+ _grantType = "authorization_code";
+ break;
+ case OAuthFlow.IMPLICIT:
+ _grantType = "implicit";
+ break;
+ case OAuthFlow.PASSWORD:
+ _grantType = "password";
+ break;*/
+ case OAuthFlow.APPLICATION:
+ _grantType = "client_credentials";
+ break;
+ default:
+ break;
+ }
+ }
+
+ ///
+ /// Creates an authentication parameter from an access token.
+ ///
+ /// An authentication parameter.
+ protected async ValueTask GetAuthenticationParameter()
+ {
+ var token = string.IsNullOrEmpty(Token) ? await GetToken().ConfigureAwait(false) : Token;
+ return new HeaderParameter(KnownHeaders.Authorization, token);
+ }
+
+ ///
+ /// Gets the token from the OAuth2 server.
+ ///
+ /// An authentication token.
+ async Task GetToken()
+ {
+ var client = new RestClient(_tokenUrl, configureSerialization: serializerConfig => serializerConfig.UseSerializer(() => new CustomJsonCodec(_serializerSettings, _configuration)));
+
+ var request = new RestRequest();
+ if (!string.IsNullOrWhiteSpace(_token?.RefreshToken))
+ {
+ request.AddParameter("grant_type", "refresh_token")
+ .AddParameter("refresh_token", _token.RefreshToken);
+ }
+ else
+ {
+ request
+ .AddParameter("grant_type", _grantType)
+ .AddParameter("client_id", _clientId)
+ .AddParameter("client_secret", _clientSecret);
+ }
+ if (!string.IsNullOrEmpty(_scope))
+ {
+ request.AddParameter("scope", _scope);
+ }
+ _token = await client.PostAsync(request).ConfigureAwait(false);
+ // RFC6749 - token_type is case insensitive.
+ // RFC6750 - In Authorization header Bearer should be capitalized.
+ // Fix the capitalization irrespective of token_type casing.
+ switch (_token?.TokenType?.ToLower())
+ {
+ case "bearer":
+ return $"Bearer {_token.AccessToken}";
+ default:
+ return $"{_token?.TokenType} {_token?.AccessToken}";
+ }
+ }
+
+ ///
+ /// Retrieves the authentication token (creating a new one if necessary) and adds it to the current request
+ ///
+ ///
+ ///
+ ///
+ public async ValueTask Authenticate(IRestClient client, RestRequest request)
+ => request.AddOrUpdateParameter(await GetAuthenticationParameter().ConfigureAwait(false));
+ }
+}
diff --git a/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/src/Org.OpenAPITools/Client/Auth/OAuthFlow.cs b/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/src/Org.OpenAPITools/Client/Auth/OAuthFlow.cs
new file mode 100644
index 00000000000..2e1adf93002
--- /dev/null
+++ b/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/src/Org.OpenAPITools/Client/Auth/OAuthFlow.cs
@@ -0,0 +1,27 @@
+/*
+ * OpenAPI Petstore
+ *
+ * This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
+ *
+ * The version of the OpenAPI document: 1.0.0
+ * Generated by: https://github.com/openapitools/openapi-generator.git
+ */
+
+
+namespace Org.OpenAPITools.Client.Auth
+{
+ ///
+ /// Available flows for OAuth2 authentication
+ ///
+ public enum OAuthFlow
+ {
+ /// Authorization code flow
+ ACCESS_CODE,
+ /// Implicit flow
+ IMPLICIT,
+ /// Password flow
+ PASSWORD,
+ /// Client credentials flow
+ APPLICATION
+ }
+}
\ No newline at end of file
diff --git a/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/src/Org.OpenAPITools/Client/Auth/TokenResponse.cs b/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/src/Org.OpenAPITools/Client/Auth/TokenResponse.cs
new file mode 100644
index 00000000000..da4342c30dd
--- /dev/null
+++ b/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/src/Org.OpenAPITools/Client/Auth/TokenResponse.cs
@@ -0,0 +1,32 @@
+/*
+ * OpenAPI Petstore
+ *
+ * This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
+ *
+ * The version of the OpenAPI document: 1.0.0
+ * Generated by: https://github.com/openapitools/openapi-generator.git
+ */
+
+
+using System;
+using Newtonsoft.Json;
+
+namespace Org.OpenAPITools.Client.Auth
+{
+ class TokenResponse
+ {
+ [JsonProperty("token_type")]
+ public string TokenType { get; set; }
+ [JsonProperty("access_token")]
+ public string AccessToken { get; set; }
+ [JsonProperty("expires_in")]
+ public int? ExpiresIn { get; set; }
+ [JsonProperty("created")]
+ public DateTime? Created { get; set; }
+
+ [JsonProperty("refresh_token")]
+ public string? RefreshToken { get; set; }
+
+ public DateTime? ExpiresAt => ExpiresIn == null ? null : Created?.AddSeconds(ExpiresIn.Value);
+ }
+}
\ No newline at end of file
diff --git a/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/src/Org.OpenAPITools/Client/ClientUtils.cs b/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/src/Org.OpenAPITools/Client/ClientUtils.cs
new file mode 100644
index 00000000000..8ba2457f7bd
--- /dev/null
+++ b/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/src/Org.OpenAPITools/Client/ClientUtils.cs
@@ -0,0 +1,253 @@
+/*
+ * OpenAPI Petstore
+ *
+ * This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
+ *
+ * The version of the OpenAPI document: 1.0.0
+ * Generated by: https://github.com/openapitools/openapi-generator.git
+ */
+
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Globalization;
+using System.IO;
+using System.Linq;
+using System.Runtime.Serialization;
+using System.Text;
+using System.Text.RegularExpressions;
+
+namespace Org.OpenAPITools.Client
+{
+ ///
+ /// Utility functions providing some benefit to API client consumers.
+ ///
+ public static class ClientUtils
+ {
+ ///
+ /// Sanitize filename by removing the path
+ ///
+ /// Filename
+ /// Filename
+ public static string SanitizeFilename(string filename)
+ {
+ Match match = Regex.Match(filename, @".*[/\\](.*)$");
+ return match.Success ? match.Groups[1].Value : filename;
+ }
+
+ ///
+ /// Convert params to key/value pairs.
+ /// Use collectionFormat to properly format lists and collections.
+ ///
+ /// The swagger-supported collection format, one of: csv, tsv, ssv, pipes, multi
+ /// Key name.
+ /// Value object.
+ /// A multimap of keys with 1..n associated values.
+ public static Multimap ParameterToMultiMap(string collectionFormat, string name, object value)
+ {
+ var parameters = new Multimap();
+
+ if (value is ICollection collection && collectionFormat == "multi")
+ {
+ foreach (var item in collection)
+ {
+ parameters.Add(name, ParameterToString(item));
+ }
+ }
+ else if (value is IDictionary dictionary)
+ {
+ if(collectionFormat == "deepObject") {
+ foreach (DictionaryEntry entry in dictionary)
+ {
+ parameters.Add(name + "[" + entry.Key + "]", ParameterToString(entry.Value));
+ }
+ }
+ else {
+ foreach (DictionaryEntry entry in dictionary)
+ {
+ parameters.Add(entry.Key.ToString(), ParameterToString(entry.Value));
+ }
+ }
+ }
+ else
+ {
+ parameters.Add(name, ParameterToString(value));
+ }
+
+ return parameters;
+ }
+
+ ///
+ /// If parameter is DateTime, output in a formatted string (default ISO 8601), customizable with Configuration.DateTime.
+ /// If parameter is a list, join the list with ",".
+ /// Otherwise just return the string.
+ ///
+ /// The parameter (header, path, query, form).
+ /// An optional configuration instance, providing formatting options used in processing.
+ /// Formatted string.
+ public static string ParameterToString(object obj, IReadableConfiguration configuration = null)
+ {
+ if (obj is DateTime dateTime)
+ // Return a formatted date string - Can be customized with Configuration.DateTimeFormat
+ // Defaults to an ISO 8601, using the known as a Round-trip date/time pattern ("o")
+ // https://msdn.microsoft.com/en-us/library/az4se3k1(v=vs.110).aspx#Anchor_8
+ // For example: 2009-06-15T13:45:30.0000000
+ return dateTime.ToString((configuration ?? GlobalConfiguration.Instance).DateTimeFormat);
+ if (obj is DateTimeOffset dateTimeOffset)
+ // Return a formatted date string - Can be customized with Configuration.DateTimeFormat
+ // Defaults to an ISO 8601, using the known as a Round-trip date/time pattern ("o")
+ // https://msdn.microsoft.com/en-us/library/az4se3k1(v=vs.110).aspx#Anchor_8
+ // For example: 2009-06-15T13:45:30.0000000
+ return dateTimeOffset.ToString((configuration ?? GlobalConfiguration.Instance).DateTimeFormat);
+ if (obj is DateOnly dateOnly)
+ // Return a formatted date string - Can be customized with Configuration.DateTimeFormat
+ // Defaults to an ISO 8601, using the known as a Round-trip date/time pattern ("o")
+ // https://msdn.microsoft.com/en-us/library/az4se3k1(v=vs.110).aspx#Anchor_8
+ // For example: 2009-06-15
+ return dateOnly.ToString((configuration ?? GlobalConfiguration.Instance).DateTimeFormat);
+ if (obj is bool boolean)
+ return boolean ? "true" : "false";
+ if (obj is ICollection collection) {
+ List entries = new List();
+ foreach (var entry in collection)
+ entries.Add(ParameterToString(entry, configuration));
+ return string.Join(",", entries);
+ }
+ if (obj is Enum && HasEnumMemberAttrValue(obj))
+ return GetEnumMemberAttrValue(obj);
+
+ return Convert.ToString(obj, CultureInfo.InvariantCulture);
+ }
+
+ ///
+ /// Serializes the given object when not null. Otherwise return null.
+ ///
+ /// The object to serialize.
+ /// Serialized string.
+ public static string Serialize(object obj)
+ {
+ return obj != null ? Newtonsoft.Json.JsonConvert.SerializeObject(obj) : null;
+ }
+
+ ///
+ /// Encode string in base64 format.
+ ///
+ /// string to be encoded.
+ /// Encoded string.
+ public static string Base64Encode(string text)
+ {
+ return Convert.ToBase64String(global::System.Text.Encoding.UTF8.GetBytes(text));
+ }
+
+ ///
+ /// Convert stream to byte array
+ ///
+ /// Input stream to be converted
+ /// Byte array
+ public static byte[] ReadAsBytes(Stream inputStream)
+ {
+ using (var ms = new MemoryStream())
+ {
+ inputStream.CopyTo(ms);
+ return ms.ToArray();
+ }
+ }
+
+ ///
+ /// Select the Content-Type header's value from the given content-type array:
+ /// if JSON type exists in the given array, use it;
+ /// otherwise use the first one defined in 'consumes'
+ ///
+ /// The Content-Type array to select from.
+ /// The Content-Type header to use.
+ public static string SelectHeaderContentType(string[] contentTypes)
+ {
+ if (contentTypes.Length == 0)
+ return null;
+
+ foreach (var contentType in contentTypes)
+ {
+ if (IsJsonMime(contentType))
+ return contentType;
+ }
+
+ return contentTypes[0]; // use the first content type specified in 'consumes'
+ }
+
+ ///
+ /// Select the Accept header's value from the given accepts array:
+ /// if JSON exists in the given array, use it;
+ /// otherwise use all of them (joining into a string)
+ ///
+ /// The accepts array to select from.
+ /// The Accept header to use.
+ public static string SelectHeaderAccept(string[] accepts)
+ {
+ if (accepts.Length == 0)
+ return null;
+
+ if (accepts.Contains("application/json", StringComparer.OrdinalIgnoreCase))
+ return "application/json";
+
+ return string.Join(",", accepts);
+ }
+
+ ///
+ /// Provides a case-insensitive check that a provided content type is a known JSON-like content type.
+ ///
+ public static readonly Regex JsonRegex = new Regex("(?i)^(application/json|[^;/ \t]+/[^;/ \t]+[+]json)[ \t]*(;.*)?$");
+
+ ///
+ /// Check if the given MIME is a JSON MIME.
+ /// JSON MIME examples:
+ /// application/json
+ /// application/json; charset=UTF8
+ /// APPLICATION/JSON
+ /// application/vnd.company+json
+ ///
+ /// MIME
+ /// Returns True if MIME type is json.
+ public static bool IsJsonMime(string mime)
+ {
+ if (string.IsNullOrWhiteSpace(mime)) return false;
+
+ return JsonRegex.IsMatch(mime) || mime.Equals("application/json-patch+json");
+ }
+
+ ///
+ /// Is the Enum decorated with EnumMember Attribute
+ ///
+ ///
+ /// true if found
+ private static bool HasEnumMemberAttrValue(object enumVal)
+ {
+ if (enumVal == null)
+ throw new ArgumentNullException(nameof(enumVal));
+ var enumType = enumVal.GetType();
+ var memInfo = enumType.GetMember(enumVal.ToString() ?? throw new InvalidOperationException());
+ var attr = memInfo.FirstOrDefault()?.GetCustomAttributes(false).OfType().FirstOrDefault();
+ if (attr != null) return true;
+ return false;
+ }
+
+ ///
+ /// Get the EnumMember value
+ ///
+ ///
+ /// EnumMember value as string otherwise null
+ private static string GetEnumMemberAttrValue(object enumVal)
+ {
+ if (enumVal == null)
+ throw new ArgumentNullException(nameof(enumVal));
+ var enumType = enumVal.GetType();
+ var memInfo = enumType.GetMember(enumVal.ToString() ?? throw new InvalidOperationException());
+ var attr = memInfo.FirstOrDefault()?.GetCustomAttributes(false).OfType().FirstOrDefault();
+ if (attr != null)
+ {
+ return attr.Value;
+ }
+ return null;
+ }
+ }
+}
diff --git a/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/src/Org.OpenAPITools/Client/Configuration.cs b/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/src/Org.OpenAPITools/Client/Configuration.cs
new file mode 100644
index 00000000000..35b89b430a8
--- /dev/null
+++ b/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/src/Org.OpenAPITools/Client/Configuration.cs
@@ -0,0 +1,648 @@
+/*
+ * OpenAPI Petstore
+ *
+ * This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
+ *
+ * The version of the OpenAPI document: 1.0.0
+ * Generated by: https://github.com/openapitools/openapi-generator.git
+ */
+
+
+using System;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Net;
+using System.Reflection;
+using System.Security.Cryptography.X509Certificates;
+using System.Text;
+using System.Net.Http;
+using System.Net.Security;
+using Org.OpenAPITools.Client.Auth;
+
+namespace Org.OpenAPITools.Client
+{
+ ///
+ /// Represents a set of configuration settings
+ ///
+ public class Configuration : IReadableConfiguration
+ {
+ #region Constants
+
+ ///
+ /// Version of the package.
+ ///
+ /// Version of the package.
+ public const string Version = "1.0.0";
+
+ ///
+ /// Identifier for ISO 8601 DateTime Format
+ ///
+ /// See https://msdn.microsoft.com/en-us/library/az4se3k1(v=vs.110).aspx#Anchor_8 for more information.
+ // ReSharper disable once InconsistentNaming
+ public const string ISO8601_DATETIME_FORMAT = "o";
+
+ #endregion Constants
+
+ #region Static Members
+
+ ///
+ /// Default creation of exceptions for a given method name and response object
+ ///
+ public static readonly ExceptionFactory DefaultExceptionFactory = (methodName, response) =>
+ {
+ var status = (int)response.StatusCode;
+ if (status >= 400)
+ {
+ return new ApiException(status,
+ string.Format("Error calling {0}: {1}", methodName, response.RawContent),
+ response.RawContent, response.Headers);
+ }
+ if (status == 0)
+ {
+ return new ApiException(status,
+ string.Format("Error calling {0}: {1}", methodName, response.ErrorText), response.ErrorText);
+ }
+ return null;
+ };
+
+ #endregion Static Members
+
+ #region Private Members
+
+ ///
+ /// Defines the base path of the target API server.
+ /// Example: http://localhost:3000/v1/
+ ///
+ private string _basePath;
+
+ private bool _useDefaultCredentials = false;
+
+ ///
+ /// Gets or sets the API key based on the authentication name.
+ /// This is the key and value comprising the "secret" for accessing an API.
+ ///
+ /// The API key.
+ private IDictionary _apiKey;
+
+ ///
+ /// Gets or sets the prefix (e.g. Token) of the API key based on the authentication name.
+ ///
+ /// The prefix of the API key.
+ private IDictionary _apiKeyPrefix;
+
+ private string _dateTimeFormat = ISO8601_DATETIME_FORMAT;
+ private string _tempFolderPath = Path.GetTempPath();
+
+ ///
+ /// Gets or sets the servers defined in the OpenAPI spec.
+ ///
+ /// The servers
+ private IList> _servers;
+
+ ///
+ /// Gets or sets the operation servers defined in the OpenAPI spec.
+ ///
+ /// The operation servers
+ private IReadOnlyDictionary>> _operationServers;
+
+ #endregion Private Members
+
+ #region Constructors
+
+ ///
+ /// Initializes a new instance of the class
+ ///
+ [global::System.Diagnostics.CodeAnalysis.SuppressMessage("ReSharper", "VirtualMemberCallInConstructor")]
+ public Configuration()
+ {
+ Proxy = null;
+ UserAgent = WebUtility.UrlEncode("OpenAPI-Generator/1.0.0/csharp");
+ BasePath = "http://petstore.swagger.io/v2";
+ DefaultHeaders = new ConcurrentDictionary();
+ ApiKey = new ConcurrentDictionary();
+ ApiKeyPrefix = new ConcurrentDictionary();
+ Servers = new List>()
+ {
+ {
+ new Dictionary {
+ {"url", "http://petstore.swagger.io/v2"},
+ {"description", "No description provided"},
+ }
+ }
+ };
+ OperationServers = new Dictionary>>()
+ {
+ };
+
+ // Setting Timeout has side effects (forces ApiClient creation).
+ Timeout = TimeSpan.FromSeconds(100);
+ }
+
+ ///
+ /// Initializes a new instance of the class
+ ///
+ [global::System.Diagnostics.CodeAnalysis.SuppressMessage("ReSharper", "VirtualMemberCallInConstructor")]
+ public Configuration(
+ IDictionary defaultHeaders,
+ IDictionary apiKey,
+ IDictionary apiKeyPrefix,
+ string basePath = "http://petstore.swagger.io/v2") : this()
+ {
+ if (string.IsNullOrWhiteSpace(basePath))
+ throw new ArgumentException("The provided basePath is invalid.", "basePath");
+ if (defaultHeaders == null)
+ throw new ArgumentNullException("defaultHeaders");
+ if (apiKey == null)
+ throw new ArgumentNullException("apiKey");
+ if (apiKeyPrefix == null)
+ throw new ArgumentNullException("apiKeyPrefix");
+
+ BasePath = basePath;
+
+ foreach (var keyValuePair in defaultHeaders)
+ {
+ DefaultHeaders.Add(keyValuePair);
+ }
+
+ foreach (var keyValuePair in apiKey)
+ {
+ ApiKey.Add(keyValuePair);
+ }
+
+ foreach (var keyValuePair in apiKeyPrefix)
+ {
+ ApiKeyPrefix.Add(keyValuePair);
+ }
+ }
+
+ #endregion Constructors
+
+ #region Properties
+
+ ///
+ /// Gets or sets the base path for API access.
+ ///
+ public virtual string BasePath
+ {
+ get { return _basePath; }
+ set { _basePath = value; }
+ }
+
+ ///
+ /// Determine whether or not the "default credentials" (e.g. the user account under which the current process is running) will be sent along to the server. The default is false.
+ ///
+ public virtual bool UseDefaultCredentials
+ {
+ get { return _useDefaultCredentials; }
+ set { _useDefaultCredentials = value; }
+ }
+
+ ///
+ /// Gets or sets the default header.
+ ///
+ [Obsolete("Use DefaultHeaders instead.")]
+ public virtual IDictionary DefaultHeader
+ {
+ get
+ {
+ return DefaultHeaders;
+ }
+ set
+ {
+ DefaultHeaders = value;
+ }
+ }
+
+ ///
+ /// Gets or sets the default headers.
+ ///
+ public virtual IDictionary DefaultHeaders { get; set; }
+
+ ///
+ /// Gets or sets the HTTP timeout of ApiClient. Defaults to 100 seconds.
+ ///
+ public virtual TimeSpan Timeout { get; set; }
+
+ ///
+ /// Gets or sets the proxy
+ ///
+ /// Proxy.
+ public virtual WebProxy Proxy { get; set; }
+
+ ///
+ /// Gets or sets the HTTP user agent.
+ ///
+ /// Http user agent.
+ public virtual string UserAgent { get; set; }
+
+ ///
+ /// Gets or sets the username (HTTP basic authentication).
+ ///
+ /// The username.
+ public virtual string Username { get; set; }
+
+ ///
+ /// Gets or sets the password (HTTP basic authentication).
+ ///
+ /// The password.
+ public virtual string Password { get; set; }
+
+ ///
+ /// Gets the API key with prefix.
+ ///
+ /// API key identifier (authentication scheme).
+ /// API key with prefix.
+ public string GetApiKeyWithPrefix(string apiKeyIdentifier)
+ {
+ string apiKeyValue;
+ ApiKey.TryGetValue(apiKeyIdentifier, out apiKeyValue);
+ string apiKeyPrefix;
+ if (ApiKeyPrefix.TryGetValue(apiKeyIdentifier, out apiKeyPrefix))
+ {
+ return apiKeyPrefix + " " + apiKeyValue;
+ }
+
+ return apiKeyValue;
+ }
+
+ ///
+ /// Gets or sets certificate collection to be sent with requests.
+ ///
+ /// X509 Certificate collection.
+ public X509CertificateCollection ClientCertificates { get; set; }
+
+ ///
+ /// Gets or sets the access token for OAuth2 authentication.
+ ///
+ /// This helper property simplifies code generation.
+ ///
+ /// The access token.
+ public virtual string AccessToken { get; set; }
+
+ ///
+ /// Gets or sets the token URL for OAuth2 authentication.
+ ///
+ /// The OAuth Token URL.
+ public virtual string OAuthTokenUrl { get; set; }
+
+ ///
+ /// Gets or sets the client ID for OAuth2 authentication.
+ ///
+ /// The OAuth Client ID.
+ public virtual string OAuthClientId { get; set; }
+
+ ///
+ /// Gets or sets the client secret for OAuth2 authentication.
+ ///
+ /// The OAuth Client Secret.
+ public virtual string OAuthClientSecret { get; set; }
+
+ ///
+ /// Gets or sets the client scope for OAuth2 authentication.
+ ///
+ /// The OAuth Client Scope.
+ public virtual string? OAuthScope { get; set; }
+
+ ///
+ /// Gets or sets the flow for OAuth2 authentication.
+ ///
+ /// The OAuth Flow.
+ public virtual OAuthFlow? OAuthFlow { get; set; }
+
+ ///
+ /// Gets or sets the temporary folder path to store the files downloaded from the server.
+ ///
+ /// Folder path.
+ public virtual string TempFolderPath
+ {
+ get { return _tempFolderPath; }
+
+ set
+ {
+ if (string.IsNullOrEmpty(value))
+ {
+ _tempFolderPath = Path.GetTempPath();
+ return;
+ }
+
+ // create the directory if it does not exist
+ if (!Directory.Exists(value))
+ {
+ Directory.CreateDirectory(value);
+ }
+
+ // check if the path contains directory separator at the end
+ if (value[value.Length - 1] == Path.DirectorySeparatorChar)
+ {
+ _tempFolderPath = value;
+ }
+ else
+ {
+ _tempFolderPath = value + Path.DirectorySeparatorChar;
+ }
+ }
+ }
+
+ ///
+ /// Gets or sets the date time format used when serializing in the ApiClient
+ /// By default, it's set to ISO 8601 - "o", for others see:
+ /// https://msdn.microsoft.com/en-us/library/az4se3k1(v=vs.110).aspx
+ /// and https://msdn.microsoft.com/en-us/library/8kb3ddd4(v=vs.110).aspx
+ /// No validation is done to ensure that the string you're providing is valid
+ ///
+ /// The DateTimeFormat string
+ public virtual string DateTimeFormat
+ {
+ get { return _dateTimeFormat; }
+ set
+ {
+ if (string.IsNullOrEmpty(value))
+ {
+ // Never allow a blank or null string, go back to the default
+ _dateTimeFormat = ISO8601_DATETIME_FORMAT;
+ return;
+ }
+
+ // Caution, no validation when you choose date time format other than ISO 8601
+ // Take a look at the above links
+ _dateTimeFormat = value;
+ }
+ }
+
+ ///
+ /// Gets or sets the prefix (e.g. Token) of the API key based on the authentication name.
+ ///
+ /// Whatever you set here will be prepended to the value defined in AddApiKey.
+ ///
+ /// An example invocation here might be:
+ ///
+ /// ApiKeyPrefix["Authorization"] = "Bearer";
+ ///
+ /// … where ApiKey["Authorization"] would then be used to set the value of your bearer token.
+ ///
+ ///
+ /// OAuth2 workflows should set tokens via AccessToken.
+ ///
+ ///
+ /// The prefix of the API key.
+ public virtual IDictionary ApiKeyPrefix
+ {
+ get { return _apiKeyPrefix; }
+ set
+ {
+ if (value == null)
+ {
+ throw new InvalidOperationException("ApiKeyPrefix collection may not be null.");
+ }
+ _apiKeyPrefix = value;
+ }
+ }
+
+ ///
+ /// Gets or sets the API key based on the authentication name.
+ ///
+ /// The API key.
+ public virtual IDictionary ApiKey
+ {
+ get { return _apiKey; }
+ set
+ {
+ if (value == null)
+ {
+ throw new InvalidOperationException("ApiKey collection may not be null.");
+ }
+ _apiKey = value;
+ }
+ }
+
+ ///
+ /// Gets or sets the servers.
+ ///
+ /// The servers.
+ public virtual IList> Servers
+ {
+ get { return _servers; }
+ set
+ {
+ if (value == null)
+ {
+ throw new InvalidOperationException("Servers may not be null.");
+ }
+ _servers = value;
+ }
+ }
+
+ ///
+ /// Gets or sets the operation servers.
+ ///
+ /// The operation servers.
+ public virtual IReadOnlyDictionary>> OperationServers
+ {
+ get { return _operationServers; }
+ set
+ {
+ if (value == null)
+ {
+ throw new InvalidOperationException("Operation servers may not be null.");
+ }
+ _operationServers = value;
+ }
+ }
+
+ ///
+ /// Returns URL based on server settings without providing values
+ /// for the variables
+ ///
+ /// Array index of the server settings.
+ /// The server URL.
+ public string GetServerUrl(int index)
+ {
+ return GetServerUrl(Servers, index, null);
+ }
+
+ ///
+ /// Returns URL based on server settings.
+ ///
+ /// Array index of the server settings.
+ /// Dictionary of the variables and the corresponding values.
+ /// The server URL.
+ public string GetServerUrl(int index, Dictionary inputVariables)
+ {
+ return GetServerUrl(Servers, index, inputVariables);
+ }
+
+ ///
+ /// Returns URL based on operation server settings.
+ ///
+ /// Operation associated with the request path.
+ /// Array index of the server settings.
+ /// The operation server URL.
+ public string GetOperationServerUrl(string operation, int index)
+ {
+ return GetOperationServerUrl(operation, index, null);
+ }
+
+ ///
+ /// Returns URL based on operation server settings.
+ ///
+ /// Operation associated with the request path.
+ /// Array index of the server settings.
+ /// Dictionary of the variables and the corresponding values.
+ /// The operation server URL.
+ public string GetOperationServerUrl(string operation, int index, Dictionary inputVariables)
+ {
+ if (operation != null && OperationServers.TryGetValue(operation, out var operationServer))
+ {
+ return GetServerUrl(operationServer, index, inputVariables);
+ }
+
+ return null;
+ }
+
+ ///
+ /// Returns URL based on server settings.
+ ///
+ /// Dictionary of server settings.
+ /// Array index of the server settings.
+ /// Dictionary of the variables and the corresponding values.
+ /// The server URL.
+ private string GetServerUrl(IList> servers, int index, Dictionary inputVariables)
+ {
+ if (index < 0 || index >= servers.Count)
+ {
+ throw new InvalidOperationException($"Invalid index {index} when selecting the server. Must be less than {servers.Count}.");
+ }
+
+ if (inputVariables == null)
+ {
+ inputVariables = new Dictionary();
+ }
+
+ IReadOnlyDictionary server = servers[index];
+ string url = (string)server["url"];
+
+ if (server.ContainsKey("variables"))
+ {
+ // go through each variable and assign a value
+ foreach (KeyValuePair variable in (IReadOnlyDictionary)server["variables"])
+ {
+
+ IReadOnlyDictionary serverVariables = (IReadOnlyDictionary)(variable.Value);
+
+ if (inputVariables.ContainsKey(variable.Key))
+ {
+ if (((List)serverVariables["enum_values"]).Contains(inputVariables[variable.Key]))
+ {
+ url = url.Replace("{" + variable.Key + "}", inputVariables[variable.Key]);
+ }
+ else
+ {
+ throw new InvalidOperationException($"The variable `{variable.Key}` in the server URL has invalid value #{inputVariables[variable.Key]}. Must be {(List)serverVariables["enum_values"]}");
+ }
+ }
+ else
+ {
+ // use default value
+ url = url.Replace("{" + variable.Key + "}", (string)serverVariables["default_value"]);
+ }
+ }
+ }
+
+ return url;
+ }
+
+ ///
+ /// Gets and Sets the RemoteCertificateValidationCallback
+ ///
+ public RemoteCertificateValidationCallback RemoteCertificateValidationCallback { get; set; }
+
+ #endregion Properties
+
+ #region Methods
+
+ ///
+ /// Returns a string with essential information for debugging.
+ ///
+ public static string ToDebugReport()
+ {
+ string report = "C# SDK (Org.OpenAPITools) Debug Report:\n";
+ report += " OS: " + System.Environment.OSVersion + "\n";
+ report += " .NET Framework Version: " + System.Environment.Version + "\n";
+ report += " Version of the API: 1.0.0\n";
+ report += " SDK Package Version: 1.0.0\n";
+
+ return report;
+ }
+
+ ///
+ /// Add Api Key Header.
+ ///
+ /// Api Key name.
+ /// Api Key value.
+ ///
+ public void AddApiKey(string key, string value)
+ {
+ ApiKey[key] = value;
+ }
+
+ ///
+ /// Sets the API key prefix.
+ ///
+ /// Api Key name.
+ /// Api Key value.
+ public void AddApiKeyPrefix(string key, string value)
+ {
+ ApiKeyPrefix[key] = value;
+ }
+
+ #endregion Methods
+
+ #region Static Members
+ ///
+ /// Merge configurations.
+ ///
+ /// First configuration.
+ /// Second configuration.
+ /// Merged configuration.
+ public static IReadableConfiguration MergeConfigurations(IReadableConfiguration first, IReadableConfiguration second)
+ {
+ if (second == null) return first ?? GlobalConfiguration.Instance;
+
+ Dictionary apiKey = first.ApiKey.ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
+ Dictionary apiKeyPrefix = first.ApiKeyPrefix.ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
+ Dictionary defaultHeaders = first.DefaultHeaders.ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
+
+ foreach (var kvp in second.ApiKey) apiKey[kvp.Key] = kvp.Value;
+ foreach (var kvp in second.ApiKeyPrefix) apiKeyPrefix[kvp.Key] = kvp.Value;
+ foreach (var kvp in second.DefaultHeaders) defaultHeaders[kvp.Key] = kvp.Value;
+
+ var config = new Configuration
+ {
+ ApiKey = apiKey,
+ ApiKeyPrefix = apiKeyPrefix,
+ DefaultHeaders = defaultHeaders,
+ BasePath = second.BasePath ?? first.BasePath,
+ Timeout = second.Timeout,
+ Proxy = second.Proxy ?? first.Proxy,
+ UserAgent = second.UserAgent ?? first.UserAgent,
+ Username = second.Username ?? first.Username,
+ Password = second.Password ?? first.Password,
+ AccessToken = second.AccessToken ?? first.AccessToken,
+ OAuthTokenUrl = second.OAuthTokenUrl ?? first.OAuthTokenUrl,
+ OAuthClientId = second.OAuthClientId ?? first.OAuthClientId,
+ OAuthClientSecret = second.OAuthClientSecret ?? first.OAuthClientSecret,
+ OAuthScope = second.OAuthScope ?? first.OAuthScope,
+ OAuthFlow = second.OAuthFlow ?? first.OAuthFlow,
+ TempFolderPath = second.TempFolderPath ?? first.TempFolderPath,
+ DateTimeFormat = second.DateTimeFormat ?? first.DateTimeFormat,
+ ClientCertificates = second.ClientCertificates ?? first.ClientCertificates,
+ UseDefaultCredentials = second.UseDefaultCredentials,
+ RemoteCertificateValidationCallback = second.RemoteCertificateValidationCallback ?? first.RemoteCertificateValidationCallback,
+ };
+ return config;
+ }
+ #endregion Static Members
+ }
+}
diff --git a/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/src/Org.OpenAPITools/Client/ExceptionFactory.cs b/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/src/Org.OpenAPITools/Client/ExceptionFactory.cs
new file mode 100644
index 00000000000..6ae2a10aae4
--- /dev/null
+++ b/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/src/Org.OpenAPITools/Client/ExceptionFactory.cs
@@ -0,0 +1,22 @@
+/*
+ * OpenAPI Petstore
+ *
+ * This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
+ *
+ * The version of the OpenAPI document: 1.0.0
+ * Generated by: https://github.com/openapitools/openapi-generator.git
+ */
+
+
+using System;
+
+namespace Org.OpenAPITools.Client
+{
+ ///
+ /// A delegate to ExceptionFactory method
+ ///
+ /// Method name
+ /// Response
+ /// Exceptions
+ public delegate Exception ExceptionFactory(string methodName, IApiResponse response);
+}
diff --git a/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/src/Org.OpenAPITools/Client/GlobalConfiguration.cs b/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/src/Org.OpenAPITools/Client/GlobalConfiguration.cs
new file mode 100644
index 00000000000..add21c02cd1
--- /dev/null
+++ b/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/src/Org.OpenAPITools/Client/GlobalConfiguration.cs
@@ -0,0 +1,67 @@
+/*
+ * OpenAPI Petstore
+ *
+ * This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
+ *
+ * The version of the OpenAPI document: 1.0.0
+ * Generated by: https://github.com/openapitools/openapi-generator.git
+ */
+
+
+using System.Collections.Generic;
+
+namespace Org.OpenAPITools.Client
+{
+ ///
+ /// provides a compile-time extension point for globally configuring
+ /// API Clients.
+ ///
+ ///
+ /// A customized implementation via partial class may reside in another file and may
+ /// be excluded from automatic generation via a .openapi-generator-ignore file.
+ ///
+ public partial class GlobalConfiguration : Configuration
+ {
+ #region Private Members
+
+ private static readonly object GlobalConfigSync = new { };
+ private static IReadableConfiguration _globalConfiguration;
+
+ #endregion Private Members
+
+ #region Constructors
+
+ ///
+ private GlobalConfiguration()
+ {
+ }
+
+ ///
+ public GlobalConfiguration(IDictionary defaultHeader, IDictionary apiKey, IDictionary apiKeyPrefix, string basePath = "http://localhost:3000/api") : base(defaultHeader, apiKey, apiKeyPrefix, basePath)
+ {
+ }
+
+ static GlobalConfiguration()
+ {
+ Instance = new GlobalConfiguration();
+ }
+
+ #endregion Constructors
+
+ ///
+ /// Gets or sets the default Configuration.
+ ///
+ /// Configuration.
+ public static IReadableConfiguration Instance
+ {
+ get { return _globalConfiguration; }
+ set
+ {
+ lock (GlobalConfigSync)
+ {
+ _globalConfiguration = value;
+ }
+ }
+ }
+ }
+}
diff --git a/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/src/Org.OpenAPITools/Client/HttpMethod.cs b/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/src/Org.OpenAPITools/Client/HttpMethod.cs
new file mode 100644
index 00000000000..1dd692d8cfb
--- /dev/null
+++ b/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/src/Org.OpenAPITools/Client/HttpMethod.cs
@@ -0,0 +1,33 @@
+/*
+ * OpenAPI Petstore
+ *
+ * This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
+ *
+ * The version of the OpenAPI document: 1.0.0
+ * Generated by: https://github.com/openapitools/openapi-generator.git
+ */
+
+
+namespace Org.OpenAPITools.Client
+{
+ ///
+ /// Http methods supported by swagger
+ ///
+ public enum HttpMethod
+ {
+ /// HTTP GET request.
+ Get,
+ /// HTTP POST request.
+ Post,
+ /// HTTP PUT request.
+ Put,
+ /// HTTP DELETE request.
+ Delete,
+ /// HTTP HEAD request.
+ Head,
+ /// HTTP OPTIONS request.
+ Options,
+ /// HTTP PATCH request.
+ Patch
+ }
+}
diff --git a/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/src/Org.OpenAPITools/Client/IApiAccessor.cs b/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/src/Org.OpenAPITools/Client/IApiAccessor.cs
new file mode 100644
index 00000000000..c8a78e995ce
--- /dev/null
+++ b/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/src/Org.OpenAPITools/Client/IApiAccessor.cs
@@ -0,0 +1,37 @@
+/*
+ * OpenAPI Petstore
+ *
+ * This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
+ *
+ * The version of the OpenAPI document: 1.0.0
+ * Generated by: https://github.com/openapitools/openapi-generator.git
+ */
+
+
+using System;
+
+namespace Org.OpenAPITools.Client
+{
+ ///
+ /// Represents configuration aspects required to interact with the API endpoints.
+ ///
+ public interface IApiAccessor
+ {
+ ///
+ /// Gets or sets the configuration object
+ ///
+ /// An instance of the Configuration
+ IReadableConfiguration Configuration { get; set; }
+
+ ///
+ /// Gets the base path of the API client.
+ ///
+ /// The base path
+ string GetBasePath();
+
+ ///
+ /// Provides a factory method hook for the creation of exceptions.
+ ///
+ ExceptionFactory ExceptionFactory { get; set; }
+ }
+}
diff --git a/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/src/Org.OpenAPITools/Client/IAsynchronousClient.cs b/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/src/Org.OpenAPITools/Client/IAsynchronousClient.cs
new file mode 100644
index 00000000000..fcb4df9b488
--- /dev/null
+++ b/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/src/Org.OpenAPITools/Client/IAsynchronousClient.cs
@@ -0,0 +1,100 @@
+/*
+ * OpenAPI Petstore
+ *
+ * This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
+ *
+ * The version of the OpenAPI document: 1.0.0
+ * Generated by: https://github.com/openapitools/openapi-generator.git
+ */
+
+
+using System;
+using System.Threading.Tasks;
+
+namespace Org.OpenAPITools.Client
+{
+ ///
+ /// Contract for Asynchronous RESTful API interactions.
+ ///
+ /// This interface allows consumers to provide a custom API accessor client.
+ ///
+ public interface IAsynchronousClient
+ {
+ ///
+ /// Executes a non-blocking call to some using the GET http verb.
+ ///
+ /// The relative path to invoke.
+ /// The request parameters to pass along to the client.
+ /// Per-request configurable settings.
+ /// Cancellation Token to cancel the request.
+ /// The return type.
+ /// A task eventually representing the response data, decorated with
+ Task> GetAsync(string path, RequestOptions options, IReadableConfiguration configuration = null, System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken));
+
+ ///
+ /// Executes a non-blocking call to some using the POST http verb.
+ ///
+ /// The relative path to invoke.
+ /// The request parameters to pass along to the client.
+ /// Per-request configurable settings.
+ /// Cancellation Token to cancel the request.
+ /// The return type.
+ /// A task eventually representing the response data, decorated with
+ Task> PostAsync(string path, RequestOptions options, IReadableConfiguration configuration = null, System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken));
+
+ ///
+ /// Executes a non-blocking call to some using the PUT http verb.
+ ///
+ /// The relative path to invoke.
+ /// The request parameters to pass along to the client.
+ /// Per-request configurable settings.
+ /// Cancellation Token to cancel the request.
+ /// The return type.
+ /// A task eventually representing the response data, decorated with
+ Task> PutAsync(string path, RequestOptions options, IReadableConfiguration configuration = null, System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken));
+
+ ///
+ /// Executes a non-blocking call to some using the DELETE http verb.
+ ///
+ /// The relative path to invoke.
+ /// The request parameters to pass along to the client.
+ /// Per-request configurable settings.
+ /// Cancellation Token to cancel the request.
+ /// The return type.
+ /// A task eventually representing the response data, decorated with
+ Task> DeleteAsync(string path, RequestOptions options, IReadableConfiguration configuration = null, System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken));
+
+ ///
+ /// Executes a non-blocking call to some using the HEAD http verb.
+ ///
+ /// The relative path to invoke.
+ /// The request parameters to pass along to the client.
+ /// Per-request configurable settings.
+ /// Cancellation Token to cancel the request.
+ /// The return type.
+ /// A task eventually representing the response data, decorated with
+ Task> HeadAsync(string path, RequestOptions options, IReadableConfiguration configuration = null, System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken));
+
+ ///
+ /// Executes a non-blocking call to some using the OPTIONS http verb.
+ ///
+ /// The relative path to invoke.
+ /// The request parameters to pass along to the client.
+ /// Per-request configurable settings.
+ /// Cancellation Token to cancel the request.
+ /// The return type.
+ /// A task eventually representing the response data, decorated with
+ Task> OptionsAsync(string path, RequestOptions options, IReadableConfiguration configuration = null, System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken));
+
+ ///
+ /// Executes a non-blocking call to some using the PATCH http verb.
+ ///
+ /// The relative path to invoke.
+ /// The request parameters to pass along to the client.
+ /// Per-request configurable settings.
+ /// Cancellation Token to cancel the request.
+ /// The return type.
+ /// A task eventually representing the response data, decorated with
+ Task> PatchAsync(string path, RequestOptions options, IReadableConfiguration configuration = null, System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken));
+ }
+}
diff --git a/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/src/Org.OpenAPITools/Client/IReadableConfiguration.cs b/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/src/Org.OpenAPITools/Client/IReadableConfiguration.cs
new file mode 100644
index 00000000000..1db047df067
--- /dev/null
+++ b/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/src/Org.OpenAPITools/Client/IReadableConfiguration.cs
@@ -0,0 +1,172 @@
+/*
+ * OpenAPI Petstore
+ *
+ * This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
+ *
+ * The version of the OpenAPI document: 1.0.0
+ * Generated by: https://github.com/openapitools/openapi-generator.git
+ */
+
+
+using System;
+using System.Collections.Generic;
+using System.Net;
+using System.Net.Security;
+using System.Security.Cryptography.X509Certificates;
+using Org.OpenAPITools.Client.Auth;
+
+namespace Org.OpenAPITools.Client
+{
+ ///
+ /// Represents a readable-only configuration contract.
+ ///
+ public interface IReadableConfiguration
+ {
+ ///
+ /// Gets the access token.
+ ///
+ /// Access token.
+ string AccessToken { get; }
+
+ ///
+ /// Gets the OAuth token URL.
+ ///
+ /// OAuth Token URL.
+ string OAuthTokenUrl { get; }
+
+ ///
+ /// Gets the OAuth client ID.
+ ///
+ /// OAuth Client ID.
+ string OAuthClientId { get; }
+
+ ///
+ /// Gets the OAuth client secret.
+ ///
+ /// OAuth Client Secret.
+ string OAuthClientSecret { get; }
+
+ ///
+ /// Gets the OAuth token scope.
+ ///
+ /// OAuth Token scope.
+ string? OAuthScope { get; }
+
+ ///
+ /// Gets the OAuth flow.
+ ///
+ /// OAuth Flow.
+ OAuthFlow? OAuthFlow { get; }
+
+ ///
+ /// Gets the API key.
+ ///
+ /// API key.
+ IDictionary ApiKey { get; }
+
+ ///
+ /// Gets the API key prefix.
+ ///
+ /// API key prefix.
+ IDictionary ApiKeyPrefix { get; }
+
+ ///
+ /// Gets the base path.
+ ///
+ /// Base path.
+ string BasePath { get; }
+
+ ///
+ /// Gets the date time format.
+ ///
+ /// Date time format.
+ string DateTimeFormat { get; }
+
+ ///
+ /// Gets the default header.
+ ///
+ /// Default header.
+ [Obsolete("Use DefaultHeaders instead.")]
+ IDictionary DefaultHeader { get; }
+
+ ///
+ /// Gets the default headers.
+ ///
+ /// Default headers.
+ IDictionary DefaultHeaders { get; }
+
+ ///
+ /// Gets the temp folder path.
+ ///
+ /// Temp folder path.
+ string TempFolderPath { get; }
+
+ ///
+ /// Gets the HTTP connection timeout.
+ ///
+ /// HTTP connection timeout.
+ TimeSpan Timeout { get; }
+
+ ///
+ /// Gets the proxy.
+ ///
+ /// Proxy.
+ WebProxy Proxy { get; }
+
+ ///
+ /// Gets the user agent.
+ ///
+ /// User agent.
+ string UserAgent { get; }
+
+ ///
+ /// Gets the username.
+ ///
+ /// Username.
+ string Username { get; }
+
+ ///
+ /// Gets the password.
+ ///
+ /// Password.
+ string Password { get; }
+
+ ///
+ /// Determine whether or not the "default credentials" (e.g. the user account under which the current process is running) will be sent along to the server. The default is false.
+ ///
+ bool UseDefaultCredentials { get; }
+
+ ///
+ /// Get the servers associated with the operation.
+ ///
+ /// Operation servers.
+ IReadOnlyDictionary>> OperationServers { get; }
+
+ ///
+ /// Gets the API key with prefix.
+ ///
+ /// API key identifier (authentication scheme).
+ /// API key with prefix.
+ string GetApiKeyWithPrefix(string apiKeyIdentifier);
+
+ ///
+ /// Gets the Operation server url at the provided index.
+ ///
+ /// Operation server name.
+ /// Index of the operation server settings.
+ ///
+ string GetOperationServerUrl(string operation, int index);
+
+ ///
+ /// Gets certificate collection to be sent with requests.
+ ///
+ /// X509 Certificate collection.
+ X509CertificateCollection ClientCertificates { get; }
+
+ ///
+ /// Callback function for handling the validation of remote certificates. Useful for certificate pinning and
+ /// overriding certificate errors in the scope of a request.
+ ///
+ RemoteCertificateValidationCallback RemoteCertificateValidationCallback { get; }
+ }
+}
diff --git a/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/src/Org.OpenAPITools/Client/ISynchronousClient.cs b/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/src/Org.OpenAPITools/Client/ISynchronousClient.cs
new file mode 100644
index 00000000000..3910f6d68ce
--- /dev/null
+++ b/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/src/Org.OpenAPITools/Client/ISynchronousClient.cs
@@ -0,0 +1,93 @@
+/*
+ * OpenAPI Petstore
+ *
+ * This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
+ *
+ * The version of the OpenAPI document: 1.0.0
+ * Generated by: https://github.com/openapitools/openapi-generator.git
+ */
+
+
+using System;
+using System.IO;
+
+namespace Org.OpenAPITools.Client
+{
+ ///
+ /// Contract for Synchronous RESTful API interactions.
+ ///
+ /// This interface allows consumers to provide a custom API accessor client.
+ ///
+ public interface ISynchronousClient
+ {
+ ///
+ /// Executes a blocking call to some using the GET http verb.
+ ///
+ /// The relative path to invoke.
+ /// The request parameters to pass along to the client.
+ /// Per-request configurable settings.
+ /// The return type.
+ /// The response data, decorated with
+ ApiResponse Get(string path, RequestOptions options, IReadableConfiguration configuration = null);
+
+ ///
+ /// Executes a blocking call to some using the POST http verb.
+ ///
+ /// The relative path to invoke.
+ /// The request parameters to pass along to the client.
+ /// Per-request configurable settings.
+ /// The return type.
+ /// The response data, decorated with
+ ApiResponse Post(string path, RequestOptions options, IReadableConfiguration configuration = null);
+
+ ///
+ /// Executes a blocking call to some using the PUT http verb.
+ ///
+ /// The relative path to invoke.
+ /// The request parameters to pass along to the client.
+ /// Per-request configurable settings.
+ /// The return type.
+ /// The response data, decorated with
+ ApiResponse Put(string path, RequestOptions options, IReadableConfiguration configuration = null);
+
+ ///
+ /// Executes a blocking call to some using the DELETE http verb.
+ ///
+ /// The relative path to invoke.
+ /// The request parameters to pass along to the client.
+ /// Per-request configurable settings.
+ /// The return type.
+ /// The response data, decorated with
+ ApiResponse Delete(string path, RequestOptions options, IReadableConfiguration configuration = null);
+
+ ///
+ /// Executes a blocking call to some using the HEAD http verb.
+ ///
+ /// The relative path to invoke.
+ /// The request parameters to pass along to the client.
+ /// Per-request configurable settings.
+ /// The return type.
+ /// The response data, decorated with
+ ApiResponse Head(string path, RequestOptions options, IReadableConfiguration configuration = null);
+
+ ///
+ /// Executes a blocking call to some using the OPTIONS http verb.
+ ///
+ /// The relative path to invoke.
+ /// The request parameters to pass along to the client.
+ /// Per-request configurable settings.
+ /// The return type.
+ /// The response data, decorated with
+ ApiResponse Options(string path, RequestOptions options, IReadableConfiguration configuration = null);
+
+ ///
+ /// Executes a blocking call to some using the PATCH http verb.
+ ///
+ /// The relative path to invoke.
+ /// The request parameters to pass along to the client.
+ /// Per-request configurable settings.
+ /// The return type.
+ /// The response data, decorated with
+ ApiResponse Patch(string path, RequestOptions options, IReadableConfiguration configuration = null);
+ }
+}
diff --git a/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/src/Org.OpenAPITools/Client/Multimap.cs b/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/src/Org.OpenAPITools/Client/Multimap.cs
new file mode 100644
index 00000000000..966d634a50b
--- /dev/null
+++ b/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/src/Org.OpenAPITools/Client/Multimap.cs
@@ -0,0 +1,295 @@
+/*
+ * OpenAPI Petstore
+ *
+ * This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
+ *
+ * The version of the OpenAPI document: 1.0.0
+ * Generated by: https://github.com/openapitools/openapi-generator.git
+ */
+
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+
+namespace Org.OpenAPITools.Client
+{
+ ///
+ /// A dictionary in which one key has many associated values.
+ ///
+ /// The type of the key
+ /// The type of the value associated with the key.
+ public class Multimap : IDictionary>
+ {
+ #region Private Fields
+
+ private readonly Dictionary> _dictionary;
+
+ #endregion Private Fields
+
+ #region Constructors
+
+ ///
+ /// Empty Constructor.
+ ///
+ public Multimap()
+ {
+ _dictionary = new Dictionary>();
+ }
+
+ ///
+ /// Constructor with comparer.
+ ///
+ ///
+ public Multimap(IEqualityComparer comparer)
+ {
+ _dictionary = new Dictionary>(comparer);
+ }
+
+ #endregion Constructors
+
+ #region Enumerators
+
+ ///
+ /// To get the enumerator.
+ ///
+ /// Enumerator
+ public IEnumerator>> GetEnumerator()
+ {
+ return _dictionary.GetEnumerator();
+ }
+
+ ///
+ /// To get the enumerator.
+ ///
+ /// Enumerator
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return _dictionary.GetEnumerator();
+ }
+
+ #endregion Enumerators
+
+ #region Public Members
+ ///
+ /// Add values to Multimap
+ ///
+ /// Key value pair
+ public void Add(KeyValuePair> item)
+ {
+ if (!TryAdd(item.Key, item.Value))
+ throw new InvalidOperationException("Could not add values to Multimap.");
+ }
+
+ ///
+ /// Add Multimap to Multimap
+ ///
+ /// Multimap
+ public void Add(Multimap multimap)
+ {
+ foreach (var item in multimap)
+ {
+ if (!TryAdd(item.Key, item.Value))
+ throw new InvalidOperationException("Could not add values to Multimap.");
+ }
+ }
+
+ ///
+ /// Clear Multimap
+ ///
+ public void Clear()
+ {
+ _dictionary.Clear();
+ }
+
+ ///
+ /// Determines whether Multimap contains the specified item.
+ ///
+ /// Key value pair
+ /// Method needs to be implemented
+ /// true if the Multimap contains the item; otherwise, false.
+ public bool Contains(KeyValuePair> item)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Copy items of the Multimap to an array,
+ /// starting at a particular array index.
+ ///
+ /// The array that is the destination of the items copied
+ /// from Multimap. The array must have zero-based indexing.
+ /// The zero-based index in array at which copying begins.
+ /// Method needs to be implemented
+ public void CopyTo(KeyValuePair>[] array, int arrayIndex)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Removes the specified item from the Multimap.
+ ///
+ /// Key value pair
+ /// true if the item is successfully removed; otherwise, false.
+ /// Method needs to be implemented
+ public bool Remove(KeyValuePair> item)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Gets the number of items contained in the Multimap.
+ ///
+ public int Count => _dictionary.Count;
+
+ ///
+ /// Gets a value indicating whether the Multimap is read-only.
+ ///
+ public bool IsReadOnly => false;
+
+ ///
+ /// Adds an item with the provided key and value to the Multimap.
+ ///
+ /// The object to use as the key of the item to add.
+ /// The object to use as the value of the item to add.
+ /// Thrown when couldn't add the value to Multimap.
+ public void Add(TKey key, IList value)
+ {
+ if (value != null && value.Count > 0)
+ {
+ if (_dictionary.TryGetValue(key, out var list))
+ {
+ foreach (var k in value) list.Add(k);
+ }
+ else
+ {
+ list = new List(value);
+ if (!TryAdd(key, list))
+ throw new InvalidOperationException("Could not add values to Multimap.");
+ }
+ }
+ }
+
+ ///
+ /// Determines whether the Multimap contains an item with the specified key.
+ ///
+ /// The key to locate in the Multimap.
+ /// true if the Multimap contains an item with
+ /// the key; otherwise, false.
+ public bool ContainsKey(TKey key)
+ {
+ return _dictionary.ContainsKey(key);
+ }
+
+ ///
+ /// Removes item with the specified key from the Multimap.
+ ///
+ /// The key to locate in the Multimap.
+ /// true if the item is successfully removed; otherwise, false.
+ public bool Remove(TKey key)
+ {
+ return TryRemove(key, out var _);
+ }
+
+ ///
+ /// Gets the value associated with the specified key.
+ ///
+ /// The key whose value to get.
+ /// When this method returns, the value associated with the specified key, if the
+ /// key is found; otherwise, the default value for the type of the value parameter.
+ /// This parameter is passed uninitialized.
+ /// true if the object that implements Multimap contains
+ /// an item with the specified key; otherwise, false.
+ public bool TryGetValue(TKey key, out IList value)
+ {
+ return _dictionary.TryGetValue(key, out value);
+ }
+
+ ///
+ /// Gets or sets the item with the specified key.
+ ///
+ /// The key of the item to get or set.
+ /// The value of the specified key.
+ public IList this[TKey key]
+ {
+ get => _dictionary[key];
+ set => _dictionary[key] = value;
+ }
+
+ ///
+ /// Gets a System.Collections.Generic.ICollection containing the keys of the Multimap.
+ ///
+ public ICollection Keys => _dictionary.Keys;
+
+ ///
+ /// Gets a System.Collections.Generic.ICollection containing the values of the Multimap.
+ ///
+ public ICollection> Values => _dictionary.Values;
+
+ ///
+ /// Copy the items of the Multimap to an System.Array,
+ /// starting at a particular System.Array index.
+ ///
+ /// The one-dimensional System.Array that is the destination of the items copied
+ /// from Multimap. The System.Array must have zero-based indexing.
+ /// The zero-based index in array at which copying begins.
+ public void CopyTo(Array array, int index)
+ {
+ ((ICollection)_dictionary).CopyTo(array, index);
+ }
+
+ ///
+ /// Adds an item with the provided key and value to the Multimap.
+ ///
+ /// The object to use as the key of the item to add.
+ /// The object to use as the value of the item to add.
+ /// Thrown when couldn't add value to Multimap.
+ public void Add(TKey key, TValue value)
+ {
+ if (value != null)
+ {
+ if (_dictionary.TryGetValue(key, out var list))
+ {
+ list.Add(value);
+ }
+ else
+ {
+ list = new List { value };
+ if (!TryAdd(key, list))
+ throw new InvalidOperationException("Could not add value to Multimap.");
+ }
+ }
+ }
+
+ #endregion Public Members
+
+ #region Private Members
+
+ /**
+ * Helper method to encapsulate generator differences between dictionary types.
+ */
+ private bool TryRemove(TKey key, out IList value)
+ {
+ _dictionary.TryGetValue(key, out value);
+ return _dictionary.Remove(key);
+ }
+
+ /**
+ * Helper method to encapsulate generator differences between dictionary types.
+ */
+ private bool TryAdd(TKey key, IList value)
+ {
+ try
+ {
+ _dictionary.Add(key, value);
+ }
+ catch (ArgumentException)
+ {
+ return false;
+ }
+
+ return true;
+ }
+ #endregion Private Members
+ }
+}
diff --git a/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/src/Org.OpenAPITools/Client/OpenAPIDateConverter.cs b/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/src/Org.OpenAPITools/Client/OpenAPIDateConverter.cs
new file mode 100644
index 00000000000..dcc79edd944
--- /dev/null
+++ b/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/src/Org.OpenAPITools/Client/OpenAPIDateConverter.cs
@@ -0,0 +1,29 @@
+/*
+ * OpenAPI Petstore
+ *
+ * This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
+ *
+ * The version of the OpenAPI document: 1.0.0
+ * Generated by: https://github.com/openapitools/openapi-generator.git
+ */
+
+using Newtonsoft.Json.Converters;
+
+namespace Org.OpenAPITools.Client
+{
+ ///
+ /// Formatter for 'date' openapi formats ss defined by full-date - RFC3339
+ /// see https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md#data-types
+ ///
+ public class OpenAPIDateConverter : IsoDateTimeConverter
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public OpenAPIDateConverter()
+ {
+ // full-date = date-fullyear "-" date-month "-" date-mday
+ DateTimeFormat = "yyyy-MM-dd";
+ }
+ }
+}
diff --git a/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/src/Org.OpenAPITools/Client/RequestOptions.cs b/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/src/Org.OpenAPITools/Client/RequestOptions.cs
new file mode 100644
index 00000000000..20366c4e7cc
--- /dev/null
+++ b/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/src/Org.OpenAPITools/Client/RequestOptions.cs
@@ -0,0 +1,89 @@
+/*
+ * OpenAPI Petstore
+ *
+ * This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
+ *
+ * The version of the OpenAPI document: 1.0.0
+ * Generated by: https://github.com/openapitools/openapi-generator.git
+ */
+
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Net;
+
+namespace Org.OpenAPITools.Client
+{
+ ///
+ /// A container for generalized request inputs. This type allows consumers to extend the request functionality
+ /// by abstracting away from the default (built-in) request framework (e.g. RestSharp).
+ ///
+ public class RequestOptions
+ {
+ ///
+ /// Parameters to be bound to path parts of the Request's URL
+ ///
+ public Dictionary PathParameters { get; set; }
+
+ ///
+ /// Query parameters to be applied to the request.
+ /// Keys may have 1 or more values associated.
+ ///
+ public Multimap QueryParameters { get; set; }
+
+ ///
+ /// Header parameters to be applied to the request.
+ /// Keys may have 1 or more values associated.
+ ///
+ public Multimap HeaderParameters { get; set; }
+
+ ///
+ /// Form parameters to be sent along with the request.
+ ///
+ public Dictionary FormParameters { get; set; }
+
+ ///
+ /// File parameters to be sent along with the request.
+ ///
+ public Multimap FileParameters { get; set; }
+
+ ///
+ /// Cookies to be sent along with the request.
+ ///
+ public List Cookies { get; set; }
+
+ ///
+ /// Operation associated with the request path.
+ ///
+ public string Operation { get; set; }
+
+ ///
+ /// Index associated with the operation.
+ ///
+ public int OperationIndex { get; set; }
+
+ ///
+ /// Any data associated with a request body.
+ ///
+ public Object Data { get; set; }
+
+ ///
+ /// If request should be authenticated with OAuth.
+ ///
+ public bool OAuth { get; set; }
+
+ ///
+ /// Constructs a new instance of
+ ///
+ public RequestOptions()
+ {
+ PathParameters = new Dictionary();
+ QueryParameters = new Multimap();
+ HeaderParameters = new Multimap();
+ FormParameters = new Dictionary();
+ FileParameters = new Multimap();
+ Cookies = new List();
+ }
+ }
+}
diff --git a/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/src/Org.OpenAPITools/Client/RetryConfiguration.cs b/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/src/Org.OpenAPITools/Client/RetryConfiguration.cs
new file mode 100644
index 00000000000..f9141a10005
--- /dev/null
+++ b/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/src/Org.OpenAPITools/Client/RetryConfiguration.cs
@@ -0,0 +1,31 @@
+/*
+ * OpenAPI Petstore
+ *
+ * This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
+ *
+ * The version of the OpenAPI document: 1.0.0
+ * Generated by: https://github.com/openapitools/openapi-generator.git
+ */
+
+
+using Polly;
+using RestSharp;
+
+namespace Org.OpenAPITools.Client
+{
+ ///
+ /// Configuration class to set the polly retry policies to be applied to the requests.
+ ///
+ public static class RetryConfiguration
+ {
+ ///
+ /// Retry policy
+ ///
+ public static Policy RetryPolicy { get; set; }
+
+ ///
+ /// Async retry policy
+ ///
+ public static AsyncPolicy AsyncRetryPolicy { get; set; }
+ }
+}
diff --git a/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/src/Org.OpenAPITools/Model/AbstractOpenAPISchema.cs b/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/src/Org.OpenAPITools/Model/AbstractOpenAPISchema.cs
new file mode 100644
index 00000000000..675bb752f4b
--- /dev/null
+++ b/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/src/Org.OpenAPITools/Model/AbstractOpenAPISchema.cs
@@ -0,0 +1,76 @@
+/*
+ * OpenAPI Petstore
+ *
+ * This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
+ *
+ * The version of the OpenAPI document: 1.0.0
+ * Generated by: https://github.com/openapitools/openapi-generator.git
+ */
+
+
+using System;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Serialization;
+
+namespace Org.OpenAPITools.Model
+{
+ ///
+ /// Abstract base class for oneOf, anyOf schemas in the OpenAPI specification
+ ///
+ public abstract partial class AbstractOpenAPISchema
+ {
+ ///
+ /// Custom JSON serializer
+ ///
+ static public readonly JsonSerializerSettings SerializerSettings = new JsonSerializerSettings
+ {
+ // OpenAPI generated types generally hide default constructors.
+ ConstructorHandling = ConstructorHandling.AllowNonPublicDefaultConstructor,
+ MissingMemberHandling = MissingMemberHandling.Error,
+ ContractResolver = new DefaultContractResolver
+ {
+ NamingStrategy = new CamelCaseNamingStrategy
+ {
+ OverrideSpecifiedNames = false
+ }
+ }
+ };
+
+ ///
+ /// Custom JSON serializer for objects with additional properties
+ ///
+ static public readonly JsonSerializerSettings AdditionalPropertiesSerializerSettings = new JsonSerializerSettings
+ {
+ // OpenAPI generated types generally hide default constructors.
+ ConstructorHandling = ConstructorHandling.AllowNonPublicDefaultConstructor,
+ MissingMemberHandling = MissingMemberHandling.Ignore,
+ ContractResolver = new DefaultContractResolver
+ {
+ NamingStrategy = new CamelCaseNamingStrategy
+ {
+ OverrideSpecifiedNames = false
+ }
+ }
+ };
+
+ ///
+ /// Gets or Sets the actual instance
+ ///
+ public abstract Object ActualInstance { get; set; }
+
+ ///
+ /// Gets or Sets IsNullable to indicate whether the instance is nullable
+ ///
+ public bool IsNullable { get; protected set; }
+
+ ///
+ /// Gets or Sets the schema type, which can be either `oneOf` or `anyOf`
+ ///
+ public string SchemaType { get; protected set; }
+
+ ///
+ /// Converts the instance into JSON string.
+ ///
+ public abstract string ToJson();
+ }
+}
diff --git a/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/src/Org.OpenAPITools/Model/Category.cs b/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/src/Org.OpenAPITools/Model/Category.cs
new file mode 100644
index 00000000000..f2702140eda
--- /dev/null
+++ b/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/src/Org.OpenAPITools/Model/Category.cs
@@ -0,0 +1,100 @@
+/*
+ * OpenAPI Petstore
+ *
+ * This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
+ *
+ * The version of the OpenAPI document: 1.0.0
+ * Generated by: https://github.com/openapitools/openapi-generator.git
+ */
+
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Linq;
+using System.IO;
+using System.Runtime.Serialization;
+using System.Text;
+using System.Text.RegularExpressions;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Converters;
+using Newtonsoft.Json.Linq;
+using System.ComponentModel.DataAnnotations;
+using OpenAPIDateConverter = Org.OpenAPITools.Client.OpenAPIDateConverter;
+
+namespace Org.OpenAPITools.Model
+{
+ ///
+ /// A category for a pet
+ ///
+ [DataContract(Name = "Category")]
+ public partial class Category : IValidatableObject
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// id.
+ /// name.
+ public Category(long id = default(long), string name = default(string))
+ {
+ this.Id = id;
+ this.Name = name;
+ }
+
+ ///
+ /// Gets or Sets Id
+ ///
+ [DataMember(Name = "id", EmitDefaultValue = false)]
+ public long Id { get; set; }
+
+ ///
+ /// Gets or Sets Name
+ ///
+ [DataMember(Name = "name", EmitDefaultValue = false)]
+ public string Name { get; set; }
+
+ ///
+ /// Returns the string presentation of the object
+ ///
+ /// String presentation of the object
+ public override string ToString()
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.Append("class Category {\n");
+ sb.Append(" Id: ").Append(Id).Append("\n");
+ sb.Append(" Name: ").Append(Name).Append("\n");
+ sb.Append("}\n");
+ return sb.ToString();
+ }
+
+ ///
+ /// Returns the JSON string presentation of the object
+ ///
+ /// JSON string presentation of the object
+ public virtual string ToJson()
+ {
+ return Newtonsoft.Json.JsonConvert.SerializeObject(this, Newtonsoft.Json.Formatting.Indented);
+ }
+
+ ///
+ /// To validate all properties of the instance
+ ///
+ /// Validation context
+ /// Validation Result
+ IEnumerable IValidatableObject.Validate(ValidationContext validationContext)
+ {
+ if (this.Name != null) {
+ // Name (string) pattern
+ Regex regexName = new Regex(@"^[a-zA-Z0-9]+[a-zA-Z0-9\.\-_]*[a-zA-Z0-9]+$", RegexOptions.CultureInvariant);
+ if (!regexName.Match(this.Name).Success)
+ {
+ yield return new System.ComponentModel.DataAnnotations.ValidationResult("Invalid value for Name, must match a pattern of " + regexName, new [] { "Name" });
+ }
+ }
+
+ yield break;
+ }
+ }
+
+}
diff --git a/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/src/Org.OpenAPITools/Model/Pet.cs b/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/src/Org.OpenAPITools/Model/Pet.cs
new file mode 100644
index 00000000000..4ef350025b5
--- /dev/null
+++ b/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/src/Org.OpenAPITools/Model/Pet.cs
@@ -0,0 +1,173 @@
+/*
+ * OpenAPI Petstore
+ *
+ * This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
+ *
+ * The version of the OpenAPI document: 1.0.0
+ * Generated by: https://github.com/openapitools/openapi-generator.git
+ */
+
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Linq;
+using System.IO;
+using System.Runtime.Serialization;
+using System.Text;
+using System.Text.RegularExpressions;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Converters;
+using Newtonsoft.Json.Linq;
+using System.ComponentModel.DataAnnotations;
+using OpenAPIDateConverter = Org.OpenAPITools.Client.OpenAPIDateConverter;
+
+namespace Org.OpenAPITools.Model
+{
+ ///
+ /// A pet for sale in the pet store
+ ///
+ [DataContract(Name = "Pet")]
+ public partial class Pet : IValidatableObject
+ {
+ ///
+ /// pet status in the store
+ ///
+ /// pet status in the store
+ [JsonConverter(typeof(StringEnumConverter))]
+ public enum StatusEnum
+ {
+ ///
+ /// Enum Available for value: available
+ ///
+ [EnumMember(Value = "available")]
+ Available = 1,
+
+ ///
+ /// Enum Pending for value: pending
+ ///
+ [EnumMember(Value = "pending")]
+ Pending = 2,
+
+ ///
+ /// Enum Sold for value: sold
+ ///
+ [EnumMember(Value = "sold")]
+ Sold = 3
+ }
+
+
+ ///
+ /// pet status in the store
+ ///
+ /// pet status in the store
+ [DataMember(Name = "status", EmitDefaultValue = false)]
+ [Obsolete]
+ public StatusEnum? Status { get; set; }
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ [JsonConstructorAttribute]
+ protected Pet() { }
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// id.
+ /// category.
+ /// name (required).
+ /// photoUrls (required).
+ /// tags.
+ /// pet status in the store.
+ public Pet(long id = default(long), Category category = default(Category), string name = default(string), List photoUrls = default(List), List tags = default(List), StatusEnum? status = default(StatusEnum?))
+ {
+ // to ensure "name" is required (not null)
+ if (name == null)
+ {
+ throw new ArgumentNullException("name is a required property for Pet and cannot be null");
+ }
+ this.Name = name;
+ // to ensure "photoUrls" is required (not null)
+ if (photoUrls == null)
+ {
+ throw new ArgumentNullException("photoUrls is a required property for Pet and cannot be null");
+ }
+ this.PhotoUrls = photoUrls;
+ this.Id = id;
+ this.Category = category;
+ this.Tags = tags;
+ this.Status = status;
+ }
+
+ ///
+ /// Gets or Sets Id
+ ///
+ [DataMember(Name = "id", EmitDefaultValue = false)]
+ public long Id { get; set; }
+
+ ///
+ /// Gets or Sets Category
+ ///
+ [DataMember(Name = "category", EmitDefaultValue = false)]
+ public Category Category { get; set; }
+
+ ///
+ /// Gets or Sets Name
+ ///
+ /*
+ doggie
+ */
+ [DataMember(Name = "name", IsRequired = true, EmitDefaultValue = true)]
+ public string Name { get; set; }
+
+ ///
+ /// Gets or Sets PhotoUrls
+ ///
+ [DataMember(Name = "photoUrls", IsRequired = true, EmitDefaultValue = true)]
+ public List PhotoUrls { get; set; }
+
+ ///
+ /// Gets or Sets Tags
+ ///
+ [DataMember(Name = "tags", EmitDefaultValue = false)]
+ public List Tags { get; set; }
+
+ ///
+ /// Returns the string presentation of the object
+ ///
+ /// String presentation of the object
+ public override string ToString()
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.Append("class Pet {\n");
+ sb.Append(" Id: ").Append(Id).Append("\n");
+ sb.Append(" Category: ").Append(Category).Append("\n");
+ sb.Append(" Name: ").Append(Name).Append("\n");
+ sb.Append(" PhotoUrls: ").Append(PhotoUrls).Append("\n");
+ sb.Append(" Tags: ").Append(Tags).Append("\n");
+ sb.Append(" Status: ").Append(Status).Append("\n");
+ sb.Append("}\n");
+ return sb.ToString();
+ }
+
+ ///
+ /// Returns the JSON string presentation of the object
+ ///
+ /// JSON string presentation of the object
+ public virtual string ToJson()
+ {
+ return Newtonsoft.Json.JsonConvert.SerializeObject(this, Newtonsoft.Json.Formatting.Indented);
+ }
+
+ ///
+ /// To validate all properties of the instance
+ ///
+ /// Validation context
+ /// Validation Result
+ IEnumerable IValidatableObject.Validate(ValidationContext validationContext)
+ {
+ yield break;
+ }
+ }
+
+}
diff --git a/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/src/Org.OpenAPITools/Model/Tag.cs b/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/src/Org.OpenAPITools/Model/Tag.cs
new file mode 100644
index 00000000000..fa80ee84810
--- /dev/null
+++ b/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/src/Org.OpenAPITools/Model/Tag.cs
@@ -0,0 +1,91 @@
+/*
+ * OpenAPI Petstore
+ *
+ * This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
+ *
+ * The version of the OpenAPI document: 1.0.0
+ * Generated by: https://github.com/openapitools/openapi-generator.git
+ */
+
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Linq;
+using System.IO;
+using System.Runtime.Serialization;
+using System.Text;
+using System.Text.RegularExpressions;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Converters;
+using Newtonsoft.Json.Linq;
+using System.ComponentModel.DataAnnotations;
+using OpenAPIDateConverter = Org.OpenAPITools.Client.OpenAPIDateConverter;
+
+namespace Org.OpenAPITools.Model
+{
+ ///
+ /// A tag for a pet
+ ///
+ [DataContract(Name = "Tag")]
+ public partial class Tag : IValidatableObject
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// id.
+ /// name.
+ public Tag(long id = default(long), string name = default(string))
+ {
+ this.Id = id;
+ this.Name = name;
+ }
+
+ ///
+ /// Gets or Sets Id
+ ///
+ [DataMember(Name = "id", EmitDefaultValue = false)]
+ public long Id { get; set; }
+
+ ///
+ /// Gets or Sets Name
+ ///
+ [DataMember(Name = "name", EmitDefaultValue = false)]
+ public string Name { get; set; }
+
+ ///
+ /// Returns the string presentation of the object
+ ///
+ /// String presentation of the object
+ public override string ToString()
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.Append("class Tag {\n");
+ sb.Append(" Id: ").Append(Id).Append("\n");
+ sb.Append(" Name: ").Append(Name).Append("\n");
+ sb.Append("}\n");
+ return sb.ToString();
+ }
+
+ ///
+ /// Returns the JSON string presentation of the object
+ ///
+ /// JSON string presentation of the object
+ public virtual string ToJson()
+ {
+ return Newtonsoft.Json.JsonConvert.SerializeObject(this, Newtonsoft.Json.Formatting.Indented);
+ }
+
+ ///
+ /// To validate all properties of the instance
+ ///
+ /// Validation context
+ /// Validation Result
+ IEnumerable IValidatableObject.Validate(ValidationContext validationContext)
+ {
+ yield break;
+ }
+ }
+
+}
diff --git a/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/src/Org.OpenAPITools/Org.OpenAPITools.csproj b/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/src/Org.OpenAPITools/Org.OpenAPITools.csproj
new file mode 100644
index 00000000000..ccb09c252b6
--- /dev/null
+++ b/samples/client/petstore/csharp/restsharp/net8/useVirtualForHooks/src/Org.OpenAPITools/Org.OpenAPITools.csproj
@@ -0,0 +1,35 @@
+
+
+
+ false
+ net8.0
+ Org.OpenAPITools
+ Org.OpenAPITools
+ Library
+ OpenAPI
+ OpenAPI
+ OpenAPI Library
+ A library generated from a OpenAPI doc
+ No Copyright
+ Org.OpenAPITools
+ 1.0.0
+ bin\$(Configuration)\$(TargetFramework)\Org.OpenAPITools.xml
+ https://github.com/GIT_USER_ID/GIT_REPO_ID.git
+ git
+ Minor update
+ annotations
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+