-
Notifications
You must be signed in to change notification settings - Fork 13
Comparison with NSwag
The comparison is loosely related to "WebApiClientGen vs Swashbuckle.AspNetCore plus NSwag". The code generated by OpenApiClientGen is similar to what generated by WebApiClientGen. And for detailed comparison, please check Compare with NSwag of NSwagStudio v13.15.10.0.
From Open API to C#
{"integer int32", typeof(int) },
{"integer int64", typeof(long) },
{"integer", typeof(int) },
{"number float", typeof(float) },
{"number double", typeof(double) },
{"number", typeof(float) },
{"string", typeof(string) },
{"boolean", typeof(bool) },
{"string date", typeof(DateOnly) },
{"string date-time", typeof(DateTimeOffset) },
For DateOnly, please read more at "DateOnly in .NET 6 and ASP.NET Core 6".
From Open API to TypeScript
{"integer int32", "number" },
{"integer int64", "number" },
{"integer", "number" },
{"number float", "number" },
{"number double", "number" },
{"number", "number" },
{"string", "string" },
{"boolean", "boolean" },
{"string date", "Date" },
{"string date-time", "Date" },
NSwag uses fairly similar mappings.
OpenApiClientGen
For example, Pet[]
in C#, and Array<Pet>
in TypeScript.
NSwag
For example, System.Collections.Generic.ICollection<Pet>
in C#, and Pet[]
in TypeScript.
OpenApiClientGen
C#
public enum PetStatus
{
available = 0,
pending = 1,
sold = 2,
}
With setting EnumToString, the generated codes:
[System.Runtime.Serialization.DataContract(Namespace="http://pet.domain/2020/03")]
[JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))]
public enum PetStatus
{
[System.Runtime.Serialization.EnumMemberAttribute(Value="available")]
available = 0,
[System.Runtime.Serialization.EnumMemberAttribute(Value="pending")]
pending = 1,
[System.Runtime.Serialization.EnumMemberAttribute(Value="sold")]
sold = 2,
}
TypeScript
export enum PetStatus { available = 0, pending = 1, sold = 2 }
With setting EnumToString, the generated codes:
export enum PetStatus { available = 'available', pending = 'pending', sold = 'sold' }
NSwag
C#
[System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "10.1.7.0 (Newtonsoft.Json v12.0.0.0)")]
public enum Anonymous
{
[System.Runtime.Serialization.EnumMember(Value = @"available")]
Available = 0,
[System.Runtime.Serialization.EnumMember(Value = @"pending")]
Pending = 1,
[System.Runtime.Serialization.EnumMember(Value = @"sold")]
Sold = 2,
}
[System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "10.1.7.0 (Newtonsoft.Json v12.0.0.0)")]
public enum CatHuntingSkill
{
[System.Runtime.Serialization.EnumMember(Value = @"clueless")]
Clueless = 0,
[System.Runtime.Serialization.EnumMember(Value = @"lazy")]
Lazy = 1,
[System.Runtime.Serialization.EnumMember(Value = @"adventurous")]
Adventurous = 2,
[System.Runtime.Serialization.EnumMember(Value = @"aggressive")]
Aggressive = 3,
}
TypeScript
export enum Status {
Available = "available",
Pending = "pending",
Sold = "sold",
}
export enum CatHuntingSkill {
Clueless = "clueless",
Lazy = "lazy",
Adventurous = "adventurous",
Aggressive = "aggressive",
}
Open API specifications define the manipulations of HTTP headers. NSwag and many other tools support such definitions, and headers may appear in the parameters of generated client function prototypes. However OpenApiClientGen does not support respective definitions, by design. HTTP headers are generally for security and load balance, and it may be better to handle HTTP headers through HTTP interception, and most programming frameworks/libraries support HTTP interception.
When using client codes generated by OpenApiClientGen, you may use HTTP interception for the auth headers and HeadersCallback for manipulating other request headers in client codes.
OpenApiClientGen supports only response in JSON and text. If response's content type is text/xml, respective operations will be skipped.
Remarks
NSwag does not seem to support XML response even though codes are still generated for XML responses.
NSwag will typically yield the following:
var status_ = ((int)response_.StatusCode).ToString();
if (status_ == "200")
{
return;
}
else
if (status_ == "480")
{
var objectResponse_ = await ReadObjectResponseAsync<FileResponse>(response_, headers_).ConfigureAwait(false);
throw new ApiException("ScalingActivityInProgressFault", (int)response_.StatusCode, objectResponse_.Text, headers_, objectResponse_.Object);
}
else
if (status_ == "481")
{
var objectResponse_ = await ReadObjectResponseAsync<FileResponse>(response_, headers_).ConfigureAwait(false);
throw new ApiException("ResourceContentionFault", (int)response_.StatusCode, objectResponse_.Text, headers_, objectResponse_.Object);
}
else
if (status_ == "482")
{
var objectResponse_ = await ReadObjectResponseAsync<FileResponse>(response_, headers_).ConfigureAwait(false);
throw new ApiException("ServiceLinkedRoleFailure", (int)response_.StatusCode, objectResponse_.Text, headers_, objectResponse_.Object);
}
else
if (status_ != "200" && status_ != "204")
{
var responseData_ = response_.Content == null ? null : await response_.Content.ReadAsStringAsync().ConfigureAwait(false);
throw new ApiException("The HTTP status code of the response was not expected (" + (int)response_.StatusCode + ").", (int)response_.StatusCode, responseData_, headers_, null);
}
OpenApiClientGen just throws HttpRequestException or WebApiRequestException, and it is up to the client codes to do respective type casts.
For generating custom complex data types in TypeScript, NSwag offers an option of generating classes, while OpenApiClientGen generates only interfaces. This is because, mapping data from a service to clients, all you need is a contract, and interface is all you need for defining the contract.
NSwag yields verbose GeneratedCodeAttribute. The GeneratedCodeAttribute class can be used by code analysis tools to identify computer-generated code, and to provide an analysis based on the tool and the version of the tool that generated the code. However it is a good practice to put generated codes into a dedicated assembly with generated codes only. Thus an application programmer may simply exclude the assembly from code analysis tools. Therefore, GeneratedCodeAttribute may be unnecessary in the generated codes.