swagger-api / swagger-api/swagger-codegen

[C#] Missing fields and properties on csharp and csharp-dotnet2 generated subclasses using "allOf"

Open
#8,122 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Mustache
Stars
17.8k
Forks
6k
PR merge metrics
No merged PRs in 30d

Description

Description

If I use "allOf" in the schema I have a wrong classes export when I use the on-line editor and I generate client code for:

  • csharp
  • csharp-dotnet2

The exported .cs code has the subclasses, but on subclasses the filed/properties of sublasses are missing.

Swagger-codegen version

I use the codegen embedded on

Swagger declaration file content or url
definitions:
  Error:
    type: object
    properties:
      code:
        type: integer
        format: int32
      type:
        type: string
      message:
        type: string
  FieldValidationError:
    type: object
    properties:
      code:
        type: integer
        format: int32
      field:
        type: string
      message:
        type: string
  ValidationError:
    allOf:
      - $ref: '#/definitions/Error'
    type: object
    properties:
      fieldsValidationErrors:
        type: array
        items:
          $ref: '#/definitions/FieldValidationError'
Steps to reproduce

Go to , in definitions copy the YAML, go to "Generate Client" an try to export csharp.
Look at generated class ValidationError

Related issues/PRs
Suggest a fix/enhancement

The class actually generated is like:

    /// <summary>
    /// ValidationError
    /// </summary>
    [DataContract]
    public partial class ValidationError : Error,  IEquatable<ValidationError>, IValidatableObject
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="ValidationError" /> class.
        /// </summary>
        public ValidationError(int? Code = default(int?), string Type = default(string), string Message = default(string)) : base(Code, Type, Message)
        {
        }
        
        /// <summary>
        /// Returns the string presentation of the object
        /// </summary>
        /// <returns>String presentation of the object</returns>
        public override string ToString()
        {
            var sb = new StringBuilder();
            sb.Append("class ValidationError {\n");
            sb.Append("  ").Append(base.ToString().Replace("\n", "\n  ")).Append("\n");
            sb.Append("}\n");
            return sb.ToString();
        }
  
        /// <summary>
        /// Returns the JSON string presentation of the object
        /// </summary>
        /// <returns>JSON string presentation of the object</returns>
        public override string ToJson()
        {
            return JsonConvert.SerializeObject(this, Formatting.Indented);
        }

        /// <summary>
        /// Returns true if objects are equal
        /// </summary>
        /// <param name="input">Object to be compared</param>
        /// <returns>Boolean</returns>
        public override bool Equals(object input)
        {
            return this.Equals(input as ValidationError);
        }

        /// <summary>
        /// Returns true if ValidationError instances are equal
        /// </summary>
        /// <param name="input">Instance of ValidationError to be compared</param>
        /// <returns>Boolean</returns>
        public bool Equals(ValidationError input)
        {
            if (input == null)
                return false;

            return base.Equals(input);
        }

        /// <summary>
        /// Gets the hash code
        /// </summary>
        /// <returns>Hash code</returns>
        public override int GetHashCode()
        {
            unchecked // Overflow is fine, just wrap
            {
                int hashCode = base.GetHashCode();
                return hashCode;
            }
        }

        /// <summary>
        /// To validate all properties of the instance
        /// </summary>
        /// <param name="validationContext">Validation context</param>
        /// <returns>Validation Result</returns>
        IEnumerable<System.ComponentModel.DataAnnotations.ValidationResult> IValidatableObject.Validate(ValidationContext validationContext)
        {
            foreach(var x in BaseValidate(validationContext)) yield return x;
            yield break;
        }
    }

The correct one should be like:

    /// <summary>
    /// ValidationError
    /// </summary>
    [DataContract]
    public partial class ValidationError : Error,  IEquatable<ValidationError>, IValidatableObject
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="ValidationError" /> class.
        /// </summary>
        public ValidationError(int? Code = default(int?), string Type = default(string), string Message = default(string), List<FieldValidationError> FieldValidationErrors = default(List<FieldValidationError>)) : base(Code, Type, Message)
        {
            this.FieldValidationErrors = FieldValidationErrors;
        }
		
		/// <summary>
        /// Gets or Sets FieldValidationErrors
        /// </summary>
        [DataMember(Name = "fieldsValidationError", EmitDefaultValue = false)]
        public List<FieldValidationError> FieldValidationErrors { get; set; }
        
        /// <summary>
        /// Returns the string presentation of the object
        /// </summary>
        /// <returns>String presentation of the object</returns>
        public override string ToString()
        {
            var sb = new StringBuilder();
            sb.Append("class ValidationError {\n");
            sb.Append("  ").Append(base.ToString().Replace("\n", "\n  ")).Append("\n");
			sb.Append("  ").Append(FieldValidationErrors).Append("\n");
            sb.Append("}\n");
            return sb.ToString();
        }
  
        /// <summary>
        /// Returns the JSON string presentation of the object
        /// </summary>
        /// <returns>JSON string presentation of the object</returns>
        public override string ToJson()
        {
            return JsonConvert.SerializeObject(this, Formatting.Indented);
        }

        /// <summary>
        /// Returns true if objects are equal
        /// </summary>
        /// <param name="input">Object to be compared</param>
        /// <returns>Boolean</returns>
        public override bool Equals(object input)
        {
            return this.Equals(input as ValidationError);
        }

        /// <summary>
        /// Returns true if ValidationError instances are equal
        /// </summary>
        /// <param name="input">Instance of ValidationError to be compared</param>
        /// <returns>Boolean</returns>
        public bool Equals(ValidationError input)
        {
            if (input == null)
                return false;

            return base.Equals(input) &&
                (
                    this.FieldValidationErrors == input.FieldValidationErrors ||
                    this.FieldValidationErrors != null &&
                    this.FieldValidationErrors.SequenceEqual(input.FieldValidationErrors)
                );
        }

        /// <summary>
        /// Gets the hash code
        /// </summary>
        /// <returns>Hash code</returns>
        public override int GetHashCode()
        {
            unchecked // Overflow is fine, just wrap
            {
                int hashCode = base.GetHashCode();
                if (this.FieldValidationErrors != null)
                    hashCode = hashCode * 59 + this.FieldValidationErrors.GetHashCode();				
                return hashCode;
            }
        }

        /// <summary>
        /// To validate all properties of the instance
        /// </summary>
        /// <param name="validationContext">Validation context</param>
        /// <returns>Validation Result</returns>
        IEnumerable<System.ComponentModel.DataAnnotations.ValidationResult> IValidatableObject.Validate(ValidationContext validationContext)
        {
            foreach(var x in BaseValidate(validationContext)) yield return x;
            yield break;
        }
    }

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start at the online editor's Generate Client entry point and reproduce the issue with the YAML declaration in the report for csharp and csharp-dotnet2. Inspect the generated ValidationError class and the generator path responsible for allOf subclasses. Done means fieldsValidationErrors is emitted with its constructor, property, serialization, equality, hash-code, and string-output handling.

Written by the indexing model from the issue text.

Assessment

Tech stack
csharp
Domain
tooling
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.