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

I can not generate interface #249

Closed
MohMehrnia opened this issue Dec 15, 2023 · 25 comments
Closed

I can not generate interface #249

MohMehrnia opened this issue Dec 15, 2023 · 25 comments
Assignees
Labels
bug Something isn't working

Comments

@MohMehrnia
Copy link

i have a json

{"swaggerVersion":"1.2","apis":[{"path":"/v2/servers/{serverName}/vhosts/{vhostName}/applications","description":"Application Operations"},{"path":"/v2/machine/monitoring/current","description":"Machine Level Current Statistics"},{"path":"/v2/machine/monitoring/historic","description":"Machine Level Historic Statistics"},{"path":"/v2/servers/{serverName}/licenses","description":"Server Licenses"},{"path":"/v2/servers/{serverName}/listeners","description":"Server Listeners"},{"path":"/v2/servers/{serverName}/log4j","description":"Server log4j system"},{"path":"/v2/servers/{serverName}/mediacache","description":"Server MediaCache"},{"path":"/v3/servers/{serverName}/mediacache","description":"Server MediaCache Version 3"},{"path":"/v2/servers/{serverName}/mediacasters","description":"Server MediaCasters"},{"path":"/v2/servers/{serverName}/monitoring","description":"Server Monitoring"},{"path":"/v2/servers/{serverName}/publishers","description":"Server Publishers"},{"path":"/v3/servers/{serverName}/publishers","description":"Server Publishers Version 3"},{"path":"/restinfo","description":"REST information"},{"path":"/v2/servers","description":"Servers Configuration"},{"path":"/v2/servers/{serverName}/status","description":"Server Status"},{"path":"/v2/servers/{serverName}/transcoder","description":"Server Transcoder"},{"path":"/v2/servers/{serverName}/tune","description":"Server Tuning"},{"path":"/v2/servers/{serverName}/users","description":"Server Users"},{"path":"/v2/servers/{serverName}/vhosts","description":"VHost Operations"}],"apiVersion":"1.0.0"}

buy i can not generate interface

@MohMehrnia MohMehrnia added the bug Something isn't working label Dec 15, 2023
@christianhelle
Copy link
Owner

@MohMehrnia thanks for taking the time to report this.

Do you have a support key? Do you get any specific error?

It could be that the OpenAPI spec contains validation errors, try using the --skip-validation argument

@christianhelle
Copy link
Owner

I tried the OpenAPI spec file myself, but first I had to format it in with indentations to be a bit more readable

{
    "swaggerVersion": "1.2",
    "apis": [
        {
            "path": "/v2/servers/{serverName}/vhosts/{vhostName}/applications",
            "description": "Application Operations"
        },
        {
            "path": "/v2/machine/monitoring/current",
            "description": "Machine Level Current Statistics"
        },
        {
            "path": "/v2/machine/monitoring/historic",
            "description": "Machine Level Historic Statistics"
        },
        {
            "path": "/v2/servers/{serverName}/licenses",
            "description": "Server Licenses"
        },
        {
            "path": "/v2/servers/{serverName}/listeners",
            "description": "Server Listeners"
        },
        {
            "path": "/v2/servers/{serverName}/log4j",
            "description": "Server log4j system"
        },
        {
            "path": "/v2/servers/{serverName}/mediacache",
            "description": "Server MediaCache"
        },
        {
            "path": "/v3/servers/{serverName}/mediacache",
            "description": "Server MediaCache Version 3"
        },
        {
            "path": "/v2/servers/{serverName}/mediacasters",
            "description": "Server MediaCasters"
        },
        {
            "path": "/v2/servers/{serverName}/monitoring",
            "description": "Server Monitoring"
        },
        {
            "path": "/v2/servers/{serverName}/publishers",
            "description": "Server Publishers"
        },
        {
            "path": "/v3/servers/{serverName}/publishers",
            "description": "Server Publishers Version 3"
        },
        {
            "path": "/restinfo",
            "description": "REST information"
        },
        {
            "path": "/v2/servers",
            "description": "Servers Configuration"
        },
        {
            "path": "/v2/servers/{serverName}/status",
            "description": "Server Status"
        },
        {
            "path": "/v2/servers/{serverName}/transcoder",
            "description": "Server Transcoder"
        },
        {
            "path": "/v2/servers/{serverName}/tune",
            "description": "Server Tuning"
        },
        {
            "path": "/v2/servers/{serverName}/users",
            "description": "Server Users"
        },
        {
            "path": "/v2/servers/{serverName}/vhosts",
            "description": "VHost Operations"
        }
    ],
    "apiVersion": "1.0.0"
}

Unfortunately, this spec has too little information to generate anything from. Even if you use the --skip-validation argument on it the C# output will just be

public partial interface IApiClient
{
}

I haven't worked much with Swagger v1.2 but I can see from older docs that it supports operations per path. Refitter deeply relies on operations to generate code as this is where the HTTP method, route parameters, and request/response types are defined.

If you're using Swagger v1.2 then Refitter will expect something like this:

{
  "apiVersion": "1.0.0",
  "swaggerVersion": "1.2",
  "basePath": "http://petstore.swagger.wordnik.com/api",
  "resourcePath": "/store",
  "produces": [
    "application/json"
  ],
  "authorizations": {},
  "apis": [
    {
      "path": "/store/order/{orderId}",
      "operations": [
        {
          "method": "GET",
          "summary": "Find purchase order by ID",
          "notes": "For valid response try integer IDs with value <= 5. Anything above 5 or nonintegers will generate API errors",
          "type": "Order",
          "nickname": "getOrderById",
          "authorizations": {},
          "parameters": [
            {
              "name": "orderId",
              "description": "ID of pet that needs to be fetched",
              "required": true,
              "type": "string",
              "paramType": "path"
            }
          ],
          "responseMessages": [
            {
              "code": 400,
              "message": "Invalid ID supplied"
            },
            {
              "code": 404,
              "message": "Order not found"
            }
          ]
        },
        {
          "method": "DELETE",
          "summary": "Delete purchase order by ID",
          "notes": "For valid response try integer IDs with value < 1000.  Anything above 1000 or nonintegers will generate API errors",
          "type": "void",
          "nickname": "deleteOrder",
          "authorizations": {
            "oauth2": [
              {
                "scope": "test:anything",
                "description": "anything"
              }
            ]
          },
          "parameters": [
            {
              "name": "orderId",
              "description": "ID of the order that needs to be deleted",
              "required": true,
              "type": "string",
              "paramType": "path"
            }
          ],
          "responseMessages": [
            {
              "code": 400,
              "message": "Invalid ID supplied"
            },
            {
              "code": 404,
              "message": "Order not found"
            }
          ]
        }
      ]
    },
    {
      "path": "/store/order",
      "operations": [
        {
          "method": "POST",
          "summary": "Place an order for a pet",
          "notes": "",
          "type": "void",
          "nickname": "placeOrder",
          "authorizations": {
            "oauth2": [
              {
                "scope": "test:anything",
                "description": "anything"
              }
            ]
          },
          "parameters": [
            {
              "name": "body",
              "description": "order placed for purchasing the pet",
              "required": true,
              "type": "Order",
              "paramType": "body"
            }
          ],
          "responseMessages": [
            {
              "code": 400,
              "message": "Invalid order"
            }
          ]
        }
      ]
    }
  ],
  "models": {
    "Order": {
      "id": "Order",
      "properties": {
        "id": {
          "type": "integer",
          "format": "int64"
        },
        "petId": {
          "type": "integer",
          "format": "int64"
        },
        "quantity": {
          "type": "integer",
          "format": "int32"
        },
        "status": {
          "type": "string",
          "description": "Order Status",
          "enum": [
            "placed",
            "approved",
            "delivered"
          ]
        },
        "shipDate": {
          "type": "string",
          "format": "date-time"
        }
      }
    }
  }
}

which is taken from https://github.com/OAI/OpenAPI-Specification/blob/main/versions/1.2.md#521-object-example

Sorry, but I don't think I can help you with this @MohMehrnia

@MohMehrnia
Copy link
Author

applications.json

this is json qwith wuth you suggestion format but bug is still

@christianhelle
Copy link
Owner

@MohMehrnia I just tried out the spec you shared. Unfortunately, you're right, it can't seem to be parsed correctly.

Apparently, it seems that NSwag, the library I use to parse OpenAPI specifications doesn't support version 1.2. NSwag only supports v2.0 and v3.0, it can sometimes work with v3.1 as well but not all features are supported

You might want to convert or migrate it to v3.0. It's a large spec so converting/migrating it to v3.0 by hand might be a lot of work. I have seen a couple of tools for converting a v2.0 spec to v3.0 but I've never tried working with a v1.2 spec (until today)

@MohMehrnia
Copy link
Author

@christianhelle
Copy link
Owner

@MohMehrnia I tried converting that spec using Swagger Converter and got v3.0.1 spec that contained errors. I tried to fix them manually, but since I don't know the API, I might have just introduced errors.

Anyway, this file: converted-swagger-v1-spec.json now produces this Output. I had to compress it myself so I can upload it to Github

I haven't tested if it even at all compiles, but it should be a good starting point

@MohMehrnia
Copy link
Author

how do convert to 3.01?

@christianhelle
Copy link
Owner

how do convert to 3.01?

I used https://converter.swagger.io/

@MohMehrnia
Copy link
Author

show me this error

Errors
Hide
 
Fetch error
Failed to fetch http://185.113.9.221:8089/v2/servers/%7BserverName%7D/vhosts/%7BvhostName%7D/applications
Fetch error
Possible mixed-content issue? The page was loaded over https:// but a http:// URL was specified. Check that you are not attempting to load mixed content.
 

@christianhelle
Copy link
Owner

@MohMehrnia I tried converting that spec using Swagger Converter and got v3.0.1 spec that contained errors. I tried to fix them manually, but since I don't know the API, I might have just introduced errors.

Anyway, this file: converted-swagger-v1-spec.json now produces this Output. I had to compress it myself so I can upload it to Github

I haven't tested if it even at all compiles, but it should be a good starting point

@MohMehrnia Have you tried the files I linked to here?

@MohMehrnia
Copy link
Author

@christianhelle
Copy link
Owner

@MohMehrnia I did the conversion for you, which resulted in this file: converted-swagger-v1-spec.json. I had to make minor changes so that it works and it now produces this Output.

Please check the hyperlinks in my comments

@christianhelle
Copy link
Owner

@MohMehrnia Swagger spec v1 is a bit out of the scope of what Refitter handles so I think I will close this issue

@MohMehrnia
Copy link
Author

thanks

@MohMehrnia
Copy link
Author

MohMehrnia commented Jan 5, 2024

log4j.json
mediacache-v3.json
publishers-v3.json
vhosts.json

I can not convert this file @christianhelle ?!

@christianhelle
Copy link
Owner

@MohMehrnia What errors do you get? Do you have a support key? What version of Refitter are you using?

@MohMehrnia
Copy link
Author

Latest version, some property not detected

@MohMehrnia
Copy link
Author

you can tested a send files

@MohMehrnia
Copy link
Author

thanks for helping

@christianhelle
Copy link
Owner

I tried out the files you and NSwag doesn't seem to like them much, actually I tried them with 4 different code generators and it seems that only Microsoft Kiota knows how to read the OAS documents

You can try out one of my other tools called REST API Client Code Generator

To install:

dotnet tool install -g rapicgen

to generate code

rapicgen csharp kiota [openapi file]

I'm considering switching out NSwag entirely with hand generated contracts as NSwag is a bit to strict with OpenAPI specs

@christianhelle
Copy link
Owner

@MohMehrnia I tried fixing the OpenAPI specs by hand and got them to work with Refitter. I didn't trying building the output file though, but it should be a start.

Here they are with the fixes...

log4j.json
vhosts.json
publishers-v3.json
mediacache-v3.json

The output error messages that Refitter writes is a direct hint to what needed to be fixed in the spec

@MohMehrnia
Copy link
Author

Hi @christianhelle
when run codes show me below error

Refit.ApiException: An error occured deserializing the response.
 ---> System.Text.Json.JsonException: The input does not contain any JSON tokens. Expected the input to start with a valid JSON token, when isFinalBlock is true. Path: $ | LineNumber: 0 | BytePositionInLine: 0.
 ---> System.Text.Json.JsonReaderException: The input does not contain any JSON tokens. Expected the input to start with a valid JSON token, when isFinalBlock is true. LineNumber: 0 | BytePositionInLine: 0.
   at System.Text.Json.ThrowHelper.ThrowJsonReaderException(Utf8JsonReader& json, ExceptionResource resource, Byte nextByte, ReadOnlySpan`1 bytes)
   at System.Text.Json.Utf8JsonReader.Read()
   at System.Text.Json.Serialization.JsonConverter`1.ReadCore(Utf8JsonReader& reader, JsonSerializerOptions options, ReadStack& state)
   --- End of inner exception stack trace ---
   at System.Text.Json.ThrowHelper.ReThrowWithPath(ReadStack& state, JsonReaderException ex)
   at System.Text.Json.Serialization.JsonConverter`1.ReadCore(Utf8JsonReader& reader, JsonSerializerOptions options, ReadStack& state)
   at System.Text.Json.Serialization.Metadata.JsonTypeInfo`1.ContinueDeserialize(ReadBufferState& bufferState, JsonReaderState& jsonReaderState, ReadStack& readStack)
   at System.Text.Json.Serialization.Metadata.JsonTypeInfo`1.DeserializeAsync(Stream utf8Json, CancellationToken cancellationToken)
   at System.Net.Http.Json.HttpContentJsonExtensions.ReadFromJsonAsyncCore[T](HttpContent content, JsonSerializerOptions options, CancellationToken cancellationToken)
   at Refit.SystemTextJsonContentSerializer.FromHttpContentAsync[T](HttpContent content, CancellationToken cancellationToken) in /_/Refit/SystemTextJsonContentSerializer.cs:line 56
   at Refit.RequestBuilderImplementation.DeserializeContentAsync[T](HttpResponseMessage resp, HttpContent content, CancellationToken cancellationToken) in /_/Refit/RequestBuilderImplementation.cs:line 344
   at Refit.RequestBuilderImplementation.<>c__DisplayClass14_0`2.<<BuildCancellableTaskFuncForMethod>b__0>d.MoveNext() in /_/Refit/RequestBuilderImplementation.cs:line 294
   --- End of inner exception stack trace ---
   at Refit.RequestBuilderImplementation.<>c__DisplayClass14_0`2.<<BuildCancellableTaskFuncForMethod>b__0>d.MoveNext() in /_/Refit/RequestBuilderImplementation.cs:line 298
--- End of stack trace from previous location ---
   at Sin.WorkerService.Wowza.Worker.ExecuteAsync(CancellationToken stoppingToken) in /home/mohammad/MySourceCode/dotnet/sin-dotnet-backend/Sin.WorkerService.Wowza/Worker.cs:line 17

@christianhelle
Copy link
Owner

Hi @christianhelle when run codes show me below error

Refit.ApiException: An error occured deserializing the response.
 ---> System.Text.Json.JsonException: The input does not contain any JSON tokens. Expected the input to start with a valid JSON token, when isFinalBlock is true. Path: $ | LineNumber: 0 | BytePositionInLine: 0.
 ---> System.Text.Json.JsonReaderException: The input does not contain any JSON tokens. Expected the input to start with a valid JSON token, when isFinalBlock is true. LineNumber: 0 | BytePositionInLine: 0.
   at System.Text.Json.ThrowHelper.ThrowJsonReaderException(Utf8JsonReader& json, ExceptionResource resource, Byte nextByte, ReadOnlySpan`1 bytes)
   at System.Text.Json.Utf8JsonReader.Read()
   at System.Text.Json.Serialization.JsonConverter`1.ReadCore(Utf8JsonReader& reader, JsonSerializerOptions options, ReadStack& state)
   --- End of inner exception stack trace ---
   at System.Text.Json.ThrowHelper.ReThrowWithPath(ReadStack& state, JsonReaderException ex)
   at System.Text.Json.Serialization.JsonConverter`1.ReadCore(Utf8JsonReader& reader, JsonSerializerOptions options, ReadStack& state)
   at System.Text.Json.Serialization.Metadata.JsonTypeInfo`1.ContinueDeserialize(ReadBufferState& bufferState, JsonReaderState& jsonReaderState, ReadStack& readStack)
   at System.Text.Json.Serialization.Metadata.JsonTypeInfo`1.DeserializeAsync(Stream utf8Json, CancellationToken cancellationToken)
   at System.Net.Http.Json.HttpContentJsonExtensions.ReadFromJsonAsyncCore[T](HttpContent content, JsonSerializerOptions options, CancellationToken cancellationToken)
   at Refit.SystemTextJsonContentSerializer.FromHttpContentAsync[T](HttpContent content, CancellationToken cancellationToken) in /_/Refit/SystemTextJsonContentSerializer.cs:line 56
   at Refit.RequestBuilderImplementation.DeserializeContentAsync[T](HttpResponseMessage resp, HttpContent content, CancellationToken cancellationToken) in /_/Refit/RequestBuilderImplementation.cs:line 344
   at Refit.RequestBuilderImplementation.<>c__DisplayClass14_0`2.<<BuildCancellableTaskFuncForMethod>b__0>d.MoveNext() in /_/Refit/RequestBuilderImplementation.cs:line 294
   --- End of inner exception stack trace ---
   at Refit.RequestBuilderImplementation.<>c__DisplayClass14_0`2.<<BuildCancellableTaskFuncForMethod>b__0>d.MoveNext() in /_/Refit/RequestBuilderImplementation.cs:line 298
--- End of stack trace from previous location ---
   at Sin.WorkerService.Wowza.Worker.ExecuteAsync(CancellationToken stoppingToken) in /home/mohammad/MySourceCode/dotnet/sin-dotnet-backend/Sin.WorkerService.Wowza/Worker.cs:line 17

This doesn't really have anything to do with Refitter (or Refit) and this looks like the HTTP response body didn't contain any JSON payload. Perhaps the API returned HTTP 4xx or 5xx with an HTML body?

You can add a message handler that logs the raw HTTP response to your HttpClient delegating handlers pipeline to verify

@MohMehrnia
Copy link
Author

I fixed last error by show me another error

Refit.ApiException: An error occured deserializing the response.
 ---> System.Text.Json.JsonException: '<' is an invalid start of a value. Path: $ | LineNumber: 0 | BytePositionInLine: 0.
 ---> System.Text.Json.JsonReaderException: '<' is an invalid start of a value. LineNumber: 0 | BytePositionInLine: 0.
   at System.Text.Json.ThrowHelper.ThrowJsonReaderException(Utf8JsonReader& json, ExceptionResource resource, Byte nextByte, ReadOnlySpan`1 bytes)
   at System.Text.Json.Utf8JsonReader.ConsumeValue(Byte marker)
   at System.Text.Json.Utf8JsonReader.ReadFirstToken(Byte first)
   at System.Text.Json.Utf8JsonReader.ReadSingleSegment()
   at System.Text.Json.Utf8JsonReader.Read()
   at System.Text.Json.Serialization.JsonConverter`1.ReadCore(Utf8JsonReader& reader, JsonSerializerOptions options, ReadStack& state)
   --- End of inner exception stack trace ---
   at System.Text.Json.ThrowHelper.ReThrowWithPath(ReadStack& state, JsonReaderException ex)
   at System.Text.Json.Serialization.JsonConverter`1.ReadCore(Utf8JsonReader& reader, JsonSerializerOptions options, ReadStack& state)
   at System.Text.Json.Serialization.Metadata.JsonTypeInfo`1.ContinueDeserialize(ReadBufferState& bufferState, JsonReaderState& jsonReaderState, ReadStack& readStack)
   at System.Text.Json.Serialization.Metadata.JsonTypeInfo`1.DeserializeAsync(Stream utf8Json, CancellationToken cancellationToken)
   at System.Net.Http.Json.HttpContentJsonExtensions.ReadFromJsonAsyncCore[T](HttpContent content, JsonSerializerOptions options, CancellationToken cancellationToken)
   at Refit.SystemTextJsonContentSerializer.FromHttpContentAsync[T](HttpContent content, CancellationToken cancellationToken) in /_/Refit/SystemTextJsonContentSerializer.cs:line 56
   at Refit.RequestBuilderImplementation.DeserializeContentAsync[T](HttpResponseMessage resp, HttpContent content, CancellationToken cancellationToken) in /_/Refit/RequestBuilderImplementation.cs:line 344
   at Refit.RequestBuilderImplementation.<>c__DisplayClass14_0`2.<<BuildCancellableTaskFuncForMethod>b__0>d.MoveNext() in /_/Refit/RequestBuilderImplementation.cs:line 294
   --- End of inner exception stack trace ---
   at Refit.RequestBuilderImplementation.<>c__DisplayClass14_0`2.<<BuildCancellableTaskFuncForMethod>b__0>d.MoveNext() in /_/Refit/RequestBuilderImplementation.cs:line 298
--- End of stack trace from previous location ---
   at Sin.WorkerService.Wowza.Worker.ExecuteAsync(CancellationToken stoppingToken) in /home/mohammad/MySourceCode/dotnet/sin-dotnet-backend/Sin.WorkerService.Wowza/Worker.cs:line 17

@MohMehrnia
Copy link
Author

Result is a with postman

<?xml version='1.0' encoding='UTF-8'?>
<RESTInfo>
    <APIVersion>1</APIVersion>
    <RestBuild>20230519113009</RestBuild>
    <CentralConfig>false</CentralConfig>
    <LicenseValid>true</LicenseValid>
</RESTInfo>

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

No branches or pull requests

2 participants