diff --git a/dotnet/src/Functions/Functions.OpenApi/RestApiOperationRunner.cs b/dotnet/src/Functions/Functions.OpenApi/RestApiOperationRunner.cs index 9c1c2bcb1177..3c1038c12dd8 100644 --- a/dotnet/src/Functions/Functions.OpenApi/RestApiOperationRunner.cs +++ b/dotnet/src/Functions/Functions.OpenApi/RestApiOperationRunner.cs @@ -350,7 +350,10 @@ private async Task ReadContentAndCreateOperationRespon mediaType = mediaTypeFallback; } - if (!this._payloadFactoryByMediaType.TryGetValue(mediaType!, out var payloadFactory)) + // Remove media type parameters, such as x-api-version, from the "text/plain; x-api-version=2.0" media type string. + mediaType = mediaType!.Split(';').First(); + + if (!this._payloadFactoryByMediaType.TryGetValue(mediaType, out var payloadFactory)) { throw new KernelException($"The media type {mediaType} of the {operation.Id} operation is not supported by {nameof(RestApiOperationRunner)}."); } diff --git a/dotnet/src/Functions/Functions.UnitTests/OpenApi/OpenApiKernelPluginFactoryTests.cs b/dotnet/src/Functions/Functions.UnitTests/OpenApi/OpenApiKernelPluginFactoryTests.cs index 2242f5032610..eb223323b86c 100644 --- a/dotnet/src/Functions/Functions.UnitTests/OpenApi/OpenApiKernelPluginFactoryTests.cs +++ b/dotnet/src/Functions/Functions.UnitTests/OpenApi/OpenApiKernelPluginFactoryTests.cs @@ -8,6 +8,7 @@ using System.Net.Http; using System.Net.Mime; using System.Text; +using System.Text.Json.Nodes; using System.Threading.Tasks; using Microsoft.SemanticKernel; using Microsoft.SemanticKernel.Plugins.OpenApi; @@ -517,6 +518,41 @@ public void ItCreatesPluginFromOpenApiSpecificationModel() Assert.Same(operations[0], function.Metadata.AdditionalProperties["operation"]); } + [Fact] + public async Task ItShouldWorkWithPayloadMediaTypesDeclaredWithParametersAsync() + { + // Arrange + using var messageHandlerStub = new HttpMessageHandlerStub(); + using var httpClient = new HttpClient(messageHandlerStub, false); + + this._executionParameters.EnableDynamicPayload = true; + this._executionParameters.HttpClient = httpClient; + + var arguments = new KernelArguments + { + ["scenario"] = "fake-scenario", + }; + + var kernel = new Kernel(); + + var openApiDocument = ResourcePluginsProvider.LoadFromResource("documentV3_0.json"); + + var plugin = await OpenApiKernelPluginFactory.CreateFromOpenApiAsync("fakePlugin", openApiDocument, this._executionParameters); + + // Act + // The media type string for the joke operation is declared with the x-api-version parameter: "application/json; x-api-version=2.0." + var result = await kernel.InvokeAsync(plugin["Joke"], arguments); + + // Assert + var messageContent = messageHandlerStub.RequestContent; + Assert.NotNull(messageContent); + + var deserializedPayload = await JsonNode.ParseAsync(new MemoryStream(messageContent)); + Assert.NotNull(deserializedPayload); + + Assert.Equal("fake-scenario", deserializedPayload["scenario"]!.GetValue()); + } + /// /// Generate theory data for ItAddSecurityMetadataToOperationAsync ///