Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generated output has Task return type instead of expected Task<T> #41

Closed
Roflincopter opened this issue May 22, 2023 · 2 comments · Fixed by #42
Closed

Generated output has Task return type instead of expected Task<T> #41

Roflincopter opened this issue May 22, 2023 · 2 comments · Fixed by #42
Assignees
Labels
bug Something isn't working

Comments

@Roflincopter
Copy link

Hi,

I have noticed the following with refitter 0.5.26. With OpenApi spec input:

openapi: 3.0.0
x-stoplight:
  id: w776sltk0h1bo
info:
  title: Gamenight
  version: '1.0'
  contact:
    name: Dennis Brentjes
    email: dennis@brentj.es
    url: 'https://brentj.es'
  description: Api specifaction for a Gamenight server
  license:
    name: MIT
servers:
  - url: 'http://localhost:8080'
    description: Gamenight
paths:
  /token:
    get:
      summary: ''
      operationId: get-token
      responses:
        '200':
          $ref: '#/components/responses/TokenResponse'
      requestBody:
        $ref: '#/components/requestBodies/LoginRequest'
      description: Submit your credentials to get a JWT-token to use with the rest of the api.
      parameters: []
components:
  schemas:
    Token:
      title: Token
      x-stoplight:
        id: 8pz19kigm1jer
      type: object
      properties:
        jwt_token:
          type: string
    Login:
      title: Login
      type: object
      properties:
        username:
          type: string
        password:
          type: string
      required:
        - username
        - password
  requestBodies:
    LoginRequest:
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Login'
  responses:
    TokenResponse:
      description: Example response
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Token'

I get the following output, with Task missing their response output as Task result.

// <auto-generated>
//     This code was generated by Refitter.
// </auto-generated>

using Refit;
using System.Threading.Tasks;
using System.Collections.Generic;

namespace GeneratedCode
{
    public interface IGamenight
    {

        /// <summary>
        /// Submit your credentials to get a JWT-token to use with the rest of the api.
        /// </summary>
        [Get("/token")]
        Task GetToken([Body] object body);

    }


}


//----------------------
// <auto-generated>
//     Generated using the NSwag toolchain v13.19.0.0 (NJsonSchema v10.9.0.0 (Newtonsoft.Json v10.0.0.0)) (http://NSwag.org)
// </auto-generated>
//----------------------

#pragma warning disable 108 // Disable "CS0108 '{derivedDto}.ToJson()' hides inherited member '{dtoBase}.ToJson()'. Use the new keyword if hiding was intended."
#pragma warning disable 114 // Disable "CS0114 '{derivedDto}.RaisePropertyChanged(String)' hides inherited member 'dtoBase.RaisePropertyChanged(String)'. To make the current member override that implementation, add the override keyword. Otherwise add the new keyword."
#pragma warning disable 472 // Disable "CS0472 The result of the expression is always 'false' since a value of type 'Int32' is never equal to 'null' of type 'Int32?'
#pragma warning disable 612 // Disable "CS0612 '...' is obsolete"
#pragma warning disable 1573 // Disable "CS1573 Parameter '...' has no matching param tag in the XML comment for ...
#pragma warning disable 1591 // Disable "CS1591 Missing XML comment for publicly visible type or member ..."
#pragma warning disable 8073 // Disable "CS8073 The result of the expression is always 'false' since a value of type 'T' is never equal to 'null' of type 'T?'"
#pragma warning disable 3016 // Disable "CS3016 Arrays as attribute arguments is not CLS-compliant"
#pragma warning disable 8603 // Disable "CS8603 Possible null reference return"

namespace GeneratedCode
{
    using System = global::System;

    

    [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "13.19.0.0 (NJsonSchema v10.9.0.0 (Newtonsoft.Json v10.0.0.0))")]
    public partial class Token
    {

        [System.Text.Json.Serialization.JsonPropertyName("jwt_token")]

        [System.Text.Json.Serialization.JsonIgnore(Condition = System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingDefault)]   
        public string Jwt_token { get; set; }

        private System.Collections.Generic.IDictionary<string, object> _additionalProperties;

        [System.Text.Json.Serialization.JsonExtensionData]
        public System.Collections.Generic.IDictionary<string, object> AdditionalProperties
        {
            get { return _additionalProperties ?? (_additionalProperties = new System.Collections.Generic.Dictionary<string, object>()); }
            set { _additionalProperties = value; }
        }

    }

    [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "13.19.0.0 (NJsonSchema v10.9.0.0 (Newtonsoft.Json v10.0.0.0))")]
    public partial class Login
    {

        [System.Text.Json.Serialization.JsonPropertyName("username")]

        [System.Text.Json.Serialization.JsonIgnore(Condition = System.Text.Json.Serialization.JsonIgnoreCondition.Never)]   
        [System.ComponentModel.DataAnnotations.Required(AllowEmptyStrings = true)]
        public string Username { get; set; }

        [System.Text.Json.Serialization.JsonPropertyName("password")]

        [System.Text.Json.Serialization.JsonIgnore(Condition = System.Text.Json.Serialization.JsonIgnoreCondition.Never)]   
        [System.ComponentModel.DataAnnotations.Required(AllowEmptyStrings = true)]
        public string Password { get; set; }

        private System.Collections.Generic.IDictionary<string, object> _additionalProperties;

        [System.Text.Json.Serialization.JsonExtensionData]
        public System.Collections.Generic.IDictionary<string, object> AdditionalProperties
        {
            get { return _additionalProperties ?? (_additionalProperties = new System.Collections.Generic.Dictionary<string, object>()); }
            set { _additionalProperties = value; }
        }

    }


}

#pragma warning restore  108
#pragma warning restore  114
#pragma warning restore  472
#pragma warning restore  612
#pragma warning restore 1573
#pragma warning restore 1591
#pragma warning restore 8073
#pragma warning restore 3016
#pragma warning restore 8603

When I apply this patch to refitter

diff --git a/src/Refitter.Core/RefitInterfaceGenerator.cs b/src/Refitter.Core/RefitInterfaceGenerator.cs
index ad588c4..0b19ab0 100644
--- a/src/Refitter.Core/RefitInterfaceGenerator.cs
+++ b/src/Refitter.Core/RefitInterfaceGenerator.cs
@@ -40,7 +40,7 @@ public class RefitInterfaceGenerator
                 var operation = operations.Value;
 
                 var returnTypeParameter = operation.Responses.ContainsKey("200")
-                    ? generator.GetTypeName(operation.Responses["200"].Schema, true, null)
+                    ? generator.GetTypeName(operation.Responses["200"].ActualResponse.Schema, true, null)
                     : null;
 
                 var returnType = GetReturnType(returnTypeParameter);

I get the expected output with Task returning their output.

// <auto-generated>
//     This code was generated by Refitter.
// </auto-generated>

using Refit;
using System.Threading.Tasks;
using System.Collections.Generic;

namespace GeneratedCode
{
    public interface IGamenight
    {

        /// <summary>
        /// Submit your credentials to get a JWT-token to use with the rest of the api.
        /// </summary>
        [Get("/token")]
        Task<Token> GetToken([Body] object body);

    }


}


//----------------------
// <auto-generated>
//     Generated using the NSwag toolchain v13.19.0.0 (NJsonSchema v10.9.0.0 (Newtonsoft.Json v10.0.0.0)) (http://NSwag.org)
// </auto-generated>
//----------------------

#pragma warning disable 108 // Disable "CS0108 '{derivedDto}.ToJson()' hides inherited member '{dtoBase}.ToJson()'. Use the new keyword if hiding was intended."
#pragma warning disable 114 // Disable "CS0114 '{derivedDto}.RaisePropertyChanged(String)' hides inherited member 'dtoBase.RaisePropertyChanged(String)'. To make the current member override that implementation, add the override keyword. Otherwise add the new keyword."
#pragma warning disable 472 // Disable "CS0472 The result of the expression is always 'false' since a value of type 'Int32' is never equal to 'null' of type 'Int32?'
#pragma warning disable 612 // Disable "CS0612 '...' is obsolete"
#pragma warning disable 1573 // Disable "CS1573 Parameter '...' has no matching param tag in the XML comment for ...
#pragma warning disable 1591 // Disable "CS1591 Missing XML comment for publicly visible type or member ..."
#pragma warning disable 8073 // Disable "CS8073 The result of the expression is always 'false' since a value of type 'T' is never equal to 'null' of type 'T?'"
#pragma warning disable 3016 // Disable "CS3016 Arrays as attribute arguments is not CLS-compliant"
#pragma warning disable 8603 // Disable "CS8603 Possible null reference return"

namespace GeneratedCode
{
    using System = global::System;

    

    [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "13.19.0.0 (NJsonSchema v10.9.0.0 (Newtonsoft.Json v10.0.0.0))")]
    public partial class Token
    {

        [System.Text.Json.Serialization.JsonPropertyName("jwt_token")]

        [System.Text.Json.Serialization.JsonIgnore(Condition = System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingDefault)]   
        public string Jwt_token { get; set; }

        private System.Collections.Generic.IDictionary<string, object> _additionalProperties;

        [System.Text.Json.Serialization.JsonExtensionData]
        public System.Collections.Generic.IDictionary<string, object> AdditionalProperties
        {
            get { return _additionalProperties ?? (_additionalProperties = new System.Collections.Generic.Dictionary<string, object>()); }
            set { _additionalProperties = value; }
        }

    }

    [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "13.19.0.0 (NJsonSchema v10.9.0.0 (Newtonsoft.Json v10.0.0.0))")]
    public partial class Login
    {

        [System.Text.Json.Serialization.JsonPropertyName("username")]

        [System.Text.Json.Serialization.JsonIgnore(Condition = System.Text.Json.Serialization.JsonIgnoreCondition.Never)]   
        [System.ComponentModel.DataAnnotations.Required(AllowEmptyStrings = true)]
        public string Username { get; set; }

        [System.Text.Json.Serialization.JsonPropertyName("password")]

        [System.Text.Json.Serialization.JsonIgnore(Condition = System.Text.Json.Serialization.JsonIgnoreCondition.Never)]   
        [System.ComponentModel.DataAnnotations.Required(AllowEmptyStrings = true)]
        public string Password { get; set; }

        private System.Collections.Generic.IDictionary<string, object> _additionalProperties;

        [System.Text.Json.Serialization.JsonExtensionData]
        public System.Collections.Generic.IDictionary<string, object> AdditionalProperties
        {
            get { return _additionalProperties ?? (_additionalProperties = new System.Collections.Generic.Dictionary<string, object>()); }
            set { _additionalProperties = value; }
        }

    }


}

#pragma warning restore  108
#pragma warning restore  114
#pragma warning restore  472
#pragma warning restore  612
#pragma warning restore 1573
#pragma warning restore 1591
#pragma warning restore 8073
#pragma warning restore 3016
#pragma warning restore 8603

The original behaviour seems to be a bug, I have no idea however if my "fix" has any impact on existing projects but I suspect that ActualResponse wil link be a reference to itself when not being used by a ref. But that is a question you might be able to answer.

@Roflincopter Roflincopter changed the title Generated output has Task return argument instead of expected Task<T> Generated output has Task return type instead of expected Task<T> May 22, 2023
@christianhelle
Copy link
Owner

Awesome catch @Roflincopter. This project started out as a public repo with zero commits and I learned how to use NSwag as an OpenAPI spec parser on this project alone so my knowledge and experience would not be much more than yours.

I have a comprehensive suite of regression tests that run as part of a pull request build so we should be able to catch errors there. This helped me and other contributors quite a lot to ensure that the generated code builds on different sets of example OpenAPI specifications.

If you create a PR @Roflincopter then I will gladly approve it

@christianhelle christianhelle added the bug Something isn't working label May 23, 2023
@christianhelle christianhelle self-assigned this May 23, 2023
@christianhelle
Copy link
Owner

christianhelle commented May 24, 2023

@Roflincopter your fix is now published to nuget.org as v0.5.27

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants