diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5a237a2e1a..5353e2ded5 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -11,6 +11,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Ruby JSON serialization #429
+### Changed
+
+- Fixed a bug where raw collections requests would not be supported #467
+
## [0.0.7] - 2021-08-04
### Added
diff --git a/abstractions/dotnet/src/IHttpCore.cs b/abstractions/dotnet/src/IHttpCore.cs
index 04f816cc0c..1f6ab4b198 100644
--- a/abstractions/dotnet/src/IHttpCore.cs
+++ b/abstractions/dotnet/src/IHttpCore.cs
@@ -1,3 +1,4 @@
+using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.Kiota.Abstractions.Serialization;
@@ -22,6 +23,13 @@ public interface IHttpCore {
/// The deserialized response model.
Task SendAsync(RequestInfo requestInfo, IResponseHandler responseHandler = default) where ModelType : IParsable;
///
+ /// Excutes the HTTP request specified by the given RequestInfo and returns the deserialized response model collection.
+ ///
+ /// The RequestInfo object to use for the HTTP request.
+ /// The response handler to use for the HTTP request instead of the default handler.
+ /// The deserialized response model collection.
+ Task> SendCollectionAsync(RequestInfo requestInfo, IResponseHandler responseHandler = default) where ModelType : IParsable;
+ ///
/// Excutes the HTTP request specified by the given RequestInfo and returns the deserialized primitive response model.
///
/// The RequestInfo object to use for the HTTP request.
diff --git a/abstractions/dotnet/src/Microsoft.Kiota.Abstractions.csproj b/abstractions/dotnet/src/Microsoft.Kiota.Abstractions.csproj
index c8689b793a..19efcc8c81 100644
--- a/abstractions/dotnet/src/Microsoft.Kiota.Abstractions.csproj
+++ b/abstractions/dotnet/src/Microsoft.Kiota.Abstractions.csproj
@@ -4,7 +4,7 @@
net5.0
true
https://github.com/microsoft/kiota
- 1.0.14
+ 1.0.15
diff --git a/abstractions/dotnet/src/RequestInfo.cs b/abstractions/dotnet/src/RequestInfo.cs
index e26c814b51..0b588e1e37 100644
--- a/abstractions/dotnet/src/RequestInfo.cs
+++ b/abstractions/dotnet/src/RequestInfo.cs
@@ -69,15 +69,19 @@ public void SetStreamContent(Stream content) {
/// Sets the request body from a model with the specified content type.
///
/// The core service to get the serialization writer from.
- /// The model to serialize.
+ /// The models to serialize.
/// The content type to set.
/// The model type to serialize.
- public void SetContentFromParsable(T item, IHttpCore coreService, string contentType) where T : IParsable {
+ public void SetContentFromParsable(IHttpCore coreService, string contentType, params T[] items) where T : IParsable {
if(string.IsNullOrEmpty(contentType)) throw new ArgumentNullException(nameof(contentType));
if(coreService == null) throw new ArgumentNullException(nameof(coreService));
+ if(items == null || !items.Any()) throw new InvalidOperationException($"{nameof(items)} cannot be null or empty");
using var writer = coreService.SerializationWriterFactory.GetSerializationWriter(contentType);
- writer.WriteObjectValue(null, item);
+ if(items.Count() == 1)
+ writer.WriteObjectValue(null, items[0]);
+ else
+ writer.WriteCollectionOfObjectValues(null, items);
Headers.Add(contentTypeHeader, contentType);
Content = writer.GetSerializedContent();
}
diff --git a/abstractions/java/lib/build.gradle b/abstractions/java/lib/build.gradle
index efff7f9aa9..35a741340a 100644
--- a/abstractions/java/lib/build.gradle
+++ b/abstractions/java/lib/build.gradle
@@ -46,7 +46,7 @@ publishing {
publications {
gpr(MavenPublication) {
artifactId 'kiota-abstractions'
- version '1.0.14'
+ version '1.0.15'
from(components.java)
}
}
diff --git a/abstractions/java/lib/src/main/java/com/microsoft/kiota/HttpCore.java b/abstractions/java/lib/src/main/java/com/microsoft/kiota/HttpCore.java
index 9702f3b352..0401f52db6 100644
--- a/abstractions/java/lib/src/main/java/com/microsoft/kiota/HttpCore.java
+++ b/abstractions/java/lib/src/main/java/com/microsoft/kiota/HttpCore.java
@@ -1,6 +1,7 @@
package com.microsoft.kiota;
import java.util.concurrent.CompletableFuture;
+import java.util.List;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
@@ -27,6 +28,15 @@ public interface HttpCore {
* @return a {@link CompletableFuture} with the deserialized response model.
*/
CompletableFuture sendAsync(@Nonnull final RequestInfo requestInfo, @Nonnull final Class targetClass, @Nullable final ResponseHandler responseHandler);
+ /**
+ * Excutes the HTTP request specified by the given RequestInfo and returns the deserialized response model collection.
+ * @param requestInfo the request info to execute.
+ * @param responseHandler The response handler to use for the HTTP request instead of the default handler.
+ * @param targetClass the class of the response model to deserialize the response into.
+ * @param the type of the response model to deserialize the response into.
+ * @return a {@link CompletableFuture} with the deserialized response model collection.
+ */
+ CompletableFuture> sendCollectionAsync(@Nonnull final RequestInfo requestInfo, @Nonnull final Class targetClass, @Nullable final ResponseHandler responseHandler);
/**
* Excutes the HTTP request specified by the given RequestInfo and returns the deserialized primitive response model.
* @param requestInfo the request info to execute.
diff --git a/abstractions/java/lib/src/main/java/com/microsoft/kiota/RequestInfo.java b/abstractions/java/lib/src/main/java/com/microsoft/kiota/RequestInfo.java
index 5498b5f12a..836637672c 100644
--- a/abstractions/java/lib/src/main/java/com/microsoft/kiota/RequestInfo.java
+++ b/abstractions/java/lib/src/main/java/com/microsoft/kiota/RequestInfo.java
@@ -3,6 +3,7 @@
import java.net.URI;
import java.io.IOException;
import java.io.InputStream;
+import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Objects;
@@ -71,18 +72,23 @@ public void setStreamContent(@Nonnull final InputStream value) {
}
/**
* Sets the request body from a model with the specified content type.
- * @param value the model.
+ * @param values the models.
* @param contentType the content type.
* @param httpCore The core service to get the serialization writer from.
* @param the model type.
*/
- public void setContentFromParsable(@Nonnull final T value, @Nonnull final HttpCore httpCore, @Nonnull final String contentType) {
+ public void setContentFromParsable(@Nonnull final HttpCore httpCore, @Nonnull final String contentType, @Nonnull final T... values) {
Objects.requireNonNull(httpCore);
- Objects.requireNonNull(value);
+ Objects.requireNonNull(values);
Objects.requireNonNull(contentType);
+ if(values.length == 0) throw new RuntimeException("values cannot be empty");
+
try(final SerializationWriter writer = httpCore.getSerializationWriterFactory().getSerializationWriter(contentType)) {
headers.put(contentTypeHeader, contentType);
- writer.writeObjectValue(null, value);
+ if(values.length == 1)
+ writer.writeObjectValue(null, values[0]);
+ else
+ writer.writeCollectionOfObjectValues(null, Arrays.asList(values));
this.content = writer.getSerializedContent();
} catch (IOException ex) {
throw new RuntimeException("could not serialize payload", ex);
diff --git a/abstractions/ruby/microsoft_kiota_abstractions/lib/microsoft_kiota_abstractions/request_info.rb b/abstractions/ruby/microsoft_kiota_abstractions/lib/microsoft_kiota_abstractions/request_info.rb
index ff46ffcb03..35c6828207 100644
--- a/abstractions/ruby/microsoft_kiota_abstractions/lib/microsoft_kiota_abstractions/request_info.rb
+++ b/abstractions/ruby/microsoft_kiota_abstractions/lib/microsoft_kiota_abstractions/request_info.rb
@@ -28,11 +28,15 @@ def set_stream_content(value = $stdin)
@headers[@@content_type_header] = @@binary_content_type
end
- def set_content_from_parsable(value, serializer_factory, content_type)
+ def set_content_from_parsable(serializer_factory, content_type, values)
begin
writer = serializer_factory.get_serialization_writer(content_type)
headers[@@content_type_header] = content_type
- writer.write_object_value(nil, value);
+ if values != nil && values.kind_of?(Array)
+ writer.write_collection_of_object_values(nil, values)
+ else
+ writer.write_object_value(nil, values);
+ end
this.content = writer.get_serialized_content();
rescue => exception
raise Exception.new "could not serialize payload"
diff --git a/abstractions/ruby/microsoft_kiota_abstractions/lib/microsoft_kiota_abstractions/version.rb b/abstractions/ruby/microsoft_kiota_abstractions/lib/microsoft_kiota_abstractions/version.rb
index c1fcf77781..c0d254ba88 100644
--- a/abstractions/ruby/microsoft_kiota_abstractions/lib/microsoft_kiota_abstractions/version.rb
+++ b/abstractions/ruby/microsoft_kiota_abstractions/lib/microsoft_kiota_abstractions/version.rb
@@ -1,5 +1,5 @@
# frozen_string_literal: true
module MicrosoftKiotaAbstractions
- VERSION = "0.1.1"
+ VERSION = "0.1.2"
end
diff --git a/abstractions/typescript/package-lock.json b/abstractions/typescript/package-lock.json
index 3937378476..a4425989b7 100644
--- a/abstractions/typescript/package-lock.json
+++ b/abstractions/typescript/package-lock.json
@@ -1,6 +1,6 @@
{
"name": "@microsoft/kiota-abstractions",
- "version": "1.0.14",
+ "version": "1.0.15",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
diff --git a/abstractions/typescript/package.json b/abstractions/typescript/package.json
index ce5df1df10..4bac866b94 100644
--- a/abstractions/typescript/package.json
+++ b/abstractions/typescript/package.json
@@ -1,6 +1,6 @@
{
"name": "@microsoft/kiota-abstractions",
- "version": "1.0.14",
+ "version": "1.0.15",
"description": "Core abstractions for kiota generated libraries in TypeScript and JavaScript",
"main": "dist/index.js",
"types": "dist/index.d.ts",
diff --git a/abstractions/typescript/src/httpCore.ts b/abstractions/typescript/src/httpCore.ts
index cad8b8132f..80094ed1f8 100644
--- a/abstractions/typescript/src/httpCore.ts
+++ b/abstractions/typescript/src/httpCore.ts
@@ -18,6 +18,15 @@ export interface HttpCore {
* @return a {@link Promise} with the deserialized response model.
*/
sendAsync(requestInfo: RequestInfo, type: new() => ModelType, responseHandler: ResponseHandler | undefined): Promise;
+ /**
+ * Excutes the HTTP request specified by the given RequestInfo and returns the deserialized response model collection.
+ * @param requestInfo the request info to execute.
+ * @param responseHandler The response handler to use for the HTTP request instead of the default handler.
+ * @param type the class of the response model to deserialize the response into.
+ * @typeParam ModelType the type of the response model to deserialize the response into.
+ * @return a {@link Promise} with the deserialized response model collection.
+ */
+ sendCollectionAsync(requestInfo: RequestInfo, type: new() => ModelType, responseHandler: ResponseHandler | undefined): Promise;
/**
* Excutes the HTTP request specified by the given RequestInfo and returns the deserialized primitive response model.
* @param requestInfo the request info to execute.
diff --git a/abstractions/typescript/src/requestInfo.ts b/abstractions/typescript/src/requestInfo.ts
index 5973f39961..96d46f8789 100644
--- a/abstractions/typescript/src/requestInfo.ts
+++ b/abstractions/typescript/src/requestInfo.ts
@@ -36,18 +36,22 @@ export class RequestInfo {
private static contentTypeHeader = "Content-Type";
/**
* Sets the request body from a model with the specified content type.
- * @param value the model.
+ * @param values the models.
* @param contentType the content type.
* @param httpCore The core service to get the serialization writer from.
* @typeParam T the model type.
*/
- public setContentFromParsable = (value?: T | undefined, httpCore?: HttpCore | undefined, contentType?: string | undefined): void => {
+ public setContentFromParsable = (httpCore?: HttpCore | undefined, contentType?: string | undefined, ...values: T[]): void => {
if(!httpCore) throw new Error("httpCore cannot be undefined");
if(!contentType) throw new Error("contentType cannot be undefined");
+ if(!values || values.length === 0) throw new Error("values cannot be undefined or empty");
const writer = httpCore.getSerializationWriterFactory().getSerializationWriter(contentType);
this.headers.set(RequestInfo.contentTypeHeader, contentType);
- writer.writeObjectValue(undefined, value);
+ if(values.length === 1)
+ writer.writeObjectValue(undefined, values[0]);
+ else
+ writer.writeCollectionOfObjectValues(undefined, values);
this.content = writer.getSerializedContent();
}
/**
diff --git a/http/dotnet/httpclient/src/HttpCore.cs b/http/dotnet/httpclient/src/HttpCore.cs
index 8bfe6ce6d3..d8b2300579 100644
--- a/http/dotnet/httpclient/src/HttpCore.cs
+++ b/http/dotnet/httpclient/src/HttpCore.cs
@@ -35,6 +35,17 @@ public HttpCore(IAuthenticationProvider authenticationProvider, IParseNodeFactor
}
/// Factory to use to get a serializer for payload serialization
public ISerializationWriterFactory SerializationWriterFactory { get { return sWriterFactory; } }
+ public async Task> SendCollectionAsync(RequestInfo requestInfo, IResponseHandler responseHandler = default) where ModelType : IParsable {
+ var response = await GetHttpResponseMessage(requestInfo);
+ requestInfo.Content?.Dispose();
+ if(responseHandler == null) {
+ var rootNode = await GetRootParseNode(response);
+ var result = rootNode.GetCollectionOfObjectValues();
+ return result;
+ }
+ else
+ return await responseHandler.HandleResponseAsync>(response);
+ }
public async Task SendAsync(RequestInfo requestInfo, IResponseHandler responseHandler = null) where ModelType : IParsable
{
var response = await GetHttpResponseMessage(requestInfo);
diff --git a/http/dotnet/httpclient/src/Microsoft.Kiota.Http.HttpClient.csproj b/http/dotnet/httpclient/src/Microsoft.Kiota.Http.HttpClient.csproj
index f2b8fbbeac..24e945e100 100644
--- a/http/dotnet/httpclient/src/Microsoft.Kiota.Http.HttpClient.csproj
+++ b/http/dotnet/httpclient/src/Microsoft.Kiota.Http.HttpClient.csproj
@@ -4,11 +4,11 @@
net5.0
true
https://github.com/microsoft/kiota
- 1.0.4
+ 1.0.5
-
+
diff --git a/http/java/okhttp/lib/build.gradle b/http/java/okhttp/lib/build.gradle
index ee79fd1316..5456401adc 100644
--- a/http/java/okhttp/lib/build.gradle
+++ b/http/java/okhttp/lib/build.gradle
@@ -36,7 +36,7 @@ dependencies {
// This dependency is used internally, and not exposed to consumers on their own compile classpath.
implementation 'com.google.guava:guava:30.1.1-jre'
api 'com.squareup.okhttp3:okhttp:4.9.1'
- api 'com.microsoft.kiota:kiota-abstractions:1.0.14'
+ api 'com.microsoft.kiota:kiota-abstractions:1.0.15'
}
publishing {
@@ -53,7 +53,7 @@ publishing {
publications {
gpr(MavenPublication) {
artifactId 'kiota-http-okhttp'
- version '1.0.4'
+ version '1.0.5'
from(components.java)
}
}
diff --git a/http/java/okhttp/lib/src/main/java/com/microsoft/kiota/http/HttpCore.java b/http/java/okhttp/lib/src/main/java/com/microsoft/kiota/http/HttpCore.java
index 5289201a13..820c280820 100644
--- a/http/java/okhttp/lib/src/main/java/com/microsoft/kiota/http/HttpCore.java
+++ b/http/java/okhttp/lib/src/main/java/com/microsoft/kiota/http/HttpCore.java
@@ -77,6 +77,33 @@ public void enableBackingStore() {
this.sWriterFactory = Objects.requireNonNull(ApiClientBuilder.enableBackingStoreForSerializationWriterFactory(sWriterFactory));
}
@Nonnull
+ public CompletableFuture> sendCollectionAsync(@Nonnull final RequestInfo requestInfo, @Nonnull final Class targetClass, @Nullable final ResponseHandler responseHandler) {
+ Objects.requireNonNull(requestInfo, "parameter requestInfo cannot be null");
+
+ return addBearerIfNotPresent(requestInfo).thenCompose(x -> {
+ final HttpCoreCallbackFutureWrapper wrapper = new HttpCoreCallbackFutureWrapper();
+ this.client.newCall(getRequestFromRequestInfo(requestInfo)).enqueue(wrapper);
+ return wrapper.future;
+ }).thenCompose(response -> {
+ if(responseHandler == null) {
+ final ResponseBody body = response.body();
+ try {
+ try (final InputStream rawInputStream = body.byteStream()) {
+ final ParseNode rootNode = pNodeFactory.getParseNode(getMediaTypeAndSubType(body.contentType()), rawInputStream);
+ final Iterable result = rootNode.getCollectionOfObjectValues(targetClass);
+ return CompletableFuture.completedStage(result);
+ }
+ } catch(IOException ex) {
+ return CompletableFuture.failedFuture(new RuntimeException("failed to read the response body", ex));
+ } finally {
+ response.close();
+ }
+ } else {
+ return responseHandler.handleResponseAsync(response);
+ }
+ });
+ }
+ @Nonnull
public CompletableFuture sendAsync(@Nonnull final RequestInfo requestInfo, @Nonnull final Class targetClass, @Nullable final ResponseHandler responseHandler) {
Objects.requireNonNull(requestInfo, "parameter requestInfo cannot be null");
diff --git a/http/typescript/fetch/package-lock.json b/http/typescript/fetch/package-lock.json
index 1f17ff9ef4..09988994a4 100644
--- a/http/typescript/fetch/package-lock.json
+++ b/http/typescript/fetch/package-lock.json
@@ -1,6 +1,6 @@
{
"name": "@microsoft/kiota-http-fetch",
- "version": "1.0.4",
+ "version": "1.0.5",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
diff --git a/http/typescript/fetch/package.json b/http/typescript/fetch/package.json
index 5645cf3ab8..6b8fc1724c 100644
--- a/http/typescript/fetch/package.json
+++ b/http/typescript/fetch/package.json
@@ -1,6 +1,6 @@
{
"name": "@microsoft/kiota-http-fetch",
- "version": "1.0.4",
+ "version": "1.0.5",
"description": "Kiota HttpCore implementation with fetch",
"main": "dist/index.js",
"types": "dist/index.d.ts",
@@ -29,7 +29,7 @@
"registry": "https://npm.pkg.github.com"
},
"dependencies": {
- "@microsoft/kiota-abstractions": "^1.0.14",
+ "@microsoft/kiota-abstractions": "^1.0.15",
"cross-fetch": "^3.1.4",
"web-streams-polyfill": "^3.1.0"
},
diff --git a/http/typescript/fetch/src/httpCore.ts b/http/typescript/fetch/src/httpCore.ts
index f51091ee75..44db699ec4 100644
--- a/http/typescript/fetch/src/httpCore.ts
+++ b/http/typescript/fetch/src/httpCore.ts
@@ -36,6 +36,27 @@ export class HttpCore implements IHttpCore {
if(segments.length === 0) return undefined;
else return segments[0];
}
+ public sendCollectionAsync = async (requestInfo: RequestInfo, type: new() => ModelType, responseHandler: ResponseHandler | undefined): Promise => {
+ if(!requestInfo) {
+ throw new Error('requestInfo cannot be null');
+ }
+ await this.addBearerIfNotPresent(requestInfo);
+
+ const request = this.getRequestFromRequestInfo(requestInfo);
+ const response = await this.httpClient.fetch(this.getRequestUrl(requestInfo), request);
+ if(responseHandler) {
+ return await responseHandler.handleResponseAsync(response);
+ } else {
+ const payload = await response.arrayBuffer();
+ const responseContentType = this.getResponseContentType(response);
+ if(!responseContentType)
+ throw new Error("no response content type found for deserialization");
+
+ const rootNode = this.parseNodeFactory.getRootParseNode(responseContentType, payload);
+ const result = rootNode.getCollectionOfObjectValues(type);
+ return result as unknown as ModelType[];
+ }
+ }
public sendAsync = async (requestInfo: RequestInfo, type: new() => ModelType, responseHandler: ResponseHandler | undefined): Promise => {
if(!requestInfo) {
throw new Error('requestInfo cannot be null');
diff --git a/samples b/samples
index ec4096414a..9a92a3518e 160000
--- a/samples
+++ b/samples
@@ -1 +1 @@
-Subproject commit ec4096414a1062064a614372b3df4b7c06ae72e1
+Subproject commit 9a92a3518e450240d647de9527a717f71dd5fe74
diff --git a/src/Kiota.Builder/CodeDOM/CodeTypeBase.cs b/src/Kiota.Builder/CodeDOM/CodeTypeBase.cs
index 31807d071d..ab101d7277 100644
--- a/src/Kiota.Builder/CodeDOM/CodeTypeBase.cs
+++ b/src/Kiota.Builder/CodeDOM/CodeTypeBase.cs
@@ -15,7 +15,8 @@ protected CodeTypeBase(CodeElement parent) : base(parent) {
public bool ActionOf {get;set;} = false;
public bool IsNullable {get;set;} = true;
public CodeTypeCollectionKind CollectionKind {get;set;} = CodeTypeCollectionKind.None;
-
+ public bool IsCollection { get { return CollectionKind != CodeTypeCollectionKind.None; } }
+ public bool IsArray { get { return CollectionKind == CodeTypeCollectionKind.Array; } }
public ChildType BaseClone(CodeTypeBase source) where ChildType : CodeTypeBase
{
ActionOf = source.ActionOf;
diff --git a/src/Kiota.Builder/Refiners/CommonLanguageRefiner.cs b/src/Kiota.Builder/Refiners/CommonLanguageRefiner.cs
index 2f69c2e9bc..77652803ef 100644
--- a/src/Kiota.Builder/Refiners/CommonLanguageRefiner.cs
+++ b/src/Kiota.Builder/Refiners/CommonLanguageRefiner.cs
@@ -366,7 +366,7 @@ protected static void AddPropertiesAndMethodTypesImports(CodeElement current, bo
.Distinct();
var methodsParametersTypes = methods
.SelectMany(x => x.Parameters)
- .Where(x => x.IsOfKind(CodeParameterKind.Custom))
+ .Where(x => x.IsOfKind(CodeParameterKind.Custom, CodeParameterKind.RequestBody))
.Select(x => x.Type)
.Distinct();
var indexerTypes = currentClass
diff --git a/src/Kiota.Builder/Writers/CSharp/CSharpConventionService.cs b/src/Kiota.Builder/Writers/CSharp/CSharpConventionService.cs
index 8bcbc1ca3b..36921b1d75 100644
--- a/src/Kiota.Builder/Writers/CSharp/CSharpConventionService.cs
+++ b/src/Kiota.Builder/Writers/CSharp/CSharpConventionService.cs
@@ -66,6 +66,11 @@ public string TranslateType(string typeName)
default: return typeName?.ToFirstCharacterUpperCase() ?? "object";
}
}
+ public bool IsPrimitiveType(string typeName) {
+ return !string.IsNullOrEmpty(typeName) &&
+ (NullableTypes.Contains(typeName) ||
+ "string".Equals(typeName, StringComparison.OrdinalIgnoreCase));
+ }
public string GetParameterSignature(CodeParameter parameter)
{
var parameterType = GetTypeString(parameter.Type);
diff --git a/src/Kiota.Builder/Writers/CSharp/CodeMethodWriter.cs b/src/Kiota.Builder/Writers/CSharp/CodeMethodWriter.cs
index 01e8166a03..e201e7b767 100644
--- a/src/Kiota.Builder/Writers/CSharp/CodeMethodWriter.cs
+++ b/src/Kiota.Builder/Writers/CSharp/CodeMethodWriter.cs
@@ -151,7 +151,7 @@ private void WriteRequestExecutorBody(CodeMethod codeElement, IEnumerable x?.Name).Where(x => x != null).Aggregate((x,y) => $"{x}, {y}");
writer.WriteLine($"var requestInfo = {generatorMethodName}({parametersList});");
- writer.WriteLine($"{(isVoid ? string.Empty : "return ")}await HttpCore.{GetSendRequestMethodName(isVoid, isStream, returnType)}(requestInfo, responseHandler);");
+ writer.WriteLine($"{(isVoid ? string.Empty : "return ")}await HttpCore.{GetSendRequestMethodName(isVoid, isStream, codeElement.ReturnType.IsCollection, returnType)}(requestInfo, responseHandler);");
}
private const string _requestInfoVarName = "requestInfo";
private void WriteRequestGeneratorBody(CodeMethod codeElement, CodeParameter requestBodyParam, CodeParameter queryStringParam, CodeParameter headersParam, CodeParameter optionsParam, LanguageWriter writer) {
@@ -168,7 +168,7 @@ private void WriteRequestGeneratorBody(CodeMethod codeElement, CodeParameter req
if(requestBodyParam.Type.Name.Equals(conventions.StreamTypeName, StringComparison.OrdinalIgnoreCase))
writer.WriteLine($"{_requestInfoVarName}.SetStreamContent({requestBodyParam.Name});");
else
- writer.WriteLine($"{_requestInfoVarName}.SetContentFromParsable({requestBodyParam.Name}, {conventions.HttpCorePropertyName}, \"{codeElement.ContentType}\");");
+ writer.WriteLine($"{_requestInfoVarName}.SetContentFromParsable({conventions.HttpCorePropertyName}, \"{codeElement.ContentType}\", {requestBodyParam.Name});");
}
if(queryStringParam != null) {
writer.WriteLine($"if ({queryStringParam.Name} != null) {{");
@@ -199,9 +199,10 @@ private void WriteSerializerBody(bool shouldHide, CodeClass parentClass, Languag
if(additionalDataProperty != null)
writer.WriteLine($"writer.WriteAdditionalData({additionalDataProperty.Name});");
}
- private static string GetSendRequestMethodName(bool isVoid, bool isStream, string returnType) {
+ private string GetSendRequestMethodName(bool isVoid, bool isStream, bool isCollection, string returnType) {
if(isVoid) return "SendNoContentAsync";
- else if(isStream) return $"SendPrimitiveAsync<{returnType}>";
+ else if(isStream || conventions.IsPrimitiveType(returnType)) return $"SendPrimitiveAsync<{returnType}>";
+ else if(isCollection) return $"SendCollectionAsync<{returnType.StripArraySuffix()}>";
else return $"SendAsync<{returnType}>";
}
private void WriteMethodDocumentation(CodeMethod code, LanguageWriter writer) {
@@ -220,14 +221,16 @@ private void WriteMethodPrototype(CodeMethod code, LanguageWriter writer, string
var staticModifier = code.IsStatic ? "static " : string.Empty;
var hideModifier = inherits && code.IsSerializationMethod ? "new " : string.Empty;
var genericTypePrefix = isVoid ? string.Empty : "<";
- var genricTypeSuffix = code.IsAsync && !isVoid ? ">": string.Empty;
+ var genericTypeSuffix = code.IsAsync && !isVoid ? ">": string.Empty;
var isConstructor = code.IsOfKind(CodeMethodKind.Constructor, CodeMethodKind.ClientConstructor);
var asyncPrefix = code.IsAsync ? "async Task" + genericTypePrefix : string.Empty;
var voidCorrectedTaskReturnType = code.IsAsync && isVoid ? string.Empty : returnType;
+ if(code.ReturnType.IsArray && code.IsOfKind(CodeMethodKind.RequestExecutor))
+ voidCorrectedTaskReturnType = $"IEnumerable<{voidCorrectedTaskReturnType.StripArraySuffix()}>";
// TODO: Task type should be moved into the refiner
var completeReturnType = isConstructor ?
string.Empty :
- $"{asyncPrefix}{voidCorrectedTaskReturnType}{genricTypeSuffix} ";
+ $"{asyncPrefix}{voidCorrectedTaskReturnType}{genericTypeSuffix} ";
var baseSuffix = string.Empty;
if(isConstructor && inherits)
baseSuffix = " : base()";
diff --git a/src/Kiota.Builder/Writers/Java/CodeMethodWriter.cs b/src/Kiota.Builder/Writers/Java/CodeMethodWriter.cs
index ab607349e7..8e7e32127e 100644
--- a/src/Kiota.Builder/Writers/Java/CodeMethodWriter.cs
+++ b/src/Kiota.Builder/Writers/Java/CodeMethodWriter.cs
@@ -170,7 +170,7 @@ private void WriteRequestExecutorBody(CodeMethod codeElement, CodeParameter requ
writer.WriteLine("try {");
writer.IncreaseIndent();
WriteGeneratorMethodCall(codeElement, requestBodyParam, queryStringParam, headersParam, optionsParam, writer, $"final RequestInfo {requestInfoVarName} = ");
- var sendMethodName = conventions.PrimitiveTypes.Contains(returnType) ? "sendPrimitiveAsync" : "sendAsync";
+ var sendMethodName = GetSendRequestMethodName(codeElement.ReturnType.IsCollection, returnType);
if(codeElement.Parameters.Any(x => x.IsOfKind(CodeParameterKind.ResponseHandler)))
writer.WriteLine($"return this.httpCore.{sendMethodName}(requestInfo, {returnType}.class, responseHandler);");
else
@@ -182,6 +182,11 @@ private void WriteRequestExecutorBody(CodeMethod codeElement, CodeParameter requ
writer.DecreaseIndent();
writer.WriteLine("}");
}
+ private string GetSendRequestMethodName(bool isCollection, string returnType) {
+ if(conventions.PrimitiveTypes.Contains(returnType)) return $"sendPrimitiveAsync";
+ else if(isCollection) return $"sendCollectionAsync";
+ else return $"sendAsync";
+ }
private const string requestInfoVarName = "requestInfo";
private static void WriteGeneratorMethodCall(CodeMethod codeElement, CodeParameter requestBodyParam, CodeParameter queryStringParam, CodeParameter headersParam, CodeParameter optionsParam, LanguageWriter writer, string prefix) {
var generatorMethodName = (codeElement.Parent as CodeClass)
@@ -216,7 +221,7 @@ private void WriteRequestGeneratorBody(CodeMethod codeElement, CodeParameter req
if(requestBodyParam.Type.Name.Equals(conventions.StreamTypeName, StringComparison.OrdinalIgnoreCase))
writer.WriteLine($"{requestInfoVarName}.setStreamContent({requestBodyParam.Name});");
else
- writer.WriteLine($"{requestInfoVarName}.setContentFromParsable({requestBodyParam.Name}, {conventions.HttpCorePropertyName}, \"{codeElement.ContentType}\");");
+ writer.WriteLine($"{requestInfoVarName}.setContentFromParsable({conventions.HttpCorePropertyName}, \"{codeElement.ContentType}\", {requestBodyParam.Name});");
if(queryStringParam != null) {
var httpMethodPrefix = codeElement.HttpMethod.ToString().ToFirstCharacterUpperCase();
writer.WriteLine($"if ({queryStringParam.Name} != null) {{");
@@ -267,7 +272,10 @@ private void WriteMethodPrototype(CodeMethod code, LanguageWriter writer, string
});
var parameters = string.Join(", ", code.Parameters.Select(p=> conventions.GetParameterSignature(p)).ToList());
var throwableDeclarations = code.IsOfKind(CodeMethodKind.RequestGenerator) ? "throws URISyntaxException ": string.Empty;
- var finalReturnType = isConstructor ? string.Empty : $" {returnTypeAsyncPrefix}{returnType}{returnTypeAsyncSuffix}";
+ var collectionCorrectedReturnType = code.ReturnType.IsArray && code.IsOfKind(CodeMethodKind.RequestExecutor) ?
+ $"Iterable<{returnType.StripArraySuffix()}>" :
+ returnType;
+ var finalReturnType = isConstructor ? string.Empty : $" {returnTypeAsyncPrefix}{collectionCorrectedReturnType}{returnTypeAsyncSuffix}";
writer.WriteLine($"{accessModifier}{genericTypeParameterDeclaration}{finalReturnType} {methodName}({parameters}) {throwableDeclarations}{{");
}
private void WriteMethodDocumentation(CodeMethod code, LanguageWriter writer) {
diff --git a/src/Kiota.Builder/Writers/Ruby/CodeMethodWriter.cs b/src/Kiota.Builder/Writers/Ruby/CodeMethodWriter.cs
index eb36854362..1cc80ec919 100644
--- a/src/Kiota.Builder/Writers/Ruby/CodeMethodWriter.cs
+++ b/src/Kiota.Builder/Writers/Ruby/CodeMethodWriter.cs
@@ -149,7 +149,7 @@ private void WriteRequestGeneratorBody(CodeMethod codeElement, CodeParameter req
if(requestBodyParam.Type.Name.Equals(conventions.StreamTypeName, StringComparison.OrdinalIgnoreCase))
writer.WriteLine($"request_info.set_stream_content({requestBodyParam.Name})");
else
- writer.WriteLine($"request_info.set_content_from_parsable({requestBodyParam.Name}, self.{RubyConventionService.SerializerFactoryPropertyName}, \"{codeElement.ContentType}\")");
+ writer.WriteLine($"request_info.set_content_from_parsable(self.{RubyConventionService.SerializerFactoryPropertyName}, \"{codeElement.ContentType}\", {requestBodyParam.Name})");
}
writer.WriteLine("return request_info;");
}
diff --git a/src/Kiota.Builder/Writers/StringExtensions.cs b/src/Kiota.Builder/Writers/StringExtensions.cs
new file mode 100644
index 0000000000..e9e1cc7d2f
--- /dev/null
+++ b/src/Kiota.Builder/Writers/StringExtensions.cs
@@ -0,0 +1,5 @@
+namespace Kiota.Builder.Writers {
+ public static class StringExtensions {
+ public static string StripArraySuffix(this string original) => string.IsNullOrEmpty(original) ? original : original.TrimEnd(']').TrimEnd('[');
+ }
+}
diff --git a/src/Kiota.Builder/Writers/TypeScript/CodeMethodWriter.cs b/src/Kiota.Builder/Writers/TypeScript/CodeMethodWriter.cs
index 775e8886be..8b7d427be7 100644
--- a/src/Kiota.Builder/Writers/TypeScript/CodeMethodWriter.cs
+++ b/src/Kiota.Builder/Writers/TypeScript/CodeMethodWriter.cs
@@ -172,7 +172,7 @@ private void WriteRequestExecutorBody(CodeMethod codeElement, IEnumerable";
}
}
- private static string GetTypeFactory(bool isVoid, bool isStream, string returnType) {
+ private string GetTypeFactory(bool isVoid, bool isStream, string returnType) {
if(isVoid) return string.Empty;
- else if(isStream) return $" \"{returnType}\",";
- else return $" {returnType},";
+ else if(isStream || conventions.IsPrimitiveType(returnType)) return $" \"{returnType}\",";
+ else return $" {returnType.StripArraySuffix()},";
}
- private static string GetSendRequestMethodName(bool isVoid, bool isStream, string returnType) {
+ private string GetSendRequestMethodName(bool isVoid, bool isStream, bool isCollection, string returnType) {
if(isVoid) return "sendNoResponseContentAsync";
- else if(isStream) return $"sendPrimitiveAsync<{returnType}>";
+ else if(isStream || conventions.IsPrimitiveType(returnType)) return $"sendPrimitiveAsync<{returnType}>";
+ else if(isCollection) return $"sendCollectionAsync<{returnType.StripArraySuffix()}>";
else return $"sendAsync<{returnType}>";
}
}
diff --git a/src/Kiota.Builder/Writers/TypeScript/TypeScriptConventionService.cs b/src/Kiota.Builder/Writers/TypeScript/TypeScriptConventionService.cs
index 94b8a76ad2..aedb88a30e 100644
--- a/src/Kiota.Builder/Writers/TypeScript/TypeScriptConventionService.cs
+++ b/src/Kiota.Builder/Writers/TypeScript/TypeScriptConventionService.cs
@@ -90,7 +90,12 @@ public string TranslateType(string typeName)
_ => typeName.ToFirstCharacterUpperCase() ?? "object",
};
}
-
+ public bool IsPrimitiveType(string typeName) {
+ return typeName switch {
+ ("number" or "string" or "byte[]" or "boolean" or "void") => true,
+ _ => false,
+ };
+ }
internal static string RemoveInvalidDescriptionCharacters(string originalDescription) => originalDescription?.Replace("\\", "/");
public void WriteShortDescription(string description, LanguageWriter writer)
{
diff --git a/tests/Kiota.Builder.Tests/Writers/CSharp/CodeMethodWriterTests.cs b/tests/Kiota.Builder.Tests/Writers/CSharp/CodeMethodWriterTests.cs
index c93aea9ea9..a7a2b1d79d 100644
--- a/tests/Kiota.Builder.Tests/Writers/CSharp/CodeMethodWriterTests.cs
+++ b/tests/Kiota.Builder.Tests/Writers/CSharp/CodeMethodWriterTests.cs
@@ -137,6 +137,17 @@ public void WritesRequestExecutorBody() {
AssertExtensions.CurlyBracesAreClosed(result);
}
[Fact]
+ public void WritesRequestExecutorBodyForCollections() {
+ method.MethodKind = CodeMethodKind.RequestExecutor;
+ method.HttpMethod = HttpMethod.Get;
+ method.ReturnType.CollectionKind = CodeTypeBase.CodeTypeCollectionKind.Array;
+ AddRequestBodyParameters();
+ writer.Write(method);
+ var result = tw.ToString();
+ Assert.Contains("SendCollectionAsync", result);
+ AssertExtensions.CurlyBracesAreClosed(result);
+ }
+ [Fact]
public void WritesRequestGeneratorBody() {
method.MethodKind = CodeMethodKind.RequestGenerator;
method.HttpMethod = HttpMethod.Get;
diff --git a/tests/Kiota.Builder.Tests/Writers/Java/CodeMethodWriterTests.cs b/tests/Kiota.Builder.Tests/Writers/Java/CodeMethodWriterTests.cs
index 8e2ebf6d15..cf2e59cfc7 100644
--- a/tests/Kiota.Builder.Tests/Writers/Java/CodeMethodWriterTests.cs
+++ b/tests/Kiota.Builder.Tests/Writers/Java/CodeMethodWriterTests.cs
@@ -148,6 +148,17 @@ public void WritesRequestExecutorBody() {
AssertExtensions.CurlyBracesAreClosed(result);
}
[Fact]
+ public void WritesRequestExecutorBodyForCollections() {
+ method.MethodKind = CodeMethodKind.RequestExecutor;
+ method.HttpMethod = HttpMethod.Get;
+ method.ReturnType.CollectionKind = CodeTypeBase.CodeTypeCollectionKind.Array;
+ AddRequestBodyParameters();
+ writer.Write(method);
+ var result = tw.ToString();
+ Assert.Contains("sendCollectionAsync", result);
+ AssertExtensions.CurlyBracesAreClosed(result);
+ }
+ [Fact]
public void WritesRequestGeneratorBody() {
method.MethodKind = CodeMethodKind.RequestGenerator;
method.HttpMethod = HttpMethod.Get;
diff --git a/tests/Kiota.Builder.Tests/Writers/StringExtensionsTests.cs b/tests/Kiota.Builder.Tests/Writers/StringExtensionsTests.cs
new file mode 100644
index 0000000000..e0c8861a17
--- /dev/null
+++ b/tests/Kiota.Builder.Tests/Writers/StringExtensionsTests.cs
@@ -0,0 +1,17 @@
+using Kiota.Builder.Writers;
+using Xunit;
+
+namespace Kiota.Builder.Tests.Writers {
+ public class StringExtensionsTests {
+ [Fact]
+ public void Defensive() {
+ Assert.Null(StringExtensions.StripArraySuffix(null));
+ Assert.Empty(StringExtensions.StripArraySuffix(string.Empty));
+ }
+ [Fact]
+ public void StripsSuffix() {
+ Assert.Equal("foo", StringExtensions.StripArraySuffix("foo[]"));
+ Assert.Equal("[]foo", StringExtensions.StripArraySuffix("[]foo"));
+ }
+ }
+}
diff --git a/tests/Kiota.Builder.Tests/Writers/TypeScript/CodeMethodWriterTests.cs b/tests/Kiota.Builder.Tests/Writers/TypeScript/CodeMethodWriterTests.cs
index f127cf3be8..9329190d7c 100644
--- a/tests/Kiota.Builder.Tests/Writers/TypeScript/CodeMethodWriterTests.cs
+++ b/tests/Kiota.Builder.Tests/Writers/TypeScript/CodeMethodWriterTests.cs
@@ -136,6 +136,17 @@ public void WritesRequestExecutorBody() {
AssertExtensions.CurlyBracesAreClosed(result);
}
[Fact]
+ public void WritesRequestExecutorBodyForCollections() {
+ method.MethodKind = CodeMethodKind.RequestExecutor;
+ method.HttpMethod = HttpMethod.Get;
+ method.ReturnType.CollectionKind = CodeTypeBase.CodeTypeCollectionKind.Array;
+ AddRequestBodyParameters();
+ writer.Write(method);
+ var result = tw.ToString();
+ Assert.Contains("sendCollectionAsync", result);
+ AssertExtensions.CurlyBracesAreClosed(result);
+ }
+ [Fact]
public void WritesRequestGeneratorBody() {
method.MethodKind = CodeMethodKind.RequestGenerator;
method.HttpMethod = HttpMethod.Get;