RicoSuter / NJsonSchema

JSON Schema reader, generator and validator for .NET
http://NJsonSchema.org
MIT License
1.38k stars 532 forks source link

Retain data validation annotation attributes in model generation #1011

Open cbordeman opened 7 years ago

cbordeman commented 7 years ago

Attributes such as [Required], [Range], [StringLength(5)] from the System.ComponentModel.DataAnnotations namespace should be retained in the generated client side models so validation can be performed.

RicoSuter commented 7 years ago

Good idea. However this is an NJsonSchema issue, can you create one on http://njsonschema.org?

jonnybi commented 7 years ago

:thumbsup: waiting for this too

cbordeman commented 7 years ago

I don't see how this is an NJsonSchema issue, since it involves scanning the webapi compiled assembly, which I believe is done by NSwagStudio.

RicoSuter commented 7 years ago

DTO classes and interface are generated by njsonschema...

cbordeman commented 7 years ago

NSwagStudio has the option to scan a dll and extract c# attributes, and that code appears to be in NSwagStudio. So doesn't part of the implementation need to reside in NSwagStudio ?

jelical commented 7 years ago

NJsonSchema includes proper defs for validation. "RegistrationViewModel": { "type": "object", "additionalProperties": false, "required": [ "FirstName", "LastName" ], "properties": { "UserName": { "type": "string", "format": "email", "maxLength": 60 }, "FirstName": { "type": "string", "maxLength": 140 }, "LastName": { "type": "string", "maxLength": 140 }, "Password": { "type": "string" } },

But there are no manifestation of this in generated models for TypeScript

RicoSuter commented 7 years ago

There are no commonly available attributes for typescript... what exactly would you expect?

jelical commented 7 years ago

Ideally, some kind of optional extensibility mechanism to obtain result like here. I am not speaking about integrating with this particular library, but support of some kind of map between NJsonSchema validation metadata attributes and TS decorators.

adamlubek commented 6 years ago

it would be good to even have these available as constant values so they can be passed to client side validation mechanism e.g. if type had a property/constant containing value of StringLength attribute, then I could use that in angular reactive form validators. This way I could keep API and client in sync

berhir commented 6 years ago

We are also looking for a way to use the validation values from the swagger definition in angular reactive form validators. The solution suggested by @adamlubek to have it available as constant values would work for us.

swagger-ts-generator creates a FormGroup for each model. But most of the time we don't have a 1:1 mapping of the DTO in the UI, so for us this is not so helpful.

For our scenario it would be nice to have a constant for each field with an array of the generated reactive form validators. But to have at least the values would be a good start.

adamlubek commented 5 years ago

apologies for shameless plug but I created npm package for getting typescript validation constants from c# dll, maybe it would help someone on c#/typescript stack. https://www.npmjs.com/package/csharp-data-annotations-parser

blasky commented 5 years ago

Has there been any movement on this issue, either on the NSwag or NJsonSchema side of things?...i.e. some sort of exposure of the relevant annotations in the generated models such that some other code can make use of them?

cbordeman commented 5 years ago

NJsonSchema already supports standard data validation attributes in the generated schema, as someone indicated. I don't know if NSwag uses them yet.

RicoSuter commented 5 years ago

NSwag uses NJS for DTOs so this should work. But there is a setting to disable that, maybe it’s switched off?

blasky commented 5 years ago

Good news. Thanks for the quick reply. I will investigate and share if I find it.

But are you saying there may be a config setting written out to the *.nswag configuration document (...which appears to drive the swaggerToTypeScriptClient execution)? Or a setting in one of the NJsonSchema xml config documents to tweak?

And any idea what I would be looking for in the resultant TypeScript service code upon success? Do we think this should show up as info Decorators on the TypeScript object class?

RicoSuter commented 5 years ago

Validation and data annotations are only supported in the c# output

blasky commented 5 years ago

OK. So this remains an open issue for the TypeScript client code, which currently receives no annotation info from the C# source object. Is this on the road map for NSwag or NJsonSchema.CodeGeneration.TypeScript (...wherever the ultimate solution resides)?

Thanks. Just trying to understand and evaluate the tool and feature set at this time.

RicoSuter commented 5 years ago

@blasky currently not planned, moved to NJS.

andrewmorris-dev commented 5 years ago

Attributes such as [Range], [Required], [StringLength] are being generated, but I'm not seeing the [Display(Name = "Field Name")] in the generated c# code?

RicoSuter commented 5 years ago

We cannot retain everything via json schema/openapi/swagger because these fields do not really exist there.. some of them are generated as xml docs i think

andrewmorris-dev commented 5 years ago

would it be possible to generate a [System.ComponentModel.DataAnnotations.DisplayName(Name = "")] annotation in the c# httpclient via the xml docs perhaps?

I see [MaxLength(15)] in my dto is able to generate a [System.ComponentModel.DataAnnotations.StringLength(15, MinimumLength = 1)] in my http generate c# client.

I also notice that if I set the description on the [Display] attribute, it will populate a comment of the value. For example in my dto I set:

[Display(Description = "Total Price")]
public decimal TotalPrice { get; set; }

and in the generated client, it comes across as:

/// <summary>Total Price</summary>
[Newtonsoft.Json.JsonProperty("totalPrice", Required = Newtonsoft.Json.Required.Always)]
public decimal TotalPrice { get; set; }

it seems the description part of the [Display] is available, could this be used to pass this information down to the generated c# client as a [Display] attribute?

It would be great if it was able to render the code as [System.ComponentModel.DataAnnotations.Display(Description = "Total Price")] inside the c# generated client instead.

andrewmorris-dev commented 5 years ago

Just something else to add. When adding the Name of the [Display] attribute, looking at the json that get's generated, it sets the value against a title param. For example, in my dto I add

        [Required]
        [Range(1.9, 3.9)]
        [Display(Name = "Total Price", Description = "The total price of the idea")]
        public decimal TotalPrice { get; set; }

which renders the following:

model

Is there a way to have the C# generated client, use the title value of the property, in this case totalPrice, as a [System.ComponentModel.DataAnnotations.Display(Name = "Total Price")]?

I'd be willing to help with this matter if needed, but am pretty new to this kind of thing and not sure how to go about it or get started? I do see some kind of annotation template, but it's empty and not sure how I would use it?

andrewmorris-dev commented 5 years ago

Hi @RicoSuter

Just wondering what you're thoughts are on the items I mentioned above last week and if you think it can work?

Thanks again

andrewmorris-dev commented 5 years ago

@RicoSuter