Update Swashbuckle.AspNetCore Version from version"4.0.1" to "6.2.3"
Tags: c, swagger, netcore, netframework
Published: 2022-05-13 06:51:16

Hi there. 
I had an interesting task: to update the Swashbuckle.AspNetCore version from "4.0.1" to "6.2.3". It looked very simple but it was not what it looked like.
The main problem was breaking changes which happened when passing from version 4 to version [5](https://github.com/domaindrivendev/Swashbuckle.AspNetCore/releases/tag/v5.0.0). Swashbuckle.AspNetCore began to use Swagger/OpenAPI [version v3](https://swagger.io/specification/) instead of OpenAPI v2. The project makes use of NSwag to generate httpClient for getting data from another microservice. Any attempt to regenerate auto generated code changed it after updating Swashbuckle.AspNetCore version. These caused a lot of build errors. I should have decreased differencies between the new code and old one.
Main difference which cause incompatibility in the project were:

- Autogenerated method names were changed. The previous format was, for example, "AddPersonalTaskV2Async" (it was a controller class method name). New auto generated names became "V2Async". There were a lot of such changes, it seemed impossible to change all method calls by hand. A better decision was to add CustomOperationIds to services.AddSwaggerGen. In my case:

```
services.AddSwaggerGen(c =>
            {
                c.SwaggerDoc("v1", new OpenApiInfo {Title = "title", Version = "v1"});
                c.CustomOperationIds(apiDesc =>
                    apiDesc.TryGetMethodInfo(out MethodInfo methodInfo) ? methodInfo.Name : null);
            });
```

- There were no changes in names of parameters with attribute [FromUri]. But all parameters with attribute [FromBody] changed their names to body. As described in the [spec](https://swagger.io/specification/) [FromUri] is aligned with Operation Object => parameters, but [FromBody] is Operation Object => requestBody. There is no field "name" in Request Body Object.

- Parameter order was changed. Before the order was the same as in method declaration. By now [FromUri] goes earlier than [FromBody]. It doesn't matter what you have coded in method declaration.

- If you use JObject as a request parameter, you will be in for an unpleasant surprise. NSWag changes JObject to System.Collections.Generic.Dictionary<string, JToken>. If you are disagree, it will be better to code custom realization of ISchemaFilter like this:

```
public class JObjectSchemaFilter : ISchemaFilter
    {
        public void Apply(OpenApiSchema schema, SchemaFilterContext context)
        {
            if (context.Type != typeof(JObject)) return;
            schema.Type = "object";
            schema.AdditionalProperties = null;
        }
    }
```

- Another change has affected Enums. Enum fields names don't be the same as in your code. They are changed to figures 1,2, ..., n. To fix this singularity it should be created another custom realization of ISchemaFilter:

```
public class EnumSchemaFilter : ISchemaFilter
    {
        public void Apply(OpenApiSchema schema, SchemaFilterContext context)
        {
            if (!context.Type.IsEnum) return;

            var fields = context.Type.GetFields(BindingFlags.Static | BindingFlags.Public);

            schema.Enum = fields.Select(field => new OpenApiString(field.Name)).Cast<IOpenApiAny>().ToList();
            schema.Type = "string";
            schema.Properties = null;
            schema.AllOf = null;
        }
    }
```

- The last thing I should mention: some fields of custom request objects suddenly have an attribute [Required]. I'm not sure that I coded the best decision, but this worked:

```
public class SettingsSchemaFilter : ISchemaFilter
    {
        public void Apply(OpenApiSchema schema, SchemaFilterContext context)
        {
            if (context.Type != typeof(Settings)) return;
            if (schema.Required == null || schema.Required.Count == 0)
            {
                schema.Nullable = true;
            }
        }
    }
```
It's all changes that I faced.