Generator option to use .NET built-in ProblemDetails type
NSwag C# client generator creates a class for every schema in OpenAPI documentation. This prevents implementing a generic exception handler based on MyException<ProblemDetails> as ProblemDetails is a different class for each client even in the same solution. A work around is to consider it a MyException and deserialize the content of the response property which is not a very elegant solution. The solution would be adding a parameter to the generator so that it uses the built-in type (Microsoft.AspNetCore.Mvc.ProblemDetails) instead of generating a new one. That way you can still use a generated class if the schema isn't compatible with the built-in type.
There is a configuration where you can specify class names which are not generated and then you provide them yourself (eg in the same namespace).
Nice ! I found the AdditionalNamespaceUsages in CSharpGeneratorBaseSettings which will allow me to add additinal "using" clauses. But I can't seem to find the parameter to specify the classes to exclude from generation.
https://github.com/RicoSuter/NJsonSchema/blob/1d00dc5675a10835f274db953693f63357846da3/src/NJsonSchema.CodeGeneration/CodeGeneratorSettingsBase.cs#L30
(CSharpGeneratorSettings inherits from this) which is part of https://github.com/RicoSuter/NSwag/blob/master/src/NSwag.CodeGeneration.CSharp/CSharpGeneratorBaseSettings.cs#L46
It works great ! Thanks for your help :)
For future readers, this is what I ended up doing :
- Add the following parameters to the command line : /ExcludedTypeNames:ProblemDetails /AdditionalNamespaceUsages:Microsoft.AspNetCore.Mvc
- Create a partial class for the generated client with the "UpdateJsonSerializerSettings" method wich allows to customize Newtonsoft serialization settings : settings.Converters.Add(new ProblemDetailsConverter());
- The converters for ProblemDetails and ValidationProblemDetails are available in this NuGet package : Microsoft.AspNetCore.Mvc.NewtonsoftJson
- Catch a SwaggerException<ProblemDetails> and get the ProblemDetails in the Result property
The only thing I'd like to do now is find a way to customize serialization settings without having to create a partial class which needs to be created per client. Maybe with inheritence and DI and IOption pattern.
The only thing I'd like to do now is find a way to customize serialization settings without having to create a partial class which needs to be created per client.
I think there is an option to define a common base class - define that and implement it and you do not need a partial class per client class.
@GuyLescalier Actually, you don't need a depenency to Microsoft.AspNetCore.Mvc because NSwag generates a ProblemDetails type with all the necessary JSON attributes when an action is annoted with
[ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status422UnprocessableEntity)] // <-- use ProblemDetails here
public ActionResult MyAction(
{
...
}
But there is a catch: NSwag generates a Extensions property in the generated class ProblemDetails with some required attributes. This results in deserialization errors because ProblemDetails is serialized as JSON object with a missing extensions field. I currently handle this by removing the property from the generated code via RegEx. Pretty hacky but I cannot find a way to tell the serialization process to exclude the Extensions property.
@RicoSuter Is there an option to control the generation of ProblemDetails, in this case excluding the Extensions property?
The issue with the required "Extensions" property has been biting me as well. I wanted to return a simple "NotFound" response and the consuming client always blows up when trying to deserialize the ProblemDetails type.
+1
@GuyLescalier Actually, you don't need a depenency to
Microsoft.AspNetCore.MvcbecauseNSwaggenerates aProblemDetailstype with all the necessary JSON attributes when an action is annoted with[ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status422UnprocessableEntity)] // <-- use ProblemDetails here public ActionResult MyAction( { ... }But there is a catch:
NSwaggenerates aExtensionsproperty in the generated classProblemDetailswith some required attributes. This results in deserialization errors becauseProblemDetailsis serialized as JSON object with a missingextensionsfield. I currently handle this by removing the property from the generated code viaRegEx. Pretty hacky but I cannot find a way to tell the serialization process to exclude theExtensionsproperty.@RicoSuter Is there an option to control the generation of
ProblemDetails, in this case excluding theExtensionsproperty?
I am getting the same issue. Is there a solution for that? I've spent a lot of time on it, but, no success so far.
@GuyLescalier Actually, you don't need a depenency to
Microsoft.AspNetCore.MvcbecauseNSwaggenerates aProblemDetailstype with all the necessary JSON attributes when an action is annoted with[ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status422UnprocessableEntity)] // <-- use ProblemDetails here public ActionResult MyAction( { ... }But there is a catch:
NSwaggenerates aExtensionsproperty in the generated classProblemDetailswith some required attributes. This results in deserialization errors becauseProblemDetailsis serialized as JSON object with a missingextensionsfield. I currently handle this by removing the property from the generated code viaRegEx. Pretty hacky but I cannot find a way to tell the serialization process to exclude theExtensionsproperty. @RicoSuter Is there an option to control the generation ofProblemDetails, in this case excluding theExtensionsproperty?I am getting the same issue. Is there a solution for that? I've spent a lot of time on it, but, no success so far.
Agreed, but I have observed that when you have more than one Connected Service, it doesn't create them for all the services.