RicoSuter / NSwag

The Swagger/OpenAPI toolchain for .NET, ASP.NET Core and TypeScript.
http://NSwag.org
MIT License
6.7k stars 1.23k forks source link

Include content in response object Nswag client #3282

Open JanOgr opened 3 years ago

JanOgr commented 3 years ago

I am currently learning about Nswag studio and have managed to generate a C# client. The generated client consumes an HTTP client and I manage to get a successful response when calling the available endpoints. However, I cannot seem to get the response body from each and every request. The only thing included in the swagger responses is the headers and the status code. Is there a way to automatically include the response content in the SwaggerResponse object or specifying what the response object should include? I.e I do not want to rewrite the generated code and check it it since I need to generate it on the fly for what I'm trying to do. I have googled for hours, tried different versions etc but cannot find what I am missing

nswag openapi2csclient /input:https://www.foodrepo.org/api-docs/swaggers/v3.json /namespace:BaseTestFrameworkCSharp.App.FoodApi /output:BaseTestFrameworkCSharp/App/FoodApi/FoodApi.cs /classname:FoodApi /usehttpclientcreationmethod:tru e /injectHttpClient:true /generateBaseUrlProperty:true /useBaseUrl:true /operationGenerationMode:SingleClientFromPathSegments /runtime:Net50 /clientClassAccessModifier:public /generateJsonMethods:true /generateDataAnnotations:true /gene rateDtoTypes:true /wrapResponses:true /generateResponseClasses:true /generateClientInterfaces:true /UseRequestAndResponseSerializationSettings:true

The generated response class looks like this, notice there is no response body only headers and status code:

    [System.CodeDom.Compiler.GeneratedCode("NSwag", "13.10.1.0 (NJsonSchema v10.3.3.0 (Newtonsoft.Json v11.0.0.0))")]
    public partial class SwaggerResponse
    {
        public int StatusCode { get; private set; }

        public System.Collections.Generic.IReadOnlyDictionary<string, System.Collections.Generic.IEnumerable<string>> Headers { get; private set; }

        public SwaggerResponse(int statusCode, System.Collections.Generic.IReadOnlyDictionary<string, System.Collections.Generic.IEnumerable<string>> headers) 
        {
            StatusCode = statusCode; 
            Headers = headers;
        }
    }

Is this functionality supported or have I missed something? If not is there a work around for generating clients on the fly based on openapi specs? @RicoSuter :D

RicoSuter commented 3 years ago

Did you try to set ReadResponseAsString to true on the client?

JanOgr commented 3 years ago

Like this? Then yes.

var foodApi = new FoodApi(client) { BaseUrl = "https://www.foodrepo.org/api/v3", ReadResponseAsString = true };

RicoSuter commented 3 years ago

The idea is that there is also a SwaggerResponse where T is the type of the response where you can actually access the deserialized body as described by the spec.

JanOgr commented 3 years ago

Ok how would that look like? I Have tried a few api specs but seem to have the same problem. Eg if you would want HttpResponseMessage back.

JanOgr commented 3 years ago

Ok, misunderstood the response at first. So the response body needs to be specified in the spec then a class is created based on that json which is used for the T Result? And if there is no response model in the spec there is no way of just getting the plain httpresponsemessage and do the serialization on your own?

vidyaalan commented 2 years ago

Hi, I'm facing the same problem. Not able to get the response content. I see only response code and Headers. Any suggestion would be helpful.

In below code only status and headers are returned

var response = await client.SendAsync(request, System.Net.Http.HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false); var disposeResponse = true; try { var headers = System.Linq.Enumerable.ToDictionary(response.Headers, h => h.Key, h => h.Value); if (response.Content != null && response.Content.Headers != null) { foreach (var item in response.Content.Headers) headers[item.Key] = item_.Value; }

                    ProcessResponse(client_, response_);

                    var status_ = (int)response_.StatusCode;
                    if (status_ == 200)
                    {
                        return new RestResponse(status_, headers_);
                    }
                    else
                    {
                        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 (" + status_ + ").", status_, responseData_, headers_, null);
                    }
                }