diff --git a/config/csharp.yaml b/config/csharp.yaml index d812e21e..b3b00209 100644 --- a/config/csharp.yaml +++ b/config/csharp.yaml @@ -1,6 +1,7 @@ changelog: - 1.5.0 (2024-07-19): - fix nuget package (closes \#131) + - add *Async() methods (closes \#132) - 1.4.0 (2024-06-11): - .net 5.0 support - 1.3.1 (2024-02-19): diff --git a/templates/csharp/ApiClient.mustache b/templates/csharp/ApiClient.mustache index 3143202a..4fa83096 100644 --- a/templates/csharp/ApiClient.mustache +++ b/templates/csharp/ApiClient.mustache @@ -352,7 +352,7 @@ namespace {{packageName}}.Client /// Content type. /// Cancellation Token. /// The Task instance. - public async System.Threading.Tasks.Task CallApiAsync( + public async System.Threading.Tasks.Task CallApiAsync( string path, {{^netStandard}}RestSharp.{{/netStandard}}Method method, List> queryParams, Object postBody, Dictionary headerParams, Dictionary formParams, Dictionary fileParams, Dictionary pathParams, @@ -363,7 +363,7 @@ namespace {{packageName}}.Client pathParams, contentType); request = InterceptRequest(request); var response = await RestClient.Execute{{^netStandard}}Async{{/netStandard}}(request, cancellationToken); - return (Object)response; + return (RestResponse)response; }{{/supportsAsync}} /// diff --git a/templates/csharp/api.mustache b/templates/csharp/api.mustache index cebec12e..03b10d10 100644 --- a/templates/csharp/api.mustache +++ b/templates/csharp/api.mustache @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; using System.Threading; +using System.Threading.Tasks; using System.IO; using {{packageName}}.Upload; {{#netStandard}} @@ -39,6 +40,25 @@ namespace {{packageName}}.{{apiPackage}} } {{#operation}} + /// + /// {{summary}} {{#multiline_comment}}{{notes}}{{/multiline_comment}} + /// + /// Thrown when fails to make API call + /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. (optional) + {{#allParams}}/// {{description}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} + {{/allParams}} + {{#vendorExtensions.x-client-chunk-upload}}/// Progress listener called after each chunk upload{{/vendorExtensions.x-client-chunk-upload}} + /// {{#returnType}}{{returnType}}{{/returnType}} + {{#isDeprecated}} + [Obsolete] + {{/isDeprecated}} + public {{#returnType}}Task<{{{returnType}}}>{{/returnType}}{{^returnType}}void{{/returnType}} {{operationId}}Async({{#allParams}}{{{dataType}}} {{paramName}}{{^required}}{{#optionalMethodArgument}} = default{{/optionalMethodArgument}}{{/required}}{{^-last}}, {{/-last}}{{/allParams}}{{#vendorExtensions.x-client-chunk-upload}},IUploadProgressListener progressListener = null{{/vendorExtensions.x-client-chunk-upload}}, CancellationToken cancellationToken = default) + { + {{#returnType}}Task> localVarResponse = {{operationId}}WithHttpInfoAsync({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}{{#vendorExtensions.x-client-chunk-upload}},progressListener{{/vendorExtensions.x-client-chunk-upload}}, cancellationToken); + return localVarResponse.ContinueWith((Task> task) => task.Result.Data ); + {{/returnType}}{{^returnType}}{{operationId}}WithHttpInfoAsync({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}, cancellationToken);{{/returnType}} + } + /// /// {{summary}} {{#multiline_comment}}{{notes}}{{/multiline_comment}} /// @@ -56,6 +76,195 @@ namespace {{packageName}}.{{apiPackage}} return localVarResponse.Data;{{/returnType}}{{^returnType}}{{operationId}}WithHttpInfo({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}});{{/returnType}} } + + /// + /// {{summary}} {{#multiline_comment}}{{notes}}{{/multiline_comment}} + /// + /// Thrown when fails to make API call + /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. (optional) + {{#allParams}}/// {{description}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} + {{/allParams}} + {{#vendorExtensions.x-client-chunk-upload}}/// Progress listener called after each chunk upload{{/vendorExtensions.x-client-chunk-upload}} + /// ApiResponse of {{#returnType}}{{returnType}}{{/returnType}}{{^returnType}}Object(void){{/returnType}} + {{#isDeprecated}} + [Obsolete] + {{/isDeprecated}} + public Task> {{operationId}}WithHttpInfoAsync({{#allParams}}{{{dataType}}} {{paramName}}{{^required}}{{#optionalMethodArgument}} = default{{/optionalMethodArgument}}{{/required}}{{^-last}}, {{/-last}}{{/allParams}}{{#vendorExtensions.x-client-chunk-upload}},IUploadProgressListener progressListener = null{{/vendorExtensions.x-client-chunk-upload}}, CancellationToken cancellationToken = default) + { + {{#allParams}} + {{#bodyParam}} + if ({{paramName}} == null) + throw new ApiException(400,"Missing required parameter '{{paramName}}' when calling {{classname}}->{{operationId}}"); + + {{# vars }} + {{#required}} + if ({{paramName}} != null && {{paramName}}.{{#lambda.lowercase}}{{name}}{{/lambda.lowercase}} == null) { + throw new ApiException(400,"Missing required parameter '{{paramName}}.{{name}}' when calling {{classname}}->{{operationId}}"); + } + {{/required}} + {{/vars}}{{/bodyParam}} + {{/allParams}} + {{#allParams}} + {{#required}} + // verify the required parameter '{{paramName}}' is set + if ({{paramName}} == null) + throw new ApiException(400, "Missing required parameter '{{paramName}}' when calling {{classname}}->{{operationId}}"); + {{/required}} + {{/allParams}} + + {{#vendorExtensions.x-client-chunk-upload}} + long totalBytes = file.Length; + int chunkSize = Convert.ToInt32(this.ApiClient.UploadChunkSize); + {{/vendorExtensions.x-client-chunk-upload}} + + var localVarPath = "{{#netStandard}}.{{/netStandard}}{{{path}}}"; + var localVarPathParams = new Dictionary(); + var localVarQueryParams = new List>(); + var localVarHeaderParams = new Dictionary(); + var localVarFormParams = new Dictionary(); + var localVarFileParams = new Dictionary(); + Object localVarPostBody = null; + + // to determine the Content-Type header + string[] localVarContentTypes = new string[] { + {{#consumes}} + "{{{mediaType}}}"{{^-last}}, {{/-last}} + {{/consumes}} + }; + string localVarContentType = ApiClient.SelectHeaderContentType(localVarContentTypes); + localVarHeaderParams.Add("Content-Type", localVarContentType); + // to determine the Accept header + string[] localVarHttpHeaderAccepts = new string[] { + {{#produces}} + "{{{mediaType}}}"{{^-last}}, {{/-last}} + {{/produces}} + }; + string localVarHttpHeaderAccept = ApiClient.SelectHeaderAccept(localVarHttpHeaderAccepts); + if (localVarHttpHeaderAccept != null) + localVarHeaderParams.Add("Accept", localVarHttpHeaderAccept); + + {{#pathParams}} + if ({{paramName}} != null) localVarPathParams.Add("{{baseName}}", this.ApiClient.ParameterToString({{paramName}})); // path parameter + {{/pathParams}} + {{#queryParams}} + if ({{paramName}} != null) localVarQueryParams.AddRange(this.ApiClient.ParameterToKeyValuePairs("{{#collectionFormat}}{{collectionFormat}}{{/collectionFormat}}", "{{baseName}}", {{paramName}})); // query parameter + {{/queryParams}} + {{#headerParams}} + if ({{paramName}} != null) localVarHeaderParams.Add("{{baseName}}", this.ApiClient.ParameterToString({{paramName}})); // header parameter + {{/headerParams}} + {{#formParams}} + {{^isFile}}if ({{paramName}} != null) + localVarFormParams.Add("{{baseName}}", {{#vendorExtensions.x-is-json}}{{paramName}}.ToJson(){{/vendorExtensions.x-is-json}}{{^vendorExtensions.x-is-json}}this.ApiClient.{{#isPrimitiveType}}ParameterToString{{/isPrimitiveType}}{{^isPrimitiveType}}Serialize{{/isPrimitiveType}}({{paramName}}){{/vendorExtensions.x-is-json}}); // form parameter{{/isFile}} + {{/formParams}} + {{#bodyParam}} + if ({{paramName}} != null && {{paramName}}.GetType() != typeof(byte[]) && {{paramName}}.GetType() != typeof(string)) + { + localVarPostBody = this.ApiClient.Serialize({{paramName}}); // http body (model) parameter + } + else + { + localVarPostBody = {{paramName}}; // byte array + } + {{/bodyParam}} + + {{#vendorExtensions.x-client-chunk-upload}} + if (totalBytes > chunkSize) + { + Task> lastRes = null; + localVarHeaderParams.Add("Content-Range", ""); + var chunkNum = 0; + int chunkCount = (int)Math.Ceiling((double)totalBytes / (double)chunkSize); + for (int i = 0; i < totalBytes; i += chunkSize) + { + chunkNum++; + byte[] buffer = new byte[chunkSize]; + if(i + chunkSize >= totalBytes) { + localVarHeaderParams["Content-Range"] = "part " + chunkNum + "/" + chunkNum; + } else { + localVarHeaderParams["Content-Range"] = "part " + chunkNum + "/*"; + } + + file.Read(buffer, 0, chunkSize); + + if(buffer != null) + { + if(localVarFileParams.ContainsKey("file")) + { + localVarFileParams["file"] = this.ApiClient.ParameterToFile("file", file, buffer); + } + else + { + localVarFileParams.Add("file",this.ApiClient.ParameterToFile("file", file, buffer)); + } + } + + // make the HTTP request + Task localVarResponse = this.ApiClient.CallApiAsync(localVarPath, + Method.Post, localVarQueryParams, localVarPostBody, localVarHeaderParams, localVarFormParams, localVarFileParams, + localVarPathParams, localVarContentType, cancellationToken); + + int localVarStatusCode = (int) localVarResponse.Result.StatusCode; + lastRes = localVarResponse.ContinueWith((Task task) => + { + return new ApiResponse