diff --git a/CHANGELOG.md b/CHANGELOG.md
index 853f45f7e4..5d3939d0db 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -13,6 +13,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Changed
+- Fixed cyclic depencies in generated Go code. [#2834](https://github.com/microsoft/kiota/issues/2834)
+
## [1.19.0] - 2024-10-03
### Added
@@ -38,7 +40,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Removed registration of default serialization and deserialization classes in client constructor. [#5478](https://github.com/microsoft/kiota/pull/5478)
- Fixed incorrect type name generation in aliased scenario in TS due to broad searching of types in root namespaces. [#5404](https://github.com/microsoft/kiota/issues/5404)
- Fixed incorrect type mapping in request builders with subsequent paths with the same name. [#5462](https://github.com/microsoft/kiota/issues/5462)
-- Fixed cyclic depencies in generated Go code. [#2834](https://github.com/microsoft/kiota/issues/2834)
+- Fixed multipart generation to default Content-Types are defined for multipart [#5504](https://github.com/microsoft/kiota/issues/5504)
## [1.18.0] - 2024-09-05
diff --git a/it/java/pom.xml b/it/java/pom.xml
index b0a9bf1f90..c4c04176ed 100644
--- a/it/java/pom.xml
+++ b/it/java/pom.xml
@@ -15,7 +15,7 @@
UTF-8
UTF-8
- 1.5.0
+ 1.5.1
diff --git a/it/python/requirements-dev.txt b/it/python/requirements-dev.txt
index 95548b7ce0..cb9821a583 100644
--- a/it/python/requirements-dev.txt
+++ b/it/python/requirements-dev.txt
@@ -104,7 +104,7 @@ microsoft-kiota-authentication-azure==1.1.0
microsoft-kiota-http==1.3.3
-microsoft-kiota-serialization-json==1.3.2
+microsoft-kiota-serialization-json==1.3.3
microsoft-kiota-serialization-text==1.0.0
diff --git a/it/typescript/package-lock.json b/it/typescript/package-lock.json
index f9dd728763..a3d41e8b5d 100644
--- a/it/typescript/package-lock.json
+++ b/it/typescript/package-lock.json
@@ -10,13 +10,13 @@
"license": "MIT",
"dependencies": {
"@azure/identity": "^4.4.1",
- "@microsoft/kiota-abstractions": "^1.0.0-preview.66",
- "@microsoft/kiota-authentication-azure": "^1.0.0-preview.61",
- "@microsoft/kiota-http-fetchlibrary": "^1.0.0-preview.65",
- "@microsoft/kiota-serialization-form": "^1.0.0-preview.54",
- "@microsoft/kiota-serialization-json": "^1.0.0-preview.66",
- "@microsoft/kiota-serialization-multipart": "^1.0.0-preview.44",
- "@microsoft/kiota-serialization-text": "^1.0.0-preview.63",
+ "@microsoft/kiota-abstractions": "^1.0.0-preview.68",
+ "@microsoft/kiota-authentication-azure": "^1.0.0-preview.63",
+ "@microsoft/kiota-http-fetchlibrary": "^1.0.0-preview.67",
+ "@microsoft/kiota-serialization-form": "^1.0.0-preview.56",
+ "@microsoft/kiota-serialization-json": "^1.0.0-preview.68",
+ "@microsoft/kiota-serialization-multipart": "^1.0.0-preview.46",
+ "@microsoft/kiota-serialization-text": "^1.0.0-preview.65",
"express": "^5.0.0",
"node-fetch": "^2.7.0"
},
@@ -772,9 +772,9 @@
}
},
"node_modules/@microsoft/kiota-abstractions": {
- "version": "1.0.0-preview.66",
- "resolved": "https://registry.npmjs.org/@microsoft/kiota-abstractions/-/kiota-abstractions-1.0.0-preview.66.tgz",
- "integrity": "sha512-mP7P+aHVLhT5A0A1nhpPQvghwNtMO9+LOV6RKYHzhzmKAvycM2rOMCpxsivHn+vtOArTiAqdfyePCpUhzziRjg==",
+ "version": "1.0.0-preview.68",
+ "resolved": "https://registry.npmjs.org/@microsoft/kiota-abstractions/-/kiota-abstractions-1.0.0-preview.68.tgz",
+ "integrity": "sha512-RDKMEqEUDr1GUhgN52Q31+qCWRU5VKcr+TeWSCTbQs3fMFIQIP5l68+OfHEwsa75f7hBuOZ0RLxEuS3hpJgmzQ==",
"dependencies": {
"@opentelemetry/api": "^1.7.0",
"@std-uritemplate/std-uritemplate": "^1.0.1",
@@ -797,9 +797,9 @@
}
},
"node_modules/@microsoft/kiota-authentication-azure": {
- "version": "1.0.0-preview.61",
- "resolved": "https://registry.npmjs.org/@microsoft/kiota-authentication-azure/-/kiota-authentication-azure-1.0.0-preview.61.tgz",
- "integrity": "sha512-Vsx6hmkMLOdrw0IHYpkTohymUjdcypTjurkEh9BZkZz9OceKgx+3pt8DmtAxc7zvCa+H23P68KBGRVZaT32YGw==",
+ "version": "1.0.0-preview.63",
+ "resolved": "https://registry.npmjs.org/@microsoft/kiota-authentication-azure/-/kiota-authentication-azure-1.0.0-preview.63.tgz",
+ "integrity": "sha512-CzBtENeYnb6wu9XKcTAFTYxkm89FlS5uo7lGZpG3ddEz1Ac8stvZgSatdMeB9zzAhbf7SvBlB0Je94NGlrrGVA==",
"dependencies": {
"@azure/core-auth": "^1.5.0",
"@microsoft/kiota-abstractions": "*",
@@ -808,9 +808,9 @@
}
},
"node_modules/@microsoft/kiota-http-fetchlibrary": {
- "version": "1.0.0-preview.65",
- "resolved": "https://registry.npmjs.org/@microsoft/kiota-http-fetchlibrary/-/kiota-http-fetchlibrary-1.0.0-preview.65.tgz",
- "integrity": "sha512-b6HsVhojYjABhkspvdWK56I2FZy+6pq8nmmBXDUuSbI22/Ep6T8xExjw1r0lzEEZVw08yihexWGZIofy1dvhcQ==",
+ "version": "1.0.0-preview.67",
+ "resolved": "https://registry.npmjs.org/@microsoft/kiota-http-fetchlibrary/-/kiota-http-fetchlibrary-1.0.0-preview.67.tgz",
+ "integrity": "sha512-nEddpr+iLw8Eglmd+v7YMFLRZin2paSB+/BiQK5JbDIFnN9FYwtM6gdRnqacGK0TxNm0m0KHK0AqK9kwxZwDEw==",
"dependencies": {
"@microsoft/kiota-abstractions": "*",
"@opentelemetry/api": "^1.7.0",
@@ -819,9 +819,9 @@
}
},
"node_modules/@microsoft/kiota-serialization-form": {
- "version": "1.0.0-preview.54",
- "resolved": "https://registry.npmjs.org/@microsoft/kiota-serialization-form/-/kiota-serialization-form-1.0.0-preview.54.tgz",
- "integrity": "sha512-Yd8GOae8zq3AK2koMK3RjLDzMfVRf+bx2je/MMZlUOrfKXF1rnaCWcXiyJJRlreawDI9WSeuD0mY/+pUTxSOsw==",
+ "version": "1.0.0-preview.56",
+ "resolved": "https://registry.npmjs.org/@microsoft/kiota-serialization-form/-/kiota-serialization-form-1.0.0-preview.56.tgz",
+ "integrity": "sha512-n4wPs8LDpgo4w2zC40RSmNIvuibcRCY/PfjR9gogQA7gQmPKDYnyk5JvfOn0yr2f0V8PKX76yQicXO1SHkG7BA==",
"dependencies": {
"@microsoft/kiota-abstractions": "*",
"guid-typescript": "^1.0.9",
@@ -829,9 +829,9 @@
}
},
"node_modules/@microsoft/kiota-serialization-json": {
- "version": "1.0.0-preview.66",
- "resolved": "https://registry.npmjs.org/@microsoft/kiota-serialization-json/-/kiota-serialization-json-1.0.0-preview.66.tgz",
- "integrity": "sha512-H9ja9wu+e68jlzqQ548Dcu5U18dh3HAEnPcrypG+YDzgpXqXJwujZa7fOzKbR3mNRD3coUT7H9PMQfaNGZus+g==",
+ "version": "1.0.0-preview.68",
+ "resolved": "https://registry.npmjs.org/@microsoft/kiota-serialization-json/-/kiota-serialization-json-1.0.0-preview.68.tgz",
+ "integrity": "sha512-5mOjnrmEGMWyPrYLW6eEOXegOip8AiqlH3/zD+HGZhdNM/RrVO/xJLsSk5RaVxXK8ViJk6BG58Esx2grUF3bxQ==",
"dependencies": {
"@microsoft/kiota-abstractions": "*",
"guid-typescript": "^1.0.9",
@@ -839,9 +839,9 @@
}
},
"node_modules/@microsoft/kiota-serialization-multipart": {
- "version": "1.0.0-preview.44",
- "resolved": "https://registry.npmjs.org/@microsoft/kiota-serialization-multipart/-/kiota-serialization-multipart-1.0.0-preview.44.tgz",
- "integrity": "sha512-+g/1euy/iZXxQPlmN6zX4rkas47BShFI7bK47jLIdt6VFtZU6deWjiplnTpfR2dGg3ipQAD9RBdU4mHVoqx1Ow==",
+ "version": "1.0.0-preview.46",
+ "resolved": "https://registry.npmjs.org/@microsoft/kiota-serialization-multipart/-/kiota-serialization-multipart-1.0.0-preview.46.tgz",
+ "integrity": "sha512-ZFq6wiB5jBfilyuZjmm/xHFUQJP0Q1OG/qW9BaHWlOoh546JkVHqpchHJXKy9fhEhFZeHsIxz6ZqaF/deruxDw==",
"dependencies": {
"@microsoft/kiota-abstractions": "*",
"guid-typescript": "^1.0.9",
@@ -849,9 +849,9 @@
}
},
"node_modules/@microsoft/kiota-serialization-text": {
- "version": "1.0.0-preview.63",
- "resolved": "https://registry.npmjs.org/@microsoft/kiota-serialization-text/-/kiota-serialization-text-1.0.0-preview.63.tgz",
- "integrity": "sha512-tfbsG7EYukBLECdcd2UVJglOVhjjjmqUtxosZ/B/oiYAKCyooPwdOLDM5WmM4Vcgm6rMaCOaEluPKQMjfhD3xg==",
+ "version": "1.0.0-preview.65",
+ "resolved": "https://registry.npmjs.org/@microsoft/kiota-serialization-text/-/kiota-serialization-text-1.0.0-preview.65.tgz",
+ "integrity": "sha512-N3msWVFk5t2WrVOgmzUwo9bK/HEtSOskw+p0Fi1OAlhz1HSAJEbSHKfedIt62j+7Xbd1PEpbzOQZgJfFc6+hug==",
"dependencies": {
"@microsoft/kiota-abstractions": "*",
"guid-typescript": "^1.0.9",
diff --git a/it/typescript/package.json b/it/typescript/package.json
index d27d9f41b8..c9e3111a0b 100644
--- a/it/typescript/package.json
+++ b/it/typescript/package.json
@@ -32,13 +32,13 @@
},
"dependencies": {
"@azure/identity": "^4.4.1",
- "@microsoft/kiota-abstractions": "^1.0.0-preview.66",
- "@microsoft/kiota-authentication-azure": "^1.0.0-preview.61",
- "@microsoft/kiota-http-fetchlibrary": "^1.0.0-preview.65",
- "@microsoft/kiota-serialization-form": "^1.0.0-preview.54",
- "@microsoft/kiota-serialization-json": "^1.0.0-preview.66",
- "@microsoft/kiota-serialization-multipart": "^1.0.0-preview.44",
- "@microsoft/kiota-serialization-text": "^1.0.0-preview.63",
+ "@microsoft/kiota-abstractions": "^1.0.0-preview.68",
+ "@microsoft/kiota-authentication-azure": "^1.0.0-preview.63",
+ "@microsoft/kiota-http-fetchlibrary": "^1.0.0-preview.67",
+ "@microsoft/kiota-serialization-form": "^1.0.0-preview.56",
+ "@microsoft/kiota-serialization-json": "^1.0.0-preview.68",
+ "@microsoft/kiota-serialization-multipart": "^1.0.0-preview.46",
+ "@microsoft/kiota-serialization-text": "^1.0.0-preview.65",
"express": "^5.0.0",
"node-fetch": "^2.7.0"
}
diff --git a/src/Kiota.Builder/KiotaBuilder.cs b/src/Kiota.Builder/KiotaBuilder.cs
index d575562412..8a1a4e69f2 100644
--- a/src/Kiota.Builder/KiotaBuilder.cs
+++ b/src/Kiota.Builder/KiotaBuilder.cs
@@ -1490,6 +1490,23 @@ private static void AddRequestConfigurationProperties(CodeClass? parameterClass,
}
private readonly ConcurrentDictionary multipartPropertiesModels = new();
+
+ private static bool IsSupportedMultipartDefault(OpenApiSchema openApiSchema,
+ StructuredMimeTypesCollection structuredMimeTypes)
+ {
+ // https://spec.openapis.org/oas/v3.0.3.html#special-considerations-for-multipart-content
+ if (openApiSchema.IsObjectType() && structuredMimeTypes.Contains("application/json"))
+ return true;
+
+ if (GetPrimitiveType(openApiSchema) is { IsExternal: true } primitiveType && // it s a primitive
+ (primitiveType.Name.Equals("binary", StringComparison.OrdinalIgnoreCase)
+ || primitiveType.Name.Equals("base64", StringComparison.OrdinalIgnoreCase) // streams are handled irrespective of configs
+ || structuredMimeTypes.Contains("text/plain"))) // other primitives need text/plain
+ return true;
+
+ return false;
+ }
+
private void AddRequestBuilderMethodParameters(OpenApiUrlTreeNode currentNode, OperationType operationType, OpenApiOperation operation, CodeClass requestConfigClass, CodeMethod method)
{
if (operation.GetRequestSchema(config.StructuredMimeTypes) is OpenApiSchema requestBodySchema)
@@ -1513,6 +1530,18 @@ private void AddRequestBuilderMethodParameters(OpenApiUrlTreeNode currentNode, O
multipartPropertiesModels.TryAdd(propertyType.TypeDefinition, true);
}
}
+ else if (requestBodySchema.Properties.Values.Any(schema => IsSupportedMultipartDefault(schema, config.StructuredMimeTypes))
+ && operation.RequestBody.Content.Count == 1)// it's the only content type.
+ {
+ requestBodyType = new CodeType { Name = "MultipartBody", IsExternal = true, };
+ foreach (var property in requestBodySchema.Properties.Values.Where(schema => IsSupportedMultipartDefault(schema, config.StructuredMimeTypes)))
+ {
+ if (CreateModelDeclarations(currentNode, property,
+ operation, method, $"{operationType}RequestBody",
+ isRequestBody: true) is CodeType { TypeDefinition: not null } propertyType)
+ multipartPropertiesModels.TryAdd(propertyType.TypeDefinition, true);
+ }
+ }
else
{
requestBodyType = CreateModelDeclarations(currentNode, requestBodySchema, operation, method,
diff --git a/tests/Kiota.Builder.Tests/KiotaBuilderTests.cs b/tests/Kiota.Builder.Tests/KiotaBuilderTests.cs
index 6b17ad738e..7d7382168b 100644
--- a/tests/Kiota.Builder.Tests/KiotaBuilderTests.cs
+++ b/tests/Kiota.Builder.Tests/KiotaBuilderTests.cs
@@ -7706,7 +7706,66 @@ public async Task SupportsMultiPartFormAsRequestBodyWithoutEncodingWithDefaultMi
Assert.NotNull(postMethod);
var bodyParameter = postMethod.Parameters.FirstOrDefault(static x => x.IsOfKind(CodeParameterKind.RequestBody));
Assert.NotNull(bodyParameter);
- Assert.Equal("directoryObjectPostRequestBody", bodyParameter.Type.Name, StringComparer.OrdinalIgnoreCase);
+ Assert.Equal("MultipartBody", bodyParameter.Type.Name, StringComparer.OrdinalIgnoreCase);
+ var addressClass = codeModel.FindChildByName("Address");
+ Assert.NotNull(addressClass);
+ }
+ [Fact]
+ public async Task SupportsMultiPartFormAsRequestBodyWithoutEncodingWithDefaultMimeTypesAsyncWithNonDefaultMimeTypesAsync()
+ {
+ var tempFilePath = Path.Combine(Path.GetTempPath(), Path.GetTempFileName());
+ await using var fs = await GetDocumentStreamAsync(@"openapi: 3.0.1
+info:
+ title: Example
+ description: Example
+ version: 1.0.1
+servers:
+ - url: https://example.org
+paths:
+ /directoryObject:
+ post:
+ requestBody:
+ content:
+ multipart/form-data:
+ schema:
+ type: object
+ properties:
+ id:
+ type: string
+ format: uuid
+ address:
+ $ref: '#/components/schemas/address'
+ profileImage:
+ type: string
+ format: binary
+ responses:
+ '204':
+ content:
+ application/json:
+ schema:
+ type: string
+components:
+ schemas:
+ address:
+ type: object
+ properties:
+ street:
+ type: string
+ city:
+ type: string");
+ var mockLogger = new Mock>();
+ var builder = new KiotaBuilder(mockLogger.Object, new GenerationConfiguration { ClientClassName = "Graph", OpenAPIFilePath = tempFilePath, IncludeAdditionalData = false, StructuredMimeTypes = new StructuredMimeTypesCollection { "multipart/form-data;q=1" } }, _httpClient);
+ var document = await builder.CreateOpenApiDocumentAsync(fs);
+ var node = builder.CreateUriSpace(document);
+ var codeModel = builder.CreateSourceModel(node);
+ Assert.NotNull(codeModel);
+ var rbClass = codeModel.FindChildByName("directoryObjectRequestBuilder");
+ Assert.NotNull(rbClass);
+ var postMethod = rbClass.FindChildByName("Post", false);
+ Assert.NotNull(postMethod);
+ var bodyParameter = postMethod.Parameters.FirstOrDefault(static x => x.IsOfKind(CodeParameterKind.RequestBody));
+ Assert.NotNull(bodyParameter);
+ Assert.Equal("DirectoryObjectPostRequestBody", bodyParameter.Type.Name, StringComparer.OrdinalIgnoreCase); //generate the model type as we do not have the serializer for the schema registered.
var addressClass = codeModel.FindChildByName("Address");
Assert.NotNull(addressClass);
}
diff --git a/vscode/microsoft-kiota/package-lock.json b/vscode/microsoft-kiota/package-lock.json
index 6332e8af7c..0a887eb428 100644
--- a/vscode/microsoft-kiota/package-lock.json
+++ b/vscode/microsoft-kiota/package-lock.json
@@ -21,7 +21,7 @@
"@types/adm-zip": "^0.5.5",
"@types/mocha": "^10.0.8",
"@types/node": "22.x",
- "@types/vscode": "^1.93.0",
+ "@types/vscode": "^1.94.0",
"@typescript-eslint/eslint-plugin": "^8.8.0",
"@typescript-eslint/parser": "^8.8.0",
"@vscode/test-electron": "^2.4.1",
@@ -540,9 +540,9 @@
}
},
"node_modules/@types/vscode": {
- "version": "1.93.0",
- "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.93.0.tgz",
- "integrity": "sha512-kUK6jAHSR5zY8ps42xuW89NLcBpw1kOabah7yv38J8MyiYuOHxLQBi0e7zeXbQgVefDy/mZZetqEFC+Fl5eIEQ==",
+ "version": "1.94.0",
+ "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.94.0.tgz",
+ "integrity": "sha512-UyQOIUT0pb14XSqJskYnRwD2aG0QrPVefIfrW1djR+/J4KeFQ0i1+hjZoaAmeNf3Z2jleK+R2hv+EboG/m8ruw==",
"dev": true
},
"node_modules/@typescript-eslint/eslint-plugin": {
diff --git a/vscode/microsoft-kiota/package.json b/vscode/microsoft-kiota/package.json
index 9c6283c730..abf57d64dc 100644
--- a/vscode/microsoft-kiota/package.json
+++ b/vscode/microsoft-kiota/package.json
@@ -8,7 +8,7 @@
"telemetryInstrumentationKey": "4c6357e0-daf9-42b5-bdfb-67878f8957b5",
"icon": "images/logo.png",
"engines": {
- "vscode": "^1.93.0"
+ "vscode": "^1.94.0"
},
"license": "MIT",
"categories": [
@@ -470,7 +470,7 @@
"@types/adm-zip": "^0.5.5",
"@types/mocha": "^10.0.8",
"@types/node": "22.x",
- "@types/vscode": "^1.93.0",
+ "@types/vscode": "^1.94.0",
"@typescript-eslint/eslint-plugin": "^8.8.0",
"@typescript-eslint/parser": "^8.8.0",
"@vscode/test-electron": "^2.4.1",