question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Regression from 13.6.2 to 13.7.0

See original GitHub issue

A SwaggerException is generated in the C# client when upgrading from 13.6.2 to 13.7.0 Beware that the entity returned contains types like enums, DateTime?, byte…

How can I determine what field is failing?

Sample method OK 13.6.2

        public async System.Threading.Tasks.Task<Asset> GetAssetAsync(int assetId, int? version, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken))
        {
            if (assetId == null)
                throw new System.ArgumentNullException("assetId");
    
            var urlBuilder_ = new System.Text.StringBuilder();
            urlBuilder_.Append(BaseUrl != null ? BaseUrl.TrimEnd('/') : "").Append("/api/Asset/GetAsset?");
            urlBuilder_.Append(System.Uri.EscapeDataString("assetId") + "=").Append(System.Uri.EscapeDataString(ConvertToString(assetId, System.Globalization.CultureInfo.InvariantCulture))).Append("&");
            urlBuilder_.Append(System.Uri.EscapeDataString("version") + "=").Append(System.Uri.EscapeDataString(version != null ? ConvertToString(version, System.Globalization.CultureInfo.InvariantCulture) : "")).Append("&");
            urlBuilder_.Length--;
    
            var client_ = await CreateHttpClientAsync(cancellationToken).ConfigureAwait(false);
            try
            {
                using (var request_ = await CreateHttpRequestMessageAsync(cancellationToken).ConfigureAwait(false))
                {
                    request_.Method = new System.Net.Http.HttpMethod("GET");
                    request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("application/json"));
    
                    PrepareRequest(client_, request_, urlBuilder_);
                    var url_ = urlBuilder_.ToString();
                    request_.RequestUri = new System.Uri(url_, System.UriKind.RelativeOrAbsolute);
                    PrepareRequest(client_, request_, url_);
    
                    var response_ = await client_.SendAsync(request_, System.Net.Http.HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false);
                    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).ToString();
                        if (status_ == "200") 
                        {
                            var objectResponse_ = await ReadObjectResponseAsync<Asset>(response_, headers_).ConfigureAwait(false);
                            return objectResponse_.Object;
                        }
                        else
                        if (status_ != "200" && status_ != "204")
                        {
                            var responseData_ = response_.Content == null ? null : await response_.Content.ReadAsStringAsync().ConfigureAwait(false); 
                            throw new SwaggerException("The HTTP status code of the response was not expected (" + (int)response_.StatusCode + ").", (int)response_.StatusCode, responseData_, headers_, null);
                        }
            
                        return default(Asset);
                    }
                    finally
                    {
                        if (response_ != null)
                            response_.Dispose();
                    }
                }
            }
            finally
            {
                if (client_ != null)
                    client_.Dispose();
            }
        }

...

 [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "10.1.11.0 (Newtonsoft.Json v12.0.0.0)")]
    public partial class Asset : System.ComponentModel.INotifyPropertyChanged
    {
        private int _id;
        private string _code;
        private decimal _sortSequence;
        private byte _pointsPlaces;
        private bool _quoteBasis;
        private int? _nDFFixDays;
        private ForwardCodeTypeEnum _forwardCodeType;
        private AssetStatus _statusCodeId;
        private System.DateTime _createdDate;
        private System.DateTime? _authorisedDate;
        private Risk _risk;
...
        private TechOverrideMask _techOverrideMask;
        private System.Collections.ObjectModel.ObservableCollection<AssetRegion> _assetRegions; 
        private System.Collections.ObjectModel.ObservableCollection<string> _currentChanges;
    ...
        [Newtonsoft.Json.JsonProperty("Id", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)]
        public int Id
        {
            get { return _id; }
            set 
            {
                if (_id != value)
                {
                    _id = value; 
                    RaisePropertyChanged();
                }
            }
        }
    ...

Sample method failing 13.7.0

     public async System.Threading.Tasks.Task<Asset> GetAssetAsync(int assetId, int? version, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken))
        {
            if (assetId == null)
                throw new System.ArgumentNullException("assetId");
    
            var urlBuilder_ = new System.Text.StringBuilder();
            urlBuilder_.Append(BaseUrl != null ? BaseUrl.TrimEnd('/') : "").Append("/api/Asset/GetAsset?");
            urlBuilder_.Append(System.Uri.EscapeDataString("assetId") + "=").Append(System.Uri.EscapeDataString(ConvertToString(assetId, System.Globalization.CultureInfo.InvariantCulture))).Append("&");
            urlBuilder_.Append(System.Uri.EscapeDataString("version") + "=").Append(System.Uri.EscapeDataString(version != null ? ConvertToString(version, System.Globalization.CultureInfo.InvariantCulture) : "")).Append("&");
            urlBuilder_.Length--;
    
            var client_ = await CreateHttpClientAsync(cancellationToken).ConfigureAwait(false);
            try
            {
                using (var request_ = await CreateHttpRequestMessageAsync(cancellationToken).ConfigureAwait(false))
                {
                    request_.Method = new System.Net.Http.HttpMethod("GET");
                    request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("application/json"));
    
                    PrepareRequest(client_, request_, urlBuilder_);
                    var url_ = urlBuilder_.ToString();
                    request_.RequestUri = new System.Uri(url_, System.UriKind.RelativeOrAbsolute);
                    PrepareRequest(client_, request_, url_);
    
                    var response_ = await client_.SendAsync(request_, System.Net.Http.HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false);
                    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)
                        {
                            var objectResponse_ = await ReadObjectResponseAsync<Asset>(response_, headers_).ConfigureAwait(false);
                            return objectResponse_.Object;
                        }
                        else
                        {
                            var responseData_ = response_.Content == null ? null : await response_.Content.ReadAsStringAsync().ConfigureAwait(false); 
                            throw new SwaggerException("The HTTP status code of the response was not expected (" + status_ + ").", status_, responseData_, headers_, null);
                        }
                    }
                    finally
                    {
                        if (response_ != null)
                            response_.Dispose();
                    }
                }
            }
            finally
            {
                if (client_ != null)
                    client_.Dispose();
            }
        }
    
...


    [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "10.1.24.0 (Newtonsoft.Json v12.0.0.0)")]
    public partial class Asset : System.ComponentModel.INotifyPropertyChanged
    {
        private int _id;
  ...  

Issue Analytics

  • State:open
  • Created 3 years ago
  • Reactions:2
  • Comments:42 (5 by maintainers)

github_iconTop GitHub Comments

5reactions
augustoproietecommented, Nov 4, 2020

C# is C#, and you can’t return two totally unrelated types from your methods

Hey @jeremyVignelles whilst I agree with your statement in general, I believe that’s not really what’s being asked here.

What I think we’re all looking for, myself included (and @mattwhitfield, correct me if I’m wrong) is for the NSwag client generator to understand null (for nullable types of course) when the response HTTP status code is 204.

As @mattwhitfield described in his scenario, his API either returns 202 with an entity, or 204 without an entity.

Right now, the API client throws an exception on 204 rather than returning null to the caller. This should be possible. If not the default option, it should at least be configurable.

5reactions
jeremyVignellescommented, Nov 4, 2020

Thanks @mattwhitfield for your detailed answer. I agree that NSwag should not have to make any decision for those kind of cases, but C# is C#, and you can’t return two totally unrelated types from your methods.

The default behavior there will be that NSwag will pick one result as the return type, but the other one will throw, which is not consistent with the fact that this is also a success.

That said, for these kind of use cases, I’d advise that you use the WrapDTO option which should be able to do just that, though I didn’t test it myself.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Regression from 13.6.2 to 13.7.0 · Issue #3171
I am using .Net 4.6.2 with swashbuckler 5.6 and generating c# code. I have tried setting a CanBeNull attribute on the method and...
Read more >
13.6 Testing the Regression Coefficients
Conduct and interpret a hypothesis test on individual regression coefficients. Previously, we learned that the population model for the multiple regression ...
Read more >
Logistic Regression - SAGE Publishing
Logistic regression accom- modates continuous predictor variables (e.g., age, income, baseline daily smoking), categorical predictor variables (e.g., gender, ...
Read more >
Logistic Regression - SAGE Publishing
Logistic regression accommo- dates continuous predictor variables (e.g., age, income, baseline daily smoking), categorical predictor variables (e.g., gender, ...
Read more >
13.6 Predicting with a Regression Equation
One important value of an estimated regression equation is its ability to predict the effects on Y of a change in one or...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found