question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Configure non-nullable types as required

See original GitHub issue

In my project we do not distinguish between required and nullable: false. If a type is non-nullable, it is also required. This is regardless if it is a value type or reference type.

It would be great if one could optionally configure Swashbuckle to set all non-nullable properties to required. E.g. like: setupAction.MarkNonNullableTypesAsRequired(); This way, I could remove all my [Required] annotations on the non-nullable C# properties.

This is a subsequent request following #1686. As _originally posted by @felschr in https://github.com/domaindrivendev/Swashbuckle.AspNetCore/issues/1686#issuecomment-674074694_ , treating non-nullable as required is the default for nullable contexts in .NET validation.

Issue Analytics

  • State:open
  • Created 3 years ago
  • Reactions:50
  • Comments:11

github_iconTop GitHub Comments

9reactions
josundtcommented, Oct 27, 2022

With C# 11.0/.NET 7.0, the required keyword is being introduced for properties. Properties with this keyword needs to be initialized through the object initializer when the class/struct/record is initialized from code.

But required properties also affects the behavior of System.Text.Json 7.x deserialization and thereby aspnetcore model validation.

The default behavior for System.Text.Json deserialization / aspnetcore model validation in .NET 7.0 is as follows.

Nullable/not required properties:

  • Property CAN be null, and property CAN be omitted from JSON payload.

Nullable/required properties:

  • Property CAN be null, but property CAN NOT be omitted from JSON payload.

Not nullable/not required properties:

  • Property CAN NOT be null, but property CAN NOT be omitted from JSON payload (since it implies null).

Not nullable/required properties:

  • Property CAN NOT be null, and property CAN NOT be omitted from JSON payload.

Since nullablility and required/not are different things where one does not necessarily imply the other, I think SwasBuckle should use the C# property nullability for swagger property nullable, and C# property required/not for the swagger property required.

If the C# property is annotated with RequiredAttribute, I think this should override the above, and set both swagger nullable/required to true.

References:

8reactions
flibustier7seascommented, Aug 6, 2021

@JosNun I’m using the following workaround:

class RequiredNotNullableSchemaFilter : ISchemaFilter
{
    public void Apply(OpenApiSchema schema, SchemaFilterContext context)
    {
        if (schema.Properties == null)
        {
            return;
        }

        FixNullableProperties(schema, context);

        var notNullableProperties = schema
            .Properties
            .Where(x => !x.Value.Nullable && !schema.Required.Contains(x.Key))
            .ToList();

        foreach (var property in notNullableProperties)
        {
            schema.Required.Add(property.Key);
        }
    }

    /// <summary>
    /// Option "SupportNonNullableReferenceTypes" not working with complex types ({ "type": "object" }), 
    /// so they always have "Nullable = false",
    /// see method "SchemaGenerator.GenerateSchemaForMember"
    /// </summary>
    private static void FixNullableProperties(OpenApiSchema schema, SchemaFilterContext context)
    {
        foreach (var property in schema.Properties)
        {
            if (property.Value.Reference != null)
            {
                var field = context.Type
                    .GetMembers(BindingFlags.Public | BindingFlags.Instance)
                    .FirstOrDefault(x =>
                        string.Equals(x.Name, property.Key, StringComparison.InvariantCultureIgnoreCase));

                if (field != null)
                {
                    var fieldType = field switch
                    {
                        FieldInfo fieldInfo => fieldInfo.FieldType,
                        PropertyInfo propertyInfo => propertyInfo.PropertyType,
                        _ => throw new NotSupportedException(),
                    };

                    property.Value.Nullable = fieldType.IsValueType
                        ? Nullable.GetUnderlyingType(fieldType) != null
                        : !field.IsNonNullableReferenceType();
                }
            }
        }
    }    
}

Result:

{
  "User": {
    "required": ["email", "firstName", "id", "lastName"],
    "type": "object",
    "properties": {
      "id": {
        "type": "string",
        "format": "uuid"
      },
      "organizationId": {
        "type": "string",
        "format": "uuid",
        "nullable": true
      },
      "firstName": {
        "type": "string"
      },
      "middleName": {
        "type": "string",
        "nullable": true
      },
      "lastName": {
        "type": "string"
      },
      "email": {
        "$ref": "#/components/schemas/UserEmail"
      },
      "phone": {
        "$ref": "#/components/schemas/UserPhone"
      }
    },
    "additionalProperties": false
  }
}
Read more comments on GitHub >

github_iconTop Results From Across the Web

ASP.NET Core [Require] non-nullable types
Solution working with json requests. You cannot validate an already created model instance, because a non-nullable property has always a ...
Read more >
Resolve Non-nullable Property Must Contain a Non-null ...
Initialize non-nullable properties; Change the type to be nullable; Disable the warning; Use the null forgiving operator; Use the required ...
Read more >
Working with nullable reference types - EF Core
Collection navigations, which contain references to multiple related entities, should always be non-nullable. An empty collection means that no ...
Read more >
Solution - Non-nullable Property Must Contain a Non-null ...
Non -nullable property must contain a non-null value when exiting constructor. Consider declaring the property as nullable.
Read more >
Improving non-nullable reference types handling
Consider declaring as nullable. This rule enforces on us mandatory field initialization to guarantee non-nullable value, which can be satisfied ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found