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

[csharp] Mustache templates do not distinguish generated and native parent classes #7669

Open
lukket opened this issue Feb 16, 2018 · 8 comments · May be fixed by #10819
Open

[csharp] Mustache templates do not distinguish generated and native parent classes #7669

lukket opened this issue Feb 16, 2018 · 8 comments · May be fixed by #10819

Comments

@lukket
Copy link

lukket commented Feb 16, 2018

Description

The mustache templates do not distinguish generated and native parent classes resulting in invalid code. For example, the override modifier is set in the modelGeneric.mustach template for the ToJson method if a non-array parent exists. But the parent can be a dictionary as well (see Swagger declaration below).

public {{#parent}}{{^isArrayModel}}override {{/isArrayModel}}{{/parent}}{{^parent}}{{#discriminator}}virtual {{/discriminator}}{{/parent}}string ToJson()

Same for the validate method:

{{#parent}}
{{^isArrayModel}}
foreach(var x in BaseValidate(validationContext)) yield return x;
{{/isArrayModel}}
{{/parent}}

BaseValidate does not exist in the dictionary class.

Swagger-codegen version

Version: 2.3.0
Is it a regression? Yes, works well with version 2.3.0-20170713.173236-24.

Swagger declaration file content or url
"KeyValues": {
  "type": "object",
    "additionalProperties": {
      "type": "string"
    }
}

Generates:

public partial class KeyValues : Dictionary<String, string>,  IEquatable<KeyValues>, IValidatableObject
Command line used for generation
java -jar .\swagger-codegen-cli-2.3.0.jar generate -l csharp -i .\swagger.json -c .\config.json -o .\output\ -t .\templates\ --ignore-file-override .swagger-codegen-ignore
Steps to reproduce
  1. Create Swagger declaration with the definition mentioned above
  2. Create the code java -jar .\swagger-codegen-cli-2.3.0.jar generate -l csharp -i .\swagger.json
  3. Try to build the generated code. You will get an compiler error CS0115:
'KeyValues.ToJson()' : no suitable method found to override
Suggest a fix/enhancement

If there would be a template variable like isArrayModel but for dictionaries or native parent classes in general, we could adjust the existing templates easily.

For example like this:

{{#parent}}
{{^isArrayModel}}
{{^isDictionary}}
foreach(var x in BaseValidate(validationContext)) yield return x;
{{/isDictionary}}
{{/isArrayModel}}
{{/parent}}
@wickedw
Copy link

wickedw commented Jun 4, 2019

Could anyone please clarify if there is a known fix for this issue? thank you.

@cnmicha
Copy link

cnmicha commented Jun 4, 2019

@wickedw You can use the csharp-dotnet2 client code generator. Although it does not respect request content-types, the created code is easy to fix.

@rdecarreau
Copy link

rdecarreau commented Mar 18, 2020

I get an error similar to this on swagger codegen v3 cli.
The name 'BaseValidate' does not exist in the current context

My OpenAPI spec is OpenAPI v 3.0.0. I don't use any additionalProperties, but I do have a few anyOf, allOf's. It appears that this ValidationContext function only shows up where my OpenAPI spec used anyOf.
I am using swagger cli 3.0.18 from here: https://mvnrepository.com/artifact/io.swagger.codegen.v3/swagger-codegen-cli/3.0.18

@biasc
Copy link

biasc commented May 8, 2020

I get an error similar to this on swagger codegen v3 cli.
The name 'BaseValidate' does not exist in the current context

My OpenAPI spec is OpenAPI v 3.0.0. I don't use any additionalProperties, but I do have a few anyOf, allOf's. It appears that this ValidationContext function only shows up where my OpenAPI spec used anyOf.
I am using swagger cli 3.0.18 from here: https://mvnrepository.com/artifact/io.swagger.codegen.v3/swagger-codegen-cli/3.0.18

Same problem

@megant
Copy link

megant commented Jul 9, 2020

Same here. C# .NET Core 2.2, https://app.swaggerhub.com/apis/Billingo/Billingo/3.0.7

@oleksabor
Copy link
Contributor

I've thought that the solution would be to edit mustache template file to change BaseValidate to base.Validate
However the problem is that Validate method is not virtual and is not protected.

A derived class can't get access to the base Validate method unfortunately
The base IValidatableObject.Validate method can't be made protected also because of implicit interface implementation

It is possible to add a new BaseValidate method to the every model class being generated (not sure is there an option to check are there derived classes) like below:

protected IEnumerable<System.ComponentModel.DataAnnotations.ValidationResult> BaseValidate(ValidationContext validationContext)
{
    return ((IValidatableObject)this).Validate(validationContext);
}

However I do not think that implicit IValidatableObject interface implementation should be used.
So another option is to make Validate method public and virtual:
base

public virtual IEnumerable<System.ComponentModel.DataAnnotations.ValidationResult> Validate(ValidationContext validationContext)
{
    yield break;
}

derived

public override IEnumerable<System.ComponentModel.DataAnnotations.ValidationResult> Validate(ValidationContext validationContext)
{
    foreach(var x in base.Validate(validationContext)) yield return x;
    yield break;
}

What do you think? Which one is better ?

I've solved it right now by creating partial class with BaseValidate method implemented in the .cs file outside of auto generated Models folder.
I do not like it since it requires new files to be created manually for the new Models inheritance.

Regards

xavierhd added a commit to xavierhd/swagger-codegen that referenced this issue Dec 10, 2020
…yModel to True.

This change enable the modelGeneric.mustache templates to distinguish between generated type and native dictionary type.
"BaseValidate" reference is no longer incorrectly generated in IValidatableObject.Validate().
"Override" keyword is no longer added to the `ToJson()` method.
@smargoli2
Copy link

Please merge PR #10819 to fix this!

@daveloveitk
Copy link

Just want to +1 that this is still an existing issue and a fix would be appreciated.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

9 participants