-
Notifications
You must be signed in to change notification settings - Fork 289
Open
Labels
CsharpPull requests that update .net codePull requests that update .net codestatus:waiting-for-triageAn issue that is yet to be reviewed or assignedAn issue that is yet to be reviewed or assignedtype:bugA broken experienceA broken experience
Description
What are you generating using Kiota, clients or plugins?
API Client/SDK
In what context or format are you using Kiota?
Mac executable
Client library/SDK language
Csharp
Describe the bug
I want to generate a TypeSpec client in which the output model is described using Record<T>. However, when generating the class, the data model description disappears — only an empty class remains.
Expected behavior
I expect the generated client description to correctly reflect the service, including the defined models.
How to reproduce
- Create new tsp project with specified typespec file
- Run
tsp compile . - Run kiota:
kiota generate \
--language CSharp \
--openapi tsp-output/@typespec/openapi3/openapi.MyApp.yaml \
--output ./kiota-output \
--namespace-name MyService \
--class-name MyServiceClient \
--exclude-backward-compatible \
--clean-output
Typespec with Record
import "@typespec/http";
import "@typespec/openapi3";
using TypeSpec.Http;
@service(#{ title: "MyApp" })
namespace MyApp {
@tag("TestEndpointApi")
interface TestEndpointApi {
@route("/test-endpoint/")
@get
get(): Record<TestModel>;
}
model TestModel {
name: string;
phone?: string;
}
}Generated C# for Record
For models only GetResponse generated without reference to expected name and phone properties.
// <auto-generated/>
#pragma warning disable CS0618
using Microsoft.Kiota.Abstractions.Extensions;
using Microsoft.Kiota.Abstractions.Serialization;
using System.Collections.Generic;
using System.IO;
using System;
namespace MyService.TestEndpoint
{
[global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")]
#pragma warning disable CS1591
public partial class GetResponse : IAdditionalDataHolder, IParsable
#pragma warning restore CS1591
{
/// <summary>Stores additional data not described in the OpenAPI description found when deserializing. Can be used for serialization as well.</summary>
public IDictionary<string, object> AdditionalData { get; set; }
/// <summary>
/// Instantiates a new <see cref="global::MyService.TestEndpoint.GetResponse"/> and sets the default values.
/// </summary>
public GetResponse()
{
AdditionalData = new Dictionary<string, object>();
}
/// <summary>
/// Creates a new instance of the appropriate class based on discriminator value
/// </summary>
/// <returns>A <see cref="global::MyService.TestEndpoint.GetResponse"/></returns>
/// <param name="parseNode">The parse node to use to read the discriminator value and create the object</param>
public static global::MyService.TestEndpoint.GetResponse CreateFromDiscriminatorValue(IParseNode parseNode)
{
_ = parseNode ?? throw new ArgumentNullException(nameof(parseNode));
return new global::MyService.TestEndpoint.GetResponse();
}
/// <summary>
/// The deserialization information for the current model
/// </summary>
/// <returns>A IDictionary<string, Action<IParseNode>></returns>
public virtual IDictionary<string, Action<IParseNode>> GetFieldDeserializers()
{
return new Dictionary<string, Action<IParseNode>>
{
};
}
/// <summary>
/// Serializes information the current object
/// </summary>
/// <param name="writer">Serialization writer to use to serialize this model</param>
public virtual void Serialize(ISerializationWriter writer)
{
_ = writer ?? throw new ArgumentNullException(nameof(writer));
writer.WriteAdditionalData(AdditionalData);
}
}
}
#pragma warning restore CS0618Typespec without Record
import "@typespec/http";
import "@typespec/openapi3";
using TypeSpec.Http;
@service(#{ title: "MyApp" })
namespace MyApp {
@tag("TestEndpointApi")
interface TestEndpointApi {
@route("/test-endpoint/")
@get
get(): TestModel; // <-- only change is here
}
model TestModel {
name: string;
phone?: string;
}
}
Generated C# without Record
Instead of GetResponse - TestModel.cs is generated, which have expected properties.
// <auto-generated/>
#pragma warning disable CS0618
using Microsoft.Kiota.Abstractions.Extensions;
using Microsoft.Kiota.Abstractions.Serialization;
using System.Collections.Generic;
using System.IO;
using System;
namespace MyService.Models
{
[global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")]
#pragma warning disable CS1591
public partial class TestModel : IAdditionalDataHolder, IParsable
#pragma warning restore CS1591
{
/// <summary>Stores additional data not described in the OpenAPI description found when deserializing. Can be used for serialization as well.</summary>
public IDictionary<string, object> AdditionalData { get; set; }
/// <summary>The name property</summary>
#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP3_1_OR_GREATER
#nullable enable
public string? Name { get; set; }
#nullable restore
#else
public string Name { get; set; }
#endif
/// <summary>The phone property</summary>
#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP3_1_OR_GREATER
#nullable enable
public string? Phone { get; set; }
#nullable restore
#else
public string Phone { get; set; }
#endif
/// <summary>
/// Instantiates a new <see cref="global::MyService.Models.TestModel"/> and sets the default values.
/// </summary>
public TestModel()
{
AdditionalData = new Dictionary<string, object>();
}
/// <summary>
/// Creates a new instance of the appropriate class based on discriminator value
/// </summary>
/// <returns>A <see cref="global::MyService.Models.TestModel"/></returns>
/// <param name="parseNode">The parse node to use to read the discriminator value and create the object</param>
public static global::MyService.Models.TestModel CreateFromDiscriminatorValue(IParseNode parseNode)
{
_ = parseNode ?? throw new ArgumentNullException(nameof(parseNode));
return new global::MyService.Models.TestModel();
}
/// <summary>
/// The deserialization information for the current model
/// </summary>
/// <returns>A IDictionary<string, Action<IParseNode>></returns>
public virtual IDictionary<string, Action<IParseNode>> GetFieldDeserializers()
{
return new Dictionary<string, Action<IParseNode>>
{
{ "name", n => { Name = n.GetStringValue(); } },
{ "phone", n => { Phone = n.GetStringValue(); } },
};
}
/// <summary>
/// Serializes information the current object
/// </summary>
/// <param name="writer">Serialization writer to use to serialize this model</param>
public virtual void Serialize(ISerializationWriter writer)
{
_ = writer ?? throw new ArgumentNullException(nameof(writer));
writer.WriteStringValue("name", Name);
writer.WriteStringValue("phone", Phone);
writer.WriteAdditionalData(AdditionalData);
}
}
}
#pragma warning restore CS0618Open API description file
openapi.MyApp-with-Record.yaml
openapi.MyApp-without-Record.yaml
Kiota Version
1.28.0+57130b1b1db3bc5c060498682f41e20c8ae089f2
Latest Kiota version known to work for scenario above?(Not required)
No response
Known Workarounds
No response
Configuration
- macOS Sequoia 15.7.1
- ARM
Debug output
Click to expand log
``` kiota generate \ --language CSharp \ --openapi tsp-output/@typespec/openapi3/openapi.MyApp.yaml \ --output ./kiota-output \ --namespace-name MyService \ --class-name MyServiceClient \ --exclude-backward-compatible \ --clean-output \ --log-level Debug info: Kiota.Builder.KiotaBuilder[0] Cleaning output directory .../get-all-single-model-kiota-case/./kiota-output dbug: Kiota.Builder.KiotaBuilder[0] kiota version 1.28.0 info: Kiota.Builder.KiotaBuilder[0] loaded description from local source dbug: Kiota.Builder.KiotaBuilder[0] step 1 - reading the stream - took 00:00:00.0059196 warn: Kiota.Builder.KiotaBuilder[0] OpenAPI warning: #/ - A servers entry (v3) or host + basePath + schemes properties (v2) was not present in the OpenAPI description. The root URL will need to be set manually with the request adapter. dbug: Kiota.Builder.KiotaBuilder[0] step 2 - parsing the document - took 00:00:00.0581297 dbug: Kiota.Builder.KiotaBuilder[0] step 3 - updating generation configuration from kiota extension - took 00:00:00.0000616 dbug: Kiota.Builder.KiotaBuilder[0] step 4 - filtering API paths with patterns - took 00:00:00.0029906 warn: Kiota.Builder.KiotaBuilder[0] No server url found in the OpenAPI document. The base url will need to be set when using the client. dbug: Kiota.Builder.KiotaBuilder[0] step 5 - checking whether the output should be updated - took 00:00:00.0097135 dbug: Kiota.Builder.KiotaBuilder[0] step 6 - create uri space - took 00:00:00.0018198 dbug: Kiota.Builder.KiotaBuilder[0] InitializeInheritanceIndex 00:00:00.0018850 dbug: Kiota.Builder.KiotaBuilder[0] CreateRequestBuilderClass 00:00:00 dbug: Kiota.Builder.KiotaBuilder[0] MapTypeDefinitions 00:00:00.0017514 dbug: Kiota.Builder.KiotaBuilder[0] TrimInheritedModels 00:00:00 dbug: Kiota.Builder.KiotaBuilder[0] CleanUpInternalState 00:00:00 dbug: Kiota.Builder.KiotaBuilder[0] step 7 - create source model - took 00:00:00.0301582 dbug: Kiota.Builder.KiotaBuilder[0] 12ms: Language refinement applied dbug: Kiota.Builder.KiotaBuilder[0] step 8 - refine by language - took 00:00:00.0131009 dbug: Kiota.Builder.KiotaBuilder[0] step 9 - writing files - took 00:00:00.0194416 info: Kiota.Builder.KiotaBuilder[0] loaded description from local source dbug: Kiota.Builder.KiotaBuilder[0] step 10 - writing lock file - took 00:00:00.0114447 Generation completed successfully dbug: Kiota.Builder.KiotaBuilder[0] Api manifest path: .../get-all-single-model-kiota-case/apimanifest.json ```Other information
No response
Metadata
Metadata
Assignees
Labels
CsharpPull requests that update .net codePull requests that update .net codestatus:waiting-for-triageAn issue that is yet to be reviewed or assignedAn issue that is yet to be reviewed or assignedtype:bugA broken experienceA broken experience
Type
Projects
Status
Needs Triage 🔍