NSwag icon indicating copy to clipboard operation
NSwag copied to clipboard

Generator option to use .NET built-in ProblemDetails type

Open GuyLescalier opened this issue 5 years ago • 10 comments

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.

GuyLescalier avatar Apr 09 '21 10:04 GuyLescalier

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).

RicoSuter avatar Apr 09 '21 11:04 RicoSuter

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.

GuyLescalier avatar Apr 09 '21 12:04 GuyLescalier

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

RicoSuter avatar Apr 09 '21 14:04 RicoSuter

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.

GuyLescalier avatar Apr 14 '21 12:04 GuyLescalier

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.

RicoSuter avatar Apr 15 '21 07:04 RicoSuter

@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?

ViRuSTriNiTy avatar Feb 28 '23 16:02 ViRuSTriNiTy

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.

StuffOfInterest avatar Apr 11 '23 14:04 StuffOfInterest

+1

werebear73 avatar Jun 18 '24 21:06 werebear73

@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?

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.

leopowershield avatar Jul 01 '24 22:07 leopowershield

@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?

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.

werebear73-tritelph avatar Jul 02 '24 18:07 werebear73-tritelph