diff --git a/docs/generators/csharp-netcore.md b/docs/generators/csharp-netcore.md index c7935752d018..ac085dc35988 100644 --- a/docs/generators/csharp-netcore.md +++ b/docs/generators/csharp-netcore.md @@ -12,11 +12,12 @@ These options may be applied as additional-properties (cli) or configOptions (pl |disallowAdditionalPropertiesIfNotPresent|If false, the 'additionalProperties' implementation (set to true by default) is compliant with the OAS and JSON schema specifications. If true (default), keep the old (incorrect) behaviour that 'additionalProperties' is set to false by default.|
**false**
The 'additionalProperties' implementation is compliant with the OAS and JSON schema specifications.
**true**
Keep the old (incorrect) behaviour that 'additionalProperties' is set to false by default.
|true| |hideGenerationTimestamp|Hides the generation timestamp when files are generated.| |true| |interfacePrefix|Prefix interfaces with a community standard or widely accepted prefix.| |I| -|library|HTTP library template (sub-template) to use|
**httpclient**
HttpClient (https://docs.microsoft.com/en-us/dotnet/api/system.net.http.httpclient) (Experimental. May subject to breaking changes without further notice.)
**restsharp**
RestSharp (https://github.com/restsharp/RestSharp)
|restsharp| +|library|HTTP library template (sub-template) to use|
**httpclient**
HttpClient (https://docs.microsoft.com/en-us/dotnet/api/system.net.http.httpclient) (Experimental. May subject to breaking changes without further notice.)
**restsharp**
RestSharp (https://github.com/restsharp/RestSharp)
**httpclient-experimental**
HttpClient (https://docs.microsoft.com/en-us/dotnet/api/system.net.http.httpclient) (Experimental. May subject to breaking changes without further notice.)
|restsharp| |licenseId|The identifier of the license| |null| |modelPropertyNaming|Naming convention for the property: 'camelCase', 'PascalCase', 'snake_case' and 'original', which keeps the original name| |PascalCase| |netCoreProjectFile|Use the new format (.NET Core) for .NET project files (.csproj).| |false| |nonPublicApi|Generates code with reduced access modifiers; allows embedding elsewhere without exposing non-public API calls to consumers.| |false| +|nullableReferenceTypes|Set the nullable reference types property to true or false. Default is false.| |false| |optionalAssemblyInfo|Generate AssemblyInfo.cs.| |true| |optionalEmitDefaultValues|Set DataMember's EmitDefaultValue.| |false| |optionalMethodArgument|C# Optional method argument, e.g. void square(int x=10) (.net 4.0+ only).| |true| 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 2e7151dc94e2..4fb0299b5c56 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 @@ -208,6 +208,9 @@ public class CodegenConstants { public static final String DOTNET_FRAMEWORK = "targetFramework"; public static final String DOTNET_FRAMEWORK_DESC = "The target .NET framework version."; + public static final String NULLABLE_REFERENCE_TYPES = "nullableReferenceTypes"; + public static final String NULLABLE_REFERENCE_TYPES_DESC = "Set the nullable reference types property to true or false. Default is false."; + public static final String TEMPLATING_ENGINE = "templatingEngine"; public static final String TEMPLATING_ENGINE_DESC = "The templating engine plugin to use: \"mustache\" (default) or \"handlebars\" (beta)"; diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractCSharpCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractCSharpCodegen.java index 2782357482c9..83ef0f315695 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractCSharpCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractCSharpCodegen.java @@ -47,6 +47,7 @@ public abstract class AbstractCSharpCodegen extends DefaultCodegen implements Co protected boolean useCollection = false; protected boolean returnICollection = false; protected boolean netCoreProjectFileFlag = false; + protected boolean nullReferenceTypesFlag = false; protected String modelPropertyNaming = CodegenConstants.MODEL_PROPERTY_NAMING_TYPE.PascalCase.name(); diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CSharpNetCoreClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CSharpNetCoreClientCodegen.java index 2575c4d4d4a8..5c1286d3c18c 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CSharpNetCoreClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CSharpNetCoreClientCodegen.java @@ -49,6 +49,7 @@ public class CSharpNetCoreClientCodegen extends AbstractCSharpCodegen { // HTTP libraries protected static final String RESTSHARP = "restsharp"; protected static final String HTTPCLIENT = "httpclient"; + protected static final String HTTPCLIENT_EXPERIMENTAL = "httpclient-experimental"; // Project Variable, determined from target framework. Not intended to be user-settable. protected static final String TARGET_FRAMEWORK_IDENTIFIER = "targetFrameworkIdentifier"; @@ -230,6 +231,10 @@ public CSharpNetCoreClientCodegen() { cliOptions.add(modelPropertyNaming.defaultValue("PascalCase")); // CLI Switches + addSwitch(CodegenConstants.NULLABLE_REFERENCE_TYPES, + CodegenConstants.NULLABLE_REFERENCE_TYPES_DESC, + this.nullReferenceTypesFlag); + addSwitch(CodegenConstants.HIDE_GENERATION_TIMESTAMP, CodegenConstants.HIDE_GENERATION_TIMESTAMP_DESC, this.hideGenerationTimestamp); @@ -303,6 +308,9 @@ public CSharpNetCoreClientCodegen() { supportedLibraries.put(HTTPCLIENT, "HttpClient (https://docs.microsoft.com/en-us/dotnet/api/system.net.http.httpclient) " + "(Experimental. May subject to breaking changes without further notice.)"); supportedLibraries.put(RESTSHARP, "RestSharp (https://github.com/restsharp/RestSharp)"); + supportedLibraries.put(HTTPCLIENT_EXPERIMENTAL, "HttpClient (https://docs.microsoft.com/en-us/dotnet/api/system.net.http.httpclient) " + + "(Experimental. May subject to breaking changes without further notice.)"); + CliOption libraryOption = new CliOption(CodegenConstants.LIBRARY, "HTTP library template (sub-template) to use"); libraryOption.setEnum(supportedLibraries); @@ -555,9 +563,21 @@ public void processOpts() { * if (additionalProperties.containsKey(prop)) convertPropertyToBooleanAndWriteBack(prop); */ + if (additionalProperties.containsKey(CodegenConstants.NULLABLE_REFERENCE_TYPES)){ + Object nullableReferenceTypesFlag = additionalProperties.get(CodegenConstants.NULLABLE_REFERENCE_TYPES); + if (nullableReferenceTypesFlag == null || nullableReferenceTypesFlag.toString().trim().length() == 0 || nullableReferenceTypesFlag.toString().equals("true")){ + writePropertyBack(CodegenConstants.NULLABLE_REFERENCE_TYPES, true); + this.setNullableReferenceTypes(true); + this.nullableType.add("string"); + } + else{ + writePropertyBack(CodegenConstants.NULLABLE_REFERENCE_TYPES, false); + } + } + if (additionalProperties.containsKey(CodegenConstants.DISALLOW_ADDITIONAL_PROPERTIES_IF_NOT_PRESENT)) { this.setDisallowAdditionalPropertiesIfNotPresent(Boolean.valueOf(additionalProperties - .get(CodegenConstants.DISALLOW_ADDITIONAL_PROPERTIES_IF_NOT_PRESENT).toString())); + .get(CodegenConstants.DISALLOW_ADDITIONAL_PROPERTIES_IF_NOT_PRESENT).toString())); } if (additionalProperties.containsKey(CodegenConstants.OPTIONAL_EMIT_DEFAULT_VALUES)) { @@ -586,6 +606,9 @@ public void processOpts() { setLibrary(HTTPCLIENT); additionalProperties.put("useHttpClient", true); needsUriBuilder = true; + }else if (HTTPCLIENT_EXPERIMENTAL.equals((getLibrary()))){ + setLibrary(HTTPCLIENT_EXPERIMENTAL); + additionalProperties.put("useHttpClientExperimental", true); } else { throw new RuntimeException("Invalid HTTP library " + getLibrary() + ". Only restsharp, httpclient are supported."); } @@ -725,6 +748,10 @@ public void processOpts() { additionalProperties.put("modelDocPath", modelDocPath); } + public void setNullableReferenceTypes(Boolean flag){ + this.nullReferenceTypesFlag = flag; + } + public void setNetStandard(Boolean netStandard) { this.netStandard = netStandard; } diff --git a/modules/openapi-generator/src/main/resources/csharp-netcore/libraries/httpclient-experimental/ApiClient.mustache b/modules/openapi-generator/src/main/resources/csharp-netcore/libraries/httpclient-experimental/ApiClient.mustache new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/modules/openapi-generator/src/main/resources/csharp-netcore/libraries/httpclient-experimental/ApiException.mustache b/modules/openapi-generator/src/main/resources/csharp-netcore/libraries/httpclient-experimental/ApiException.mustache new file mode 100644 index 000000000000..582e22f5d9e6 --- /dev/null +++ b/modules/openapi-generator/src/main/resources/csharp-netcore/libraries/httpclient-experimental/ApiException.mustache @@ -0,0 +1,42 @@ +{{>partial_header}} + +using System; + +namespace {{packageName}}.Client +{ + /// + /// API Exception + /// + {{>visibility}} class ApiException : Exception + { + /// + /// The reason the api request failed + /// + public string{{#nullableReferenceTypes}}?{{/nullableReferenceTypes}} ReasonPhrase { get; } + + /// + /// The HttpStatusCode + /// + public System.Net.HttpStatusCode StatusCode { get; } + + /// + /// The raw data returned by the api + /// + public string RawContent { get; } + + /// + /// Construct the ApiException from parts of the reponse + /// + /// + /// + /// + public ApiException(string{{#nullableReferenceTypes}}?{{/nullableReferenceTypes}} reasonPhrase, System.Net.HttpStatusCode statusCode, string rawContent) : base(reasonPhrase ?? rawContent) + { + ReasonPhrase = reasonPhrase; + + StatusCode = statusCode; + + RawContent = rawContent; + } + } +} diff --git a/modules/openapi-generator/src/main/resources/csharp-netcore/libraries/httpclient-experimental/ApiResponse.mustache b/modules/openapi-generator/src/main/resources/csharp-netcore/libraries/httpclient-experimental/ApiResponse.mustache new file mode 100644 index 000000000000..ba1d71bf70a3 --- /dev/null +++ b/modules/openapi-generator/src/main/resources/csharp-netcore/libraries/httpclient-experimental/ApiResponse.mustache @@ -0,0 +1,104 @@ +{{>partial_header}} + +using System; +using System.Collections.Generic; +using System.Net; +using Newtonsoft.Json; + +namespace {{packageName}}.Client +{ + /// + /// Provides a non-generic contract for the ApiResponse wrapper. + /// + public interface IApiResponse + { + /// + /// The data type of + /// + Type ResponseType { get; } + + /// + /// Gets or sets the status code (HTTP status code) + /// + /// The status code. + HttpStatusCode StatusCode { get; } + + /// + /// 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 + /// + {{>visibility}} partial class ApiResponse : IApiResponse + { + #region Properties + + /// + /// The deserialized content + /// + public T{{#nullableReferenceTypes}}?{{/nullableReferenceTypes}} Content { get; set; } + + /// + /// Gets or sets the status code (HTTP status code) + /// + /// The status code. + public HttpStatusCode StatusCode { get; } + + /// + /// 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 raw data + /// + public string RawContent { get; } + + /// + /// The IsSuccessStatusCode from the api response + /// + public bool IsSuccessStatusCode { get; } + + /// + /// The reason phrase contained in the api response + /// + public string{{#nullableReferenceTypes}}?{{/nullableReferenceTypes}} ReasonPhrase { get; } + + /// + /// The headers contained in the api response + /// + public System.Net.Http.Headers.HttpResponseHeaders Headers { get; } + + #endregion Properties + + /// + /// Construct the reponse using an HttpResponseMessage + /// + /// + /// + public ApiResponse(System.Net.Http.HttpResponseMessage response, string rawContent) + { + StatusCode = response.StatusCode; + Headers = response.Headers; + IsSuccessStatusCode = response.IsSuccessStatusCode; + ReasonPhrase = response.ReasonPhrase; + RawContent = rawContent; + } + } +} diff --git a/modules/openapi-generator/src/main/resources/csharp-netcore/libraries/httpclient-experimental/AssemblyInfo.mustache b/modules/openapi-generator/src/main/resources/csharp-netcore/libraries/httpclient-experimental/AssemblyInfo.mustache new file mode 100644 index 000000000000..c5d19bfd2357 --- /dev/null +++ b/modules/openapi-generator/src/main/resources/csharp-netcore/libraries/httpclient-experimental/AssemblyInfo.mustache @@ -0,0 +1,37 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("{{packageTitle}}")] +[assembly: AssemblyDescription("{{packageDescription}}")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("{{packageCompany}}")] +[assembly: AssemblyProduct("{{packageProductName}}")] +[assembly: AssemblyCopyright("{{packageCopyright}}")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("{{packageVersion}}")] +[assembly: AssemblyFileVersion("{{packageVersion}}")] +{{^supportsAsync}} +[assembly: InternalsVisibleTo("NewtonSoft.Json")] +[assembly: InternalsVisibleTo("JsonSubTypes")] +{{/supportsAsync}} diff --git a/modules/openapi-generator/src/main/resources/csharp-netcore/libraries/httpclient-experimental/ClientUtils.mustache b/modules/openapi-generator/src/main/resources/csharp-netcore/libraries/httpclient-experimental/ClientUtils.mustache new file mode 100644 index 000000000000..684f79e66524 --- /dev/null +++ b/modules/openapi-generator/src/main/resources/csharp-netcore/libraries/httpclient-experimental/ClientUtils.mustache @@ -0,0 +1,245 @@ +{{>partial_header}} + +using System; +using System.Collections; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +{{#useCompareNetObjects}} +using KellermanSoftware.CompareNetObjects; +{{/useCompareNetObjects}} + +namespace {{packageName}}.Client +{ + /// + /// Utility functions providing some benefit to API client consumers. + /// + public static class ClientUtils + { + {{#useCompareNetObjects}} + /// + /// An instance of CompareLogic. + /// + public static CompareLogic compareLogic; + + /// + /// Static contstructor to initialise compareLogic. + /// + static ClientUtils() + { + compareLogic = new CompareLogic(); + } + {{/useCompareNetObjects}} + + /// + /// Custom JSON serializer + /// + public static readonly Newtonsoft.Json.JsonSerializerSettings JsonSerializerSettings = new Newtonsoft.Json.JsonSerializerSettings + { + // OpenAPI generated types generally hide default constructors. + ConstructorHandling = Newtonsoft.Json.ConstructorHandling.AllowNonPublicDefaultConstructor, + MissingMemberHandling = Newtonsoft.Json.MissingMemberHandling.Error, + ContractResolver = new Newtonsoft.Json.Serialization.DefaultContractResolver + { + NamingStrategy = new Newtonsoft.Json.Serialization.CamelCaseNamingStrategy + { + OverrideSpecifiedNames = false + } + } + }; + + /// + /// 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 + { + 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) + { + throw new NotImplementedException(); + + /* + 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 bool boolean) + return boolean ? "true" : "false"; + if (obj is ICollection collection) + return string.Join(",", collection.Cast()); + + return Convert.ToString(obj, CultureInfo.InvariantCulture); + */ + } + + /// + /// URL encode a string + /// Credit/Ref: https://github.com/restsharp/RestSharp/blob/master/RestSharp/Extensions/StringExtensions.cs#L50 + /// + /// String to be URL encoded + /// Byte array + public static string UrlEncode(string input) + { + const int maxLength = 32766; + + if (input == null) + { + throw new ArgumentNullException("input"); + } + + if (input.Length <= maxLength) + { + return Uri.EscapeDataString(input); + } + + StringBuilder sb = new StringBuilder(input.Length * 2); + int index = 0; + + while (index < input.Length) + { + int length = Math.Min(input.Length - index, maxLength); + string subString = input.Substring(index, length); + + sb.Append(Uri.EscapeDataString(subString)); + index += subString.Length; + } + + return sb.ToString(); + } + + /// + /// Encode string in base64 format. + /// + /// String to be encoded. + /// Encoded string. + public static string Base64Encode(string text) + { + return Convert.ToBase64String(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"); + } + } +} diff --git a/modules/openapi-generator/src/main/resources/csharp-netcore/libraries/httpclient-experimental/Configuration.mustache b/modules/openapi-generator/src/main/resources/csharp-netcore/libraries/httpclient-experimental/Configuration.mustache new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/modules/openapi-generator/src/main/resources/csharp-netcore/libraries/httpclient-experimental/GlobalConfiguration.mustache b/modules/openapi-generator/src/main/resources/csharp-netcore/libraries/httpclient-experimental/GlobalConfiguration.mustache new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/modules/openapi-generator/src/main/resources/csharp-netcore/libraries/httpclient-experimental/README.mustache b/modules/openapi-generator/src/main/resources/csharp-netcore/libraries/httpclient-experimental/README.mustache new file mode 100644 index 000000000000..f5ccddd94e50 --- /dev/null +++ b/modules/openapi-generator/src/main/resources/csharp-netcore/libraries/httpclient-experimental/README.mustache @@ -0,0 +1,233 @@ +If you are not using .Net Standard, consider setting validatable to false in your generator-config.json due to this bug: https://github.com/dotnet/project-system/issues/3934 + +``` +java -jar "../openapi-generator/modules/openapi-generator-cli/target/openapi-generator-cli.jar" generate ` + -g csharp-netcore ` + -i "your-swagger-file.yml" ` + -c generator-config.json ` + -o output ` + --library httpclient-experimental ` + --additional-properties=targetFramework=net5.0 ` + --additional-properties=validatable=false ` + --additional-properties=nullableReferenceTypes +``` + +# {{packageName}} - the C# library for the {{appName}} + +{{#appDescriptionWithNewLines}} +{{{appDescriptionWithNewLines}}} +{{/appDescriptionWithNewLines}} + +This C# SDK is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project: + +- API version: {{appVersion}} +- SDK version: {{packageVersion}} +{{^hideGenerationTimestamp}} +- Build date: {{generatedDate}} +{{/hideGenerationTimestamp}} +- Build package: {{generatorClass}} +{{#infoUrl}} + For more information, please visit [{{{infoUrl}}}]({{{infoUrl}}}) +{{/infoUrl}} + + +## Frameworks supported +{{#netStandard}} +- .NET Core >=1.0 +- .NET Framework >=4.6 +- Mono/Xamarin >=vNext +{{/netStandard}} + + +## Dependencies + +- [Json.NET](https://www.nuget.org/packages/Newtonsoft.Json/) - 12.0.3 or later +- [JsonSubTypes](https://www.nuget.org/packages/JsonSubTypes/) - 1.7.0 or later +{{#useCompareNetObjects}} +- [CompareNETObjects](https://www.nuget.org/packages/CompareNETObjects) - 4.61.0 or later +{{/useCompareNetObjects}} +{{#validatable}} +- [System.ComponentModel.Annotations](https://www.nuget.org/packages/System.ComponentModel.Annotations) - 4.7.0 or later +{{/validatable}} + +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 Newtonsoft.Json +Install-Package JsonSubTypes +{{#validatable}} +Install-Package System.ComponentModel.Annotations +{{/validatable}} +{{#useCompareNetObjects}} +Install-Package CompareNETObjects +{{/useCompareNetObjects}} +``` + + +## Installation +{{#netStandard}} +Generate the DLL using your preferred tool (e.g. `dotnet build`) +{{/netStandard}} +{{^netStandard}} +Run the following command to generate the DLL +- [Mac/Linux] `/bin/sh build.sh` +- [Windows] `build.bat` +{{/netStandard}} + +Then include the DLL (under the `bin` folder) in the C# project, and use the namespaces: +```csharp +using {{packageName}}.{{apiPackage}}; +using {{packageName}}.Client; +using {{packageName}}.{{modelPackage}}; +``` +{{^netStandard}} + +## 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 {{packageName}}.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. + +{{/netStandard}} + +## 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 {{packageName}}.{{apiPackage}}; +using {{packageName}}.Client; +using {{packageName}}.{{modelPackage}}; + +namespace Example +{ + public class {{operationId}}Example + { + public static void Main() + { +{{#apiInfo}}{{#apis}}{{#-first}}{{#operations}}{{#operation}}{{#-first}} + Configuration config = new Configuration(); + config.BasePath = "{{{basePath}}}"; + {{#hasAuthMethods}} + {{#authMethods}} + {{#isBasicBasic}} + // Configure HTTP basic authorization: {{{name}}} + config.Username = "YOUR_USERNAME"; + config.Password = "YOUR_PASSWORD"; + {{/isBasicBasic}} + {{#isBasicBearer}} + // Configure Bearer token for authorization: {{{name}}} + config.AccessToken = "YOUR_BEARER_TOKEN"; + {{/isBasicBearer}} + {{#isApiKey}} + // Configure API key authorization: {{{name}}} + config.ApiKey.Add("{{{keyParamName}}}", "YOUR_API_KEY"); + // Uncomment below to setup prefix (e.g. Bearer) for API key, if needed + // config.ApiKeyPrefix.Add("{{{keyParamName}}}", "Bearer"); + {{/isApiKey}} + {{#isOAuth}} + // Configure OAuth2 access token for authorization: {{{name}}} + config.AccessToken = "YOUR_ACCESS_TOKEN"; + {{/isOAuth}} + {{/authMethods}} + + {{/hasAuthMethods}} + var apiInstance = new {{classname}}(config); + {{#allParams}} + {{#isPrimitiveType}} + var {{paramName}} = {{{example}}}; // {{{dataType}}} | {{{description}}}{{^required}} (optional) {{/required}}{{#defaultValue}} (default to {{{.}}}){{/defaultValue}} + {{/isPrimitiveType}} + {{^isPrimitiveType}} + var {{paramName}} = new {{{dataType}}}(); // {{{dataType}}} | {{{description}}}{{^required}} (optional) {{/required}}{{#defaultValue}} (default to {{{.}}}){{/defaultValue}} + {{/isPrimitiveType}} + {{/allParams}} + + try + { + {{#summary}} + // {{{.}}} + {{/summary}} + {{#returnType}}{{{returnType}}} result = {{/returnType}}apiInstance.{{{operationId}}}({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}});{{#returnType}} + Debug.WriteLine(result);{{/returnType}} + } + catch (ApiException e) + { + Debug.Print("Exception when calling {{classname}}.{{operationId}}: " + e.Message ); + Debug.Print("Status Code: "+ e.ErrorCode); + Debug.Print(e.StackTrace); + } +{{/-first}}{{/operation}}{{/operations}}{{/-first}}{{/apis}}{{/apiInfo}} + } + } +} +``` + + +## Documentation for API Endpoints + +All URIs are relative to *{{{basePath}}}* + +Class | Method | HTTP request | Description +------------ | ------------- | ------------- | ------------- +{{#apiInfo}}{{#apis}}{{#operations}}{{#operation}}*{{classname}}* | [**{{operationId}}**]({{apiDocPath}}{{classname}}.md#{{operationIdLowerCase}}) | **{{httpMethod}}** {{path}} | {{#summary}}{{{summary}}}{{/summary}} +{{/operation}}{{/operations}}{{/apis}}{{/apiInfo}} + + +## Documentation for Models + +{{#modelPackage}} +{{#models}}{{#model}} - [{{{modelPackage}}}.{{{classname}}}]({{modelDocPath}}{{{classname}}}.md) +{{/model}}{{/models}} +{{/modelPackage}} +{{^modelPackage}} +No model defined in this package +{{/modelPackage}} + + +## Documentation for Authorization + +{{^authMethods}} +All endpoints do not require authorization. +{{/authMethods}} +{{#authMethods}} +{{#last}} +Authentication schemes defined for the API: +{{/last}} +{{/authMethods}} +{{#authMethods}} + +### {{name}} + +{{#isApiKey}}- **Type**: API key +- **API key parameter name**: {{keyParamName}} +- **Location**: {{#isKeyInQuery}}URL query string{{/isKeyInQuery}}{{#isKeyInHeader}}HTTP header{{/isKeyInHeader}} +{{/isApiKey}} +{{#isBasicBasic}}- **Type**: HTTP basic authentication +{{/isBasicBasic}} +{{#isBasicBearer}}- **Type**: Bearer Authentication +{{/isBasicBearer}} +{{#isOAuth}}- **Type**: OAuth +- **Flow**: {{flow}} +- **Authorization URL**: {{authorizationUrl}} +- **Scopes**: {{^scopes}}N/A{{/scopes}} +{{#scopes}} - {{scope}}: {{description}} +{{/scopes}} +{{/isOAuth}} + +{{/authMethods}} diff --git a/modules/openapi-generator/src/main/resources/csharp-netcore/libraries/httpclient-experimental/RetryConfiguration.mustache b/modules/openapi-generator/src/main/resources/csharp-netcore/libraries/httpclient-experimental/RetryConfiguration.mustache new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/modules/openapi-generator/src/main/resources/csharp-netcore/libraries/httpclient-experimental/TestProject.mustache b/modules/openapi-generator/src/main/resources/csharp-netcore/libraries/httpclient-experimental/TestProject.mustache new file mode 100644 index 000000000000..b1c368ccb7d1 --- /dev/null +++ b/modules/openapi-generator/src/main/resources/csharp-netcore/libraries/httpclient-experimental/TestProject.mustache @@ -0,0 +1,37 @@ + + + + + false + Properties + {{testPackageName}} + {{testPackageName}} + net5.0 + enable + false + 512 + + + + + + + + + {{packageGuid}} + {{packageName}} + + + + diff --git a/modules/openapi-generator/src/main/resources/csharp-netcore/libraries/httpclient-experimental/api.mustache b/modules/openapi-generator/src/main/resources/csharp-netcore/libraries/httpclient-experimental/api.mustache new file mode 100644 index 000000000000..395ae1c0bc8c --- /dev/null +++ b/modules/openapi-generator/src/main/resources/csharp-netcore/libraries/httpclient-experimental/api.mustache @@ -0,0 +1,313 @@ +{{>partial_header}} + +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.Net; +using System.Net.Mime; +using {{packageName}}.Client; +{{#hasImport}}using {{packageName}}.{{modelPackage}}; +{{/hasImport}} + +namespace {{packageName}}.{{apiPackage}} +{ + {{#operations}} + /// + /// Represents a collection of functions to interact with the API endpoints + /// + {{>visibility}} interface {{interfacePrefix}}{{classname}} + { + {{#operation}} + /// + /// {{summary}} + /// + /// + /// {{notes}} + /// + /// Thrown when fails to make API call + {{#allParams}} + /// {{description}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} + {{/allParams}} + /// Cancellation Token to cancel the request. + /// Task of ApiResponse{{#returnType}} ({{returnType}}){{/returnType}} + System.Threading.Tasks.Task> {{operationId}}WithHttpInfoAsync({{#allParams}}{{#required}}{{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/required}}{{^required}}{{{dataType}}} {{paramName}} = null{{^-last}}, {{/-last}}{{/required}}{{/allParams}}{{#allParams.0}}, {{/allParams.0}}System.Threading.CancellationToken? cancellationToken = null); + + /// + /// {{summary}} + /// + /// + /// {{notes}} + /// + /// Thrown when fails to make API call + {{#allParams}} + /// {{description}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} + {{/allParams}} + /// Cancellation Token to cancel the request. + /// Task of ApiResponse{{#returnType}} ({{returnType}}){{/returnType}} + System.Threading.Tasks.Task<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Object{{/returnType}}> {{operationId}}Async({{#allParams}}{{#required}}{{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/required}}{{^required}}{{{dataType}}} {{paramName}} = null{{^-last}}, {{/-last}}{{/required}}{{/allParams}}{{#allParams.0}}, {{/allParams.0}}System.Threading.CancellationToken? cancellationToken = null); + + {{#returnType}} + /// + /// {{summary}} + /// + /// + /// {{notes}} + /// + {{#allParams}} + /// {{description}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} + {{/allParams}} + /// Cancellation Token to cancel the request. + /// Task of ApiResponse{{#returnType}} ({{returnType}}{{#nullableReferenceTypes}}?{{/nullableReferenceTypes}}){{/returnType}} + System.Threading.Tasks.Task<{{#returnType}}{{{returnType}}}{{#nullableReferenceTypes}}?{{/nullableReferenceTypes}}{{/returnType}}> {{operationId}}OrDefaultAsync({{#allParams}}{{#required}}{{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/required}}{{^required}}{{{dataType}}} {{paramName}} = null{{^-last}}, {{/-last}}{{/required}}{{/allParams}}{{#allParams.0}}, {{/allParams.0}}System.Threading.CancellationToken? cancellationToken = null); + {{/returnType}} + {{/operation}} + } + + /// + /// Represents a collection of functions to interact with the API endpoints + /// + {{>visibility}} partial class {{classname}} : {{interfacePrefix}}{{classname}} + { + private readonly System.Net.Http.HttpClient _httpClient; + + /// + /// Initializes a new instance of the class. + /// + /// + public {{classname}}(System.Net.Http.HttpClient httpClient) + { + _httpClient = httpClient; + } + + /// + /// Returns the token to be used in the api query + /// + public Func>{{#nullableReferenceTypes}}?{{/nullableReferenceTypes}} GetTokenAsync { get; set; } + + {{#operation}} + + {{#returnType}} + /// + /// {{summary}} {{notes}} + /// + /// Thrown when fails to make API call + {{#allParams}} + /// {{description}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} + {{/allParams}} + /// Cancellation Token to cancel the request. + /// Task of {{returnType}} + public async System.Threading.Tasks.Task<{{{returnType}}}> {{operationId}}Async({{#allParams}}{{#required}}{{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/required}}{{^required}}{{{dataType}}} {{paramName}} = null{{^-last}}, {{/-last}}{{/required}}{{/allParams}}{{#allParams.0}}, {{/allParams.0}}System.Threading.CancellationToken? cancellationToken = null) + { + {{packageName}}.Client.ApiResponse<{{{returnType}}}> result = await {{operationId}}WithHttpInfoAsync({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}{{#allParams.0}}, {{/allParams.0}}cancellationToken).ConfigureAwait(false); + return result.Content ?? throw new ApiException(result.ReasonPhrase, result.StatusCode, result.RawContent); + } + {{/returnType}} + + {{#returnType}} + /// + /// {{summary}} {{notes}} + /// + /// Thrown when fails to make API call + {{#allParams}} + /// {{description}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} + {{/allParams}} + /// Cancellation Token to cancel the request. + /// Task of {{returnType}} + public async System.Threading.Tasks.Task<{{{returnType}}}{{#nullableReferenceTypes}}?{{/nullableReferenceTypes}}> {{operationId}}OrDefaultAsync({{#allParams}}{{#required}}{{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/required}}{{^required}}{{{dataType}}} {{paramName}} = null{{^-last}}, {{/-last}}{{/required}}{{/allParams}}{{#allParams.0}}, {{/allParams.0}}System.Threading.CancellationToken? cancellationToken = null) + { + {{packageName}}.Client.ApiResponse<{{{returnType}}}> result = await {{operationId}}WithHttpInfoAsync({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}{{#allParams.0}}, {{/allParams.0}}cancellationToken).ConfigureAwait(false); + + return result.IsSuccessStatusCode + ? result.Content + : null; + } + {{/returnType}} + + /// + /// {{summary}} {{notes}} + /// + /// Thrown when fails to make API call + {{#allParams}} + /// {{description}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} + {{/allParams}} + /// Cancellation Token to cancel the request. + /// Task of ApiResponse{{#returnType}} ({{returnType}}){{/returnType}} + public async System.Threading.Tasks.Task<{{packageName}}.Client.ApiResponse<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Object{{/returnType}}>> {{operationId}}WithHttpInfoAsync({{#allParams}}{{#required}}{{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/required}}{{^required}}{{{dataType}}} {{paramName}} = null{{^-last}}, {{/-last}}{{/required}}{{/allParams}}{{#allParams.0}}, {{/allParams.0}}System.Threading.CancellationToken? cancellationToken = null) + { + {{#allParams}} + {{#required}} + {{^vendorExtensions.x-csharp-value-type}} + if ({{paramName}} == null) + throw new ArgumentNullException(nameof({{paramName}})); + {{/vendorExtensions.x-csharp-value-type}} + {{/required}} + {{/allParams}} + + using System.Net.Http.HttpRequestMessage request = new System.Net.Http.HttpRequestMessage(); + + string path = "{{path}}"; + {{#pathParams}} + {{#required}} +{{=<< >>=}} + path = path.Replace("{<>}", Uri.EscapeDataString(<>)); +<<={{ }}=>> + {{/required}} + + {{^required}} + if ({{paramName}} != null) +{{=<< >>=}} + path = $"{path}{path.Replace("<>", Uri.EscapeDataString(<>))}&"; +<<={{ }}=>> + {{/required}}{{/pathParams}} + + path = $"{path}?"; + + {{#queryParams}} + {{#required}} + path = $"{path}{{baseName}}={Uri.EscapeDataString({{paramName}}.ToString()!)&"; + + {{/required}} + {{^required}} + if ({{paramName}} != null) + path = $"{path}{{baseName}}={Uri.EscapeDataString({{paramName}}.ToString()!)}&"; + + {{/required}} + {{/queryParams}} + + if (path.EndsWith("&")) + path = path[..^1]; + + if (path.EndsWith("?")) + path = path[..^1]; + + request.RequestUri = new Uri($"{_httpClient.BaseAddress}{path}"); + + {{#headerParams}} + {{#required}} + request.Headers.Add({{baseName}}, {{paramName}}); + {{/required}} + {{^required}} + if ({{paramName}} != null) + request.Headers.Add({{baseName}}, {{paramName}}); + {{/required}} + {{/headerParams}} + + {{#formParams}} + {{#required}} + {{#isFile}} + // todo localVarRequestOptions.FileParameters.Add("{{baseName}}", {{paramName}}); + {{/isFile}} + {{^isFile}} + // todo localVarRequestOptions.FormParameters.Add("{{baseName}}", {{packageName}}.Client.ClientUtils.ParameterToString({{paramName}})); // form parameter + {{/isFile}} + {{/required}} + {{^required}} + if ({{paramName}} != null) + { + {{#isFile}} + // todo localVarRequestOptions.FileParameters.Add("{{baseName}}", {{paramName}}); + {{/isFile}} + {{^isFile}} + // todo localVarRequestOptions.FormParameters.Add("{{baseName}}", {{packageName}}.Client.ClientUtils.ParameterToString({{paramName}})); // form parameter + {{/isFile}} + } + {{/required}} + {{/formParams}} + + {{#bodyParam}} + // todo localVarRequestOptions.Content = {{paramName}}; + {{/bodyParam}} + + {{#authMethods}} + // authentication ({{name}}) required + {{#isApiKey}} + {{#isKeyInCookie}} + // cookie parameter support + // todo if (!string.IsNullOrEmpty(this.Configuration.GetApiKeyWithPrefix("{{keyParamName}}"))) + // todo localVarRequestOptions.Cookies.Add(new Cookie("{{keyParamName}}", this.Configuration.GetApiKeyWithPrefix("{{keyParamName}}"))); + {{/isKeyInCookie}} + {{#isKeyInHeader}}//isKeyInHeader + string{{#nullableReferenceTypes}}?{{/nullableReferenceTypes}} token = GetTokenAsync != null + ? await GetTokenAsync().ConfigureAwait(false) + : null; + + if (token != null) + request.Headers.Add("authorization", $"Bearer {token}"); + {{/isKeyInHeader}} + {{#isKeyInQuery}} + //todo if (!string.IsNullOrEmpty(this.Configuration.GetApiKeyWithPrefix("{{keyParamName}}"))) + //todo localVarRequestOptions.QueryParameters.Add({{packageName}}.Client.ClientUtils.ParameterToMultiMap("", "{{keyParamName}}", this.Configuration.GetApiKeyWithPrefix("{{keyParamName}}"))); + {{/isKeyInQuery}} + {{/isApiKey}} + {{#isBasic}} + {{#isBasicBasic}} + // http basic authentication required + //todo if (!string.IsNullOrEmpty(this.Configuration.Username) || !string.IsNullOrEmpty(this.Configuration.Password)) + //todo localVarRequestOptions.HeaderParameters.Add("Authorization", "Basic " + {{packageName}}.Client.ClientUtils.Base64Encode(this.Configuration.Username + ":" + this.Configuration.Password)); + {{/isBasicBasic}} + {{#isBasicBearer}}//isBasicBearer + // bearer authentication required + //todo if (!string.IsNullOrEmpty(this.Configuration.AccessToken)) + //todo request.Headers.Add("authorization", $"Bearer {Environment.GetEnvironmentVariable("TOKEN_0", EnvironmentVariableTarget.Machine)}"); + {{/isBasicBearer}} + {{/isBasic}} + {{#isOAuth}} + // oauth required + //todo if (!string.IsNullOrEmpty(this.Configuration.AccessToken)) + //todo localVarRequestOptions.HeaderParameters.Add("Authorization", "Bearer " + this.Configuration.AccessToken); + {{/isOAuth}} + {{#isHttpSignature}} + //todo + /* + if (this.Configuration.HttpSigningConfiguration != null) + { + var HttpSigningHeaders = this.Configuration.HttpSigningConfiguration.GetHttpSignedHeader(this.Configuration.BasePath, "{{{httpMethod}}}", "{{{path}}}", localVarRequestOptions); + foreach (var headerItem in HttpSigningHeaders) + { + if (localVarRequestOptions.HeaderParameters.ContainsKey(headerItem.Key)) + { + localVarRequestOptions.HeaderParameters[headerItem.Key] = new List() { headerItem.Value }; + } + else + { + localVarRequestOptions.HeaderParameters.Add(headerItem.Key, headerItem.Value); + } + } + } + */ + {{/isHttpSignature}} + {{/authMethods}} + + {{#consumes}} + request.Headers.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("{{{mediaType}}}")); + {{/consumes}} + + string[] contentTypes = new string[] { + {{#consumes}} + "{{{mediaType}}}"{{^-last}}, {{/-last}} + {{/consumes}} + }; + + if (request.Content != null && contentTypes.Length > 0) + request.Content.Headers.Add("CONTENT-TYPE", contentTypes); + + {{#produces}} + request.Headers.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("{{{mediaType}}}")); + {{/produces}} + + using System.Net.Http.HttpResponseMessage responseMessage = await _httpClient.SendAsync(request, cancellationToken.GetValueOrDefault()).ConfigureAwait(false); + + string responseContent = await responseMessage.Content.ReadAsStringAsync().ConfigureAwait(false); + + ApiResponse<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Object{{/returnType}}> apiResponse = new ApiResponse<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Object{{/returnType}}>(responseMessage, responseContent); + + if (apiResponse.IsSuccessStatusCode) + apiResponse.Content = Newtonsoft.Json.JsonConvert.DeserializeObject<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Object{{/returnType}}>(apiResponse.RawContent, {{packageName}}.Client.ClientUtils.JsonSerializerSettings); + + return apiResponse; + } + {{/operation}} + } + {{/operations}} +} diff --git a/modules/openapi-generator/src/main/resources/csharp-netcore/libraries/httpclient-experimental/api_test.mustache b/modules/openapi-generator/src/main/resources/csharp-netcore/libraries/httpclient-experimental/api_test.mustache new file mode 100644 index 000000000000..87187868dfad --- /dev/null +++ b/modules/openapi-generator/src/main/resources/csharp-netcore/libraries/httpclient-experimental/api_test.mustache @@ -0,0 +1,72 @@ +{{>partial_header}} +using System; +using System.IO; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.Reflection; +using Xunit; + +using {{packageName}}.Client; +using {{packageName}}.{{apiPackage}}; +{{#hasImport}} +// uncomment below to import models +//using {{packageName}}.{{modelPackage}}; +{{/hasImport}} + +namespace {{packageName}}.Test.Api +{ + /// + /// Class for testing {{classname}} + /// + /// + /// 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 {{classname}}Tests : IDisposable + { + private readonly {{classname}} _instance; + + private readonly System.Net.Http.HttpClient _httpClient = new System.Net.Http.HttpClient(); + + public {{classname}}Tests() + { + //_instance = new {{classname}}(_httpClient); + } + + public void Dispose() + { + // Cleanup when everything is done. + } + + /// + /// Test an instance of {{classname}} + /// + [Fact] + public void {{operationId}}InstanceTest() + { + // TODO uncomment below to test 'IsType' {{classname}} + //Assert.IsType<{{classname}}>(_instance); + } + {{#operations}} + {{#operation}} + + /// + /// Test {{operationId}} + /// + [Fact] + public void {{operationId}}Test() + { + // TODO uncomment below to test the method and replace null with proper value + {{#allParams}} + //{{{dataType}}} {{paramName}} = null; + {{/allParams}} + //{{#returnType}}var response = {{/returnType}}_instance.{{operationId}}({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}); + {{#returnType}} + //Assert.IsType<{{{returnType}}}>(response); + {{/returnType}} + } + {{/operation}} + {{/operations}} + } +} diff --git a/modules/openapi-generator/src/main/resources/csharp-netcore/libraries/httpclient-experimental/model.mustache b/modules/openapi-generator/src/main/resources/csharp-netcore/libraries/httpclient-experimental/model.mustache new file mode 100644 index 000000000000..93af226b3102 --- /dev/null +++ b/modules/openapi-generator/src/main/resources/csharp-netcore/libraries/httpclient-experimental/model.mustache @@ -0,0 +1,44 @@ +{{>partial_header}} + +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; +{{#models}} +{{#model}} +{{#discriminator}} +using JsonSubTypes; +{{/discriminator}} +{{/model}} +{{/models}} +{{#validatable}} +using System.ComponentModel.DataAnnotations; +{{/validatable}} +using OpenAPIDateConverter = {{packageName}}.Client.OpenAPIDateConverter; +{{#useCompareNetObjects}} +using OpenAPIClientUtils = {{packageName}}.Client.ClientUtils; +{{/useCompareNetObjects}} +{{#models}} +{{#model}} +{{#oneOf}} +{{#-first}} +using System.Reflection; +{{/-first}} +{{/oneOf}} +{{#anyOf}} +{{#-first}} +using System.Reflection; +{{/-first}} +{{/anyOf}} + +namespace {{packageName}}.{{modelPackage}} +{ +{{#isEnum}}{{>modelEnum}}{{/isEnum}}{{^isEnum}}{{#oneOf}}{{#-first}}{{>modelOneOf}}{{/-first}}{{/oneOf}}{{#anyOf}}{{#-first}}{{>modelAnyOf}}{{/-first}}{{/anyOf}}{{^oneOf}}{{^anyOf}}{{>modelGeneric}}{{/anyOf}}{{/oneOf}}{{/isEnum}} +{{/model}} +{{/models}} +} diff --git a/modules/openapi-generator/src/main/resources/csharp-netcore/libraries/httpclient-experimental/modelGeneric.mustache b/modules/openapi-generator/src/main/resources/csharp-netcore/libraries/httpclient-experimental/modelGeneric.mustache new file mode 100644 index 000000000000..858db44de3f1 --- /dev/null +++ b/modules/openapi-generator/src/main/resources/csharp-netcore/libraries/httpclient-experimental/modelGeneric.mustache @@ -0,0 +1,353 @@ + /// + /// {{#description}}{{.}}{{/description}}{{^description}}{{classname}}{{/description}} + /// + [DataContract(Name = "{{{name}}}")] + {{#discriminator}} + [Newtonsoft.Json.JsonConverter(typeof(JsonSubtypes), "{{{discriminatorName}}}")] + {{#mappedModels}} + [JsonSubtypes.KnownSubType(typeof({{{modelName}}}), "{{^vendorExtensions.x-discriminator-value}}{{{mappingName}}}{{/vendorExtensions.x-discriminator-value}}{{#vendorExtensions.x-discriminator-value}}{{{.}}}{{/vendorExtensions.x-discriminator-value}}")] + {{/mappedModels}} + {{/discriminator}} + {{>visibility}} partial class {{classname}} : {{#parent}}{{{parent}}}, {{/parent}}IEquatable<{{classname}}>{{#validatable}}, IValidatableObject{{/validatable}} + { + {{#vars}} + {{#items.isEnum}} + {{#items}} + {{^complexType}} +{{>modelInnerEnum}} + {{/complexType}} + {{/items}} + {{/items.isEnum}} + {{#isEnum}} + {{^complexType}} +{{>modelInnerEnum}} + {{/complexType}} + {{/isEnum}} + {{#isEnum}} + /// + /// {{^description}}Gets or Sets {{{name}}}{{/description}}{{#description}}{{description}}{{/description}} + /// + {{#description}} + /// {{description}} + {{/description}} + [DataMember(Name = "{{baseName}}"{{#required}}, IsRequired = true{{/required}}, EmitDefaultValue = {{#vendorExtensions.x-emit-default-value}}true{{/vendorExtensions.x-emit-default-value}}{{^vendorExtensions.x-emit-default-value}}{{#isNullable}}true{{/isNullable}}{{^isNullable}}false{{/isNullable}}{{/vendorExtensions.x-emit-default-value}})] + public {{#complexType}}{{{complexType}}}{{/complexType}}{{^complexType}}{{{datatypeWithEnum}}}{{/complexType}}{{^isContainer}}{{^required}}?{{/required}}{{/isContainer}} {{name}} { get; set; } + + {{#isReadOnly}} + /// + /// Returns false as {{name}} should not be serialized given that it's read-only. + /// + /// false (boolean) + public bool ShouldSerialize{{name}}() + { + return false; + } + + {{/isReadOnly}} + {{/isEnum}} + {{/vars}} + {{#hasRequired}} + {{^hasOnlyReadOnly}} + /// + /// Initializes a new instance of the class. + /// + [JsonConstructorAttribute] + {{^isAdditionalPropertiesTrue}} + protected {{classname}}() { } + {{/isAdditionalPropertiesTrue}} + {{#isAdditionalPropertiesTrue}} + protected {{classname}}() + { + this.AdditionalProperties = new Dictionary(); + } + + {{/isAdditionalPropertiesTrue}} + {{/hasOnlyReadOnly}} + {{/hasRequired}} + /// + /// Initializes a new instance of the class. + /// + {{#readWriteVars}} + /// {{#description}}{{description}}{{/description}}{{^description}}{{#lambda.camelcase_param}}{{name}}{{/lambda.camelcase_param}}{{/description}}{{#required}} (required){{/required}}{{#defaultValue}} (default to {{defaultValue}}){{/defaultValue}}. + {{/readWriteVars}} + {{#hasOnlyReadOnly}} + [JsonConstructorAttribute] + {{/hasOnlyReadOnly}} + public {{classname}}({{#readWriteVars}}{{{datatypeWithEnum}}}{{#isEnum}}{{^isContainer}}{{^required}}?{{/required}}{{/isContainer}}{{/isEnum}} {{#lambda.camelcase_param}}{{name}}{{/lambda.camelcase_param}}{{^-last}}, {{/-last}}{{/readWriteVars}}){{#parent}} : base({{#parentVars}}{{#lambda.camelcase_param}}{{name}}{{/lambda.camelcase_param}}{{^-last}}, {{/-last}}{{/parentVars}}){{/parent}} + { + {{#vars}} + {{^isInherited}} + {{^isReadOnly}} + {{#required}} + {{^vendorExtensions.x-csharp-value-type}} + // to ensure "{{#lambda.camelcase_param}}{{name}}{{/lambda.camelcase_param}}" is required (not null) + {{name}} = {{#lambda.camelcase_param}}{{name}}{{/lambda.camelcase_param}} ?? throw new ArgumentNullException("{{#lambda.camelcase_param}}{{name}}{{/lambda.camelcase_param}} is a required property for {{classname}} and cannot be null"); + {{/vendorExtensions.x-csharp-value-type}} + {{#vendorExtensions.x-csharp-value-type}} + {{name}} = {{#lambda.camelcase_param}}{{name}}{{/lambda.camelcase_param}}; + {{/vendorExtensions.x-csharp-value-type}} + + {{/required}} + {{/isReadOnly}} + {{/isInherited}} + {{/vars}} + {{#vars}} + {{^isInherited}} + {{^isReadOnly}} + {{^required}} + {{#defaultValue}} + {{^vendorExtensions.x-csharp-value-type}} + // use default value if no "{{#lambda.camelcase_param}}{{name}}{{/lambda.camelcase_param}}" provided + {{name}} = {{#lambda.camelcase_param}}{{name}}{{/lambda.camelcase_param}} ?? {{{defaultValue}}}; + {{/vendorExtensions.x-csharp-value-type}} + {{#vendorExtensions.x-csharp-value-type}} + {{name}} = {{#lambda.camelcase_param}}{{name}}{{/lambda.camelcase_param}}; + {{/vendorExtensions.x-csharp-value-type}} + {{/defaultValue}} + {{^defaultValue}} + {{name}} = {{#lambda.camelcase_param}}{{name}}{{/lambda.camelcase_param}}; + {{/defaultValue}} + {{/required}} + {{/isReadOnly}} + {{/isInherited}} + {{/vars}} + {{#isAdditionalPropertiesTrue}} + AdditionalProperties = new Dictionary(); + {{/isAdditionalPropertiesTrue}} + } + + {{#vars}} + {{^isInherited}} + {{^isEnum}} + /// + /// {{^description}}Gets or Sets {{{name}}}{{/description}}{{#description}}{{description}}{{/description}} + /// {{#description}} + /// {{description}}{{/description}} + [DataMember(Name = "{{baseName}}"{{#required}}, IsRequired = true{{/required}}, EmitDefaultValue = {{#vendorExtensions.x-emit-default-value}}true{{/vendorExtensions.x-emit-default-value}}{{^vendorExtensions.x-emit-default-value}}{{#isNullable}}true{{/isNullable}}{{^isNullable}}false{{/isNullable}}{{/vendorExtensions.x-emit-default-value}})] + {{#isDate}} + [Newtonsoft.Json.JsonConverter(typeof(OpenAPIDateConverter))] + {{/isDate}} + public {{{dataType}}} {{name}} { get; {{#isReadOnly}}private {{/isReadOnly}}set; } + + {{#isReadOnly}} + /// + /// Returns false as {{name}} should not be serialized given that it's read-only. + /// + /// false (boolean) + public bool ShouldSerialize{{name}}() + { + return false; + } + + {{/isReadOnly}} + {{/isEnum}} + {{/isInherited}} + {{/vars}} + {{#isAdditionalPropertiesTrue}} + /// + /// Gets or Sets additional properties + /// + [JsonExtensionData] + public IDictionary AdditionalProperties { get; set; } + + {{/isAdditionalPropertiesTrue}} + /// + /// Returns the string presentation of the object + /// + /// String presentation of the object + public override string ToString() + { + var sb = new StringBuilder(); + sb.Append("class {{classname}} {\n"); + {{#parent}} + sb.Append(" ").Append(base.ToString().Replace("\n", "\n ")).Append('\n'); + {{/parent}} + {{#vars}} + sb.Append(" {{name}}: ").Append({{name}}).Append('\n'); + {{/vars}} + {{#isAdditionalPropertiesTrue}} + sb.Append(" AdditionalProperties: ").Append(AdditionalProperties).Append('\n'); + {{/isAdditionalPropertiesTrue}} + sb.Append("}\n"); + return sb.ToString(); + } + + /// + /// Returns the JSON string presentation of the object + /// + /// JSON string presentation of the object + public {{#parent}}{{^isArray}}{{^isMap}}override {{/isMap}}{{/isArray}}{{/parent}}{{^parent}}virtual {{/parent}}string ToJson(Newtonsoft.Json.JsonSerializerSettings? jsonSerializerSettings = null) + { + return Newtonsoft.Json.JsonConvert.SerializeObject(this, jsonSerializerSettings ?? {{packageName}}.Client.ClientUtils.JsonSerializerSettings); + } + + /// + /// Returns true if objects are equal + /// + /// Object to be compared + /// Boolean + public override bool Equals(object{{#nullableReferenceTypes}}?{{/nullableReferenceTypes}} input) + { + {{#useCompareNetObjects}} + return OpenAPIClientUtils.compareLogic.Compare(this, input as {{classname}}).AreEqual; + {{/useCompareNetObjects}} + {{^useCompareNetObjects}} + return Equals(input as {{classname}}); + {{/useCompareNetObjects}} + } + + /// + /// Returns true if {{classname}} instances are equal + /// + /// Instance of {{classname}} to be compared + /// Boolean + public bool Equals({{classname}}? input) + { + {{#useCompareNetObjects}} + return OpenAPIClientUtils.compareLogic.Compare(this, input).AreEqual; + {{/useCompareNetObjects}} + {{^useCompareNetObjects}} + if (input == null) + return false; + + return {{#vars}}{{#parent}}base.Equals(input) && {{/parent}}{{^isContainer}} + ( + {{name}} == input.{{name}} || + {{^vendorExtensions.x-is-value-type}} + ({{name}} != null && + {{name}}.Equals(input.{{name}})) + {{/vendorExtensions.x-is-value-type}} + {{#vendorExtensions.x-is-value-type}} + {{name}}.Equals(input.{{name}}) + {{/vendorExtensions.x-is-value-type}} + ){{^-last}} && {{/-last}}{{/isContainer}}{{#isContainer}} + ( + {{name}} == input.{{name}} || + {{^vendorExtensions.x-is-value-type}}{{name}} != null && + input.{{name}} != null && + {{/vendorExtensions.x-is-value-type}}{{name}}.SequenceEqual(input.{{name}}) + ){{^-last}} && {{/-last}}{{/isContainer}}{{/vars}}{{^vars}}{{#parent}}base.Equals(input){{/parent}}{{^parent}}false{{/parent}}{{/vars}}{{^isAdditionalPropertiesTrue}};{{/isAdditionalPropertiesTrue}} + {{#isAdditionalPropertiesTrue}} + && (AdditionalProperties.Count == input.AdditionalProperties.Count && !AdditionalProperties.Except(input.AdditionalProperties).Any()); + {{/isAdditionalPropertiesTrue}} + {{/useCompareNetObjects}} + } + + /// + /// Gets the hash code + /// + /// Hash code + public override int GetHashCode() + { + unchecked // Overflow is fine, just wrap + { + {{#parent}} + int hashCode = base.GetHashCode(); + {{/parent}} + {{^parent}} + int hashCode = 41; + {{/parent}} + {{#vars}} + {{^vendorExtensions.x-is-value-type}} + if (this.{{name}} != null) + hashCode = hashCode * 59 + this.{{name}}.GetHashCode(); + {{/vendorExtensions.x-is-value-type}} + {{#vendorExtensions.x-is-value-type}} + hashCode = hashCode * 59 + this.{{name}}.GetHashCode(); + {{/vendorExtensions.x-is-value-type}} + {{/vars}} + {{#isAdditionalPropertiesTrue}} + if (this.AdditionalProperties != null) + hashCode = hashCode * 59 + this.AdditionalProperties.GetHashCode(); + {{/isAdditionalPropertiesTrue}} + return hashCode; + } + } + +{{#validatable}} +{{#discriminator}} + /// + /// To validate all properties of the instance + /// + /// Validation context + /// Validation Result + IEnumerable IValidatableObject.Validate(ValidationContext validationContext) + { + return this.BaseValidate(validationContext); + } + + /// + /// To validate all properties of the instance + /// + /// Validation context + /// Validation Result + protected IEnumerable BaseValidate(ValidationContext validationContext) + { +{{/discriminator}} +{{^discriminator}} + /// + /// To validate all properties of the instance + /// + /// Validation context + /// Validation Result + IEnumerable IValidatableObject.Validate(ValidationContext validationContext) + { +{{/discriminator}} + {{#parent}} + {{^isArray}} + {{^isMap}} + foreach(var x in BaseValidate(validationContext)) yield return x; + {{/isMap}} + {{/isArray}} + {{/parent}} + {{#vars}} + {{#hasValidation}} + {{#maxLength}} + // {{{name}}} ({{{dataType}}}) maxLength + if(this.{{{name}}} != null && this.{{{name}}}.Length > {{maxLength}}) + { + yield return new System.ComponentModel.DataAnnotations.ValidationResult("Invalid value for {{{name}}}, length must be less than {{maxLength}}.", new [] { "{{{name}}}" }); + } + + {{/maxLength}} + {{#minLength}} + // {{{name}}} ({{{dataType}}}) minLength + if(this.{{{name}}} != null && this.{{{name}}}.Length < {{minLength}}) + { + yield return new System.ComponentModel.DataAnnotations.ValidationResult("Invalid value for {{{name}}}, length must be greater than {{minLength}}.", new [] { "{{{name}}}" }); + } + + {{/minLength}} + {{#maximum}} + // {{{name}}} ({{{dataType}}}) maximum + if(this.{{{name}}} > ({{{dataType}}}){{maximum}}) + { + yield return new System.ComponentModel.DataAnnotations.ValidationResult("Invalid value for {{{name}}}, must be a value less than or equal to {{maximum}}.", new [] { "{{{name}}}" }); + } + + {{/maximum}} + {{#minimum}} + // {{{name}}} ({{{dataType}}}) minimum + if(this.{{{name}}} < ({{{dataType}}}){{minimum}}) + { + yield return new System.ComponentModel.DataAnnotations.ValidationResult("Invalid value for {{{name}}}, must be a value greater than or equal to {{minimum}}.", new [] { "{{{name}}}" }); + } + + {{/minimum}} + {{#pattern}} + {{^isByteArray}} + // {{{name}}} ({{{dataType}}}) pattern + Regex regex{{{name}}} = new Regex(@"{{{vendorExtensions.x-regex}}}"{{#vendorExtensions.x-modifiers}}{{#-first}}, {{/-first}}RegexOptions.{{{.}}}{{^-last}} | {{/-last}}{{/vendorExtensions.x-modifiers}}); + if (false == regex{{{name}}}.Match(this.{{{name}}}).Success) + { + yield return new System.ComponentModel.DataAnnotations.ValidationResult("Invalid value for {{{name}}}, must match a pattern of " + regex{{{name}}}, new [] { "{{{name}}}" }); + } + + {{/isByteArray}} + {{/pattern}} + {{/hasValidation}} + {{/vars}} + yield break; + } +{{/validatable}} + } diff --git a/modules/openapi-generator/src/main/resources/csharp-netcore/libraries/httpclient-experimental/modelInnerEnum.mustache b/modules/openapi-generator/src/main/resources/csharp-netcore/libraries/httpclient-experimental/modelInnerEnum.mustache new file mode 100644 index 000000000000..8c17023f38a0 --- /dev/null +++ b/modules/openapi-generator/src/main/resources/csharp-netcore/libraries/httpclient-experimental/modelInnerEnum.mustache @@ -0,0 +1,26 @@ + {{^isContainer}} + /// + /// {{^description}}Defines {{{name}}}{{/description}}{{#description}}{{description}}{{/description}} + /// + {{#description}} + /// {{description}} + {{/description}} + {{#isString}} + [Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))] + {{/isString}} + {{>visibility}} enum {{#datatypeWithEnum}}{{.}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}}{{#vendorExtensions.x-enum-byte}}: byte{{/vendorExtensions.x-enum-byte}} + { + {{#allowableValues}} + {{#enumVars}} + /// + /// Enum {{name}} for value: {{{value}}} + /// + {{#isString}} + [EnumMember(Value = "{{{value}}}")] + {{/isString}} + {{name}}{{^isString}} = {{{value}}}{{/isString}}{{#isString}} = {{-index}}{{/isString}}{{^-last}},{{/-last}} + + {{/enumVars}} + {{/allowableValues}} + } + {{/isContainer}} diff --git a/modules/openapi-generator/src/main/resources/csharp-netcore/libraries/httpclient-experimental/model_test.mustache b/modules/openapi-generator/src/main/resources/csharp-netcore/libraries/httpclient-experimental/model_test.mustache new file mode 100644 index 000000000000..43510ade64ee --- /dev/null +++ b/modules/openapi-generator/src/main/resources/csharp-netcore/libraries/httpclient-experimental/model_test.mustache @@ -0,0 +1,80 @@ +{{>partial_header}} + +using Xunit; + +using System; +using System.Linq; +using System.IO; +using System.Collections.Generic; +using {{packageName}}.{{apiPackage}}; +using {{packageName}}.{{modelPackage}}; +using {{packageName}}.Client; +using Newtonsoft.Json; + +{{#models}} +{{#model}} +namespace {{packageName}}.Test.Model +{ + /// + /// Class for testing {{classname}} + /// + /// + /// This file is automatically generated by OpenAPI Generator (https://openapi-generator.tech). + /// Please update the test case below to test the model. + /// + public class {{classname}}Tests : IDisposable + { + // TODO uncomment below to declare an instance variable for {{classname}} + //private {{classname}} instance; + + public {{classname}}Tests() + { + // TODO uncomment below to create an instance of {{classname}} + //instance = new {{classname}}(); + } + + public void Dispose() + { + // Cleanup when everything is done. + } + + /// + /// Test an instance of {{classname}} + /// + [Fact] + public void {{classname}}InstanceTest() + { + // TODO uncomment below to test "IsType" {{classname}} + //Assert.IsType<{{classname}}>(instance); + } + + {{#discriminator}} + {{#children}} + /// + /// Test deserialize a {{classname}} from type {{parent}} + /// + [Fact] + public void {{classname}}DeserializeFrom{{parent}}Test() + { + // TODO uncomment below to test deserialize a {{classname}} from type {{parent}} + //Assert.IsType<{{parent}}>(JsonConvert.DeserializeObject<{{parent}}>(new {{classname}}().ToJson())); + } + {{/children}} + {{/discriminator}} + + {{#vars}} + /// + /// Test the property '{{name}}' + /// + [Fact] + public void {{name}}Test() + { + // TODO unit test for the property '{{name}}' + } + {{/vars}} + + } + +} +{{/model}} +{{/models}} diff --git a/modules/openapi-generator/src/main/resources/csharp-netcore/libraries/httpclient-experimental/netcore_project.mustache b/modules/openapi-generator/src/main/resources/csharp-netcore/libraries/httpclient-experimental/netcore_project.mustache new file mode 100644 index 000000000000..1445b0967eac --- /dev/null +++ b/modules/openapi-generator/src/main/resources/csharp-netcore/libraries/httpclient-experimental/netcore_project.mustache @@ -0,0 +1,39 @@ + + + + false + {{targetFramework}} + {{packageName}} + {{packageName}} + Library + {{packageAuthors}} + {{packageCompany}} + {{packageTitle}} + {{packageDescription}} + {{packageCopyright}} + {{packageName}} + {{packageVersion}} + bin\$(Configuration)\$(TargetFramework)\{{packageName}}.xml{{#licenseId}} + {{licenseId}}{{/licenseId}} + https://{{{gitHost}}}/{{{gitUserId}}}/{{{gitRepoId}}}.git + git{{#releaseNote}} + {{releaseNote}}{{/releaseNote}}{{#packageTags}} + {{{packageTags}}}{{/packageTags}} + {{#nullableReferenceTypes}} + enable + {{/nullableReferenceTypes}} + + + + {{#useCompareNetObjects}} + + {{/useCompareNetObjects}} + + + + {{#validatable}} + + {{/validatable}} + + + diff --git a/modules/openapi-generator/src/main/resources/csharp-netcore/libraries/httpclient-experimental/netcore_testproject.mustache b/modules/openapi-generator/src/main/resources/csharp-netcore/libraries/httpclient-experimental/netcore_testproject.mustache new file mode 100644 index 000000000000..6310c2e17084 --- /dev/null +++ b/modules/openapi-generator/src/main/resources/csharp-netcore/libraries/httpclient-experimental/netcore_testproject.mustache @@ -0,0 +1,21 @@ + + + + {{testPackageName}} + {{testPackageName}} + net5.0 + enable + false + + + + + + + + + + + + + diff --git a/modules/openapi-generator/src/main/resources/csharp-netcore/libraries/httpclient-experimental/nuspec.mustache b/modules/openapi-generator/src/main/resources/csharp-netcore/libraries/httpclient-experimental/nuspec.mustache new file mode 100644 index 000000000000..4b9b30a5fe25 --- /dev/null +++ b/modules/openapi-generator/src/main/resources/csharp-netcore/libraries/httpclient-experimental/nuspec.mustache @@ -0,0 +1,51 @@ + + + + + $id$ + {{packageTitle}} + + + $version$ + + + $author$ + + + $author$ + false + false + + + {{packageDescription}} + {{#termsOfService}} + {{termsOfService}} + {{/termsOfService}} + {{#licenseUrl}} + {{licenseUrl}} + {{/licenseUrl}} + + + + + + {{#useCompareNetObjects}} + + {{/useCompareNetObjects}} + + {{#validatable}} + + {{/validatable}} + + + + + + + + + + + diff --git a/modules/openapi-generator/src/main/resources/csharp-netcore/libraries/httpclient/ApiClient.mustache b/modules/openapi-generator/src/main/resources/csharp-netcore/libraries/httpclient/ApiClient.mustache index 4c31f4e127b8..6dc86933f44d 100644 --- a/modules/openapi-generator/src/main/resources/csharp-netcore/libraries/httpclient/ApiClient.mustache +++ b/modules/openapi-generator/src/main/resources/csharp-netcore/libraries/httpclient/ApiClient.mustache @@ -696,4 +696,4 @@ namespace {{packageName}}.Client } #endregion ISynchronousClient } -} +} \ No newline at end of file diff --git a/samples/client/petstore/csharp-netcore/OpenAPIClient-httpclient/src/Org.OpenAPITools/Client/ApiClient.cs b/samples/client/petstore/csharp-netcore/OpenAPIClient-httpclient/src/Org.OpenAPITools/Client/ApiClient.cs index 43dba5694832..8846c2bc1587 100644 --- a/samples/client/petstore/csharp-netcore/OpenAPIClient-httpclient/src/Org.OpenAPITools/Client/ApiClient.cs +++ b/samples/client/petstore/csharp-netcore/OpenAPIClient-httpclient/src/Org.OpenAPITools/Client/ApiClient.cs @@ -670,4 +670,4 @@ public ApiResponse Patch(string path, RequestOptions options, IReadableCon } #endregion ISynchronousClient } -} +} \ No newline at end of file