@@ -411,6 +411,236 @@ await VerifyOpenApiDocument(builder, document =>
411
411
} ) ;
412
412
}
413
413
414
+ [ Fact ]
415
+ public async Task GetOpenApiSchema_Base64StringAttribute_StringProperties ( )
416
+ {
417
+ var builder = CreateBuilder ( ) ;
418
+ builder . MapPost ( "/api" , ( PropertiesWithDataAnnotations model ) => { } ) ;
419
+
420
+ await VerifyOpenApiDocument ( builder , document =>
421
+ {
422
+ var schema = document . Paths [ "/api" ] . Operations [ HttpMethod . Post ] . RequestBody . Content . First ( ) . Value . Schema ;
423
+ var nonNullable = schema . Properties [ "base64StringValue" ] ;
424
+ var nullable = schema . Properties [ "nullableBase64StringValue" ] ;
425
+ Assert . Equal ( JsonSchemaType . String , nonNullable . Type ) ;
426
+ Assert . Equal ( "byte" , nonNullable . Format ) ;
427
+ Assert . Equal ( JsonSchemaType . String | JsonSchemaType . Null , nullable . Type ) ;
428
+ Assert . Equal ( "byte" , nullable . Format ) ;
429
+ } ) ;
430
+ }
431
+
432
+ [ Fact ]
433
+ public async Task GetOpenApiSchema_RangeAttribute_IntProperties ( )
434
+ {
435
+ var builder = CreateBuilder ( ) ;
436
+ builder . MapPost ( "/api" , ( PropertiesWithDataAnnotations model ) => { } ) ;
437
+
438
+ await VerifyOpenApiDocument ( builder , document =>
439
+ {
440
+ var schema = document . Paths [ "/api" ] . Operations [ HttpMethod . Post ] . RequestBody . Content . First ( ) . Value . Schema ;
441
+ var nonNullable = schema . Properties [ "rangeIntValue" ] ;
442
+ var nullable = schema . Properties [ "nullableRangeIntValue" ] ;
443
+ Assert . Equal ( JsonSchemaType . Integer , nonNullable . Type ) ;
444
+ Assert . Equal ( "int32" , nonNullable . Format ) ;
445
+ Assert . Equal ( "1" , nonNullable . Minimum ) ;
446
+ Assert . Equal ( "100" , nonNullable . Maximum ) ;
447
+ Assert . Equal ( JsonSchemaType . Integer | JsonSchemaType . Null , nullable . Type ) ;
448
+ Assert . Equal ( "int32" , nullable . Format ) ;
449
+ Assert . Equal ( "1" , nullable . Minimum ) ;
450
+ Assert . Equal ( "100" , nullable . Maximum ) ;
451
+ } ) ;
452
+ }
453
+
454
+ [ Fact ]
455
+ public async Task GetOpenApiSchema_RangeAttribute_DoubleProperties ( )
456
+ {
457
+ var builder = CreateBuilder ( ) ;
458
+ builder . MapPost ( "/api" , ( PropertiesWithDataAnnotations model ) => { } ) ;
459
+
460
+ await VerifyOpenApiDocument ( builder , document =>
461
+ {
462
+ var schema = document . Paths [ "/api" ] . Operations [ HttpMethod . Post ] . RequestBody . Content . First ( ) . Value . Schema ;
463
+ var nonNullable = schema . Properties [ "rangeDoubleValue" ] ;
464
+ var nullable = schema . Properties [ "nullableRangeDoubleValue" ] ;
465
+ Assert . Equal ( JsonSchemaType . Number , nonNullable . Type ) ;
466
+ Assert . Equal ( "double" , nonNullable . Format ) ;
467
+ Assert . Equal ( "0.1" , nonNullable . Minimum as string ) ;
468
+ Assert . Equal ( "99.9" , nonNullable . Maximum as string ) ;
469
+ Assert . Equal ( JsonSchemaType . Number | JsonSchemaType . Null , nullable . Type ) ;
470
+ Assert . Equal ( "double" , nullable . Format ) ;
471
+ Assert . Equal ( "0.1" , nullable . Minimum as string ) ;
472
+ Assert . Equal ( "99.9" , nullable . Maximum as string ) ;
473
+ } ) ;
474
+ }
475
+
476
+ [ Fact ]
477
+ public async Task GetOpenApiSchema_RegularExpressionAttribute_StringProperties ( )
478
+ {
479
+ var builder = CreateBuilder ( ) ;
480
+ builder . MapPost ( "/api" , ( PropertiesWithDataAnnotations model ) => { } ) ;
481
+
482
+ await VerifyOpenApiDocument ( builder , document =>
483
+ {
484
+ var schema = document . Paths [ "/api" ] . Operations [ HttpMethod . Post ] . RequestBody . Content . First ( ) . Value . Schema ;
485
+ var nonNullable = schema . Properties [ "regexStringValue" ] ;
486
+ var nullable = schema . Properties [ "nullableRegexStringValue" ] ;
487
+ Assert . Equal ( JsonSchemaType . String , nonNullable . Type ) ;
488
+ Assert . Equal ( "^[A-Z]{3}$" , nonNullable . Pattern ) ;
489
+ Assert . Equal ( JsonSchemaType . String | JsonSchemaType . Null , nullable . Type ) ;
490
+ Assert . Equal ( "^[A-Z]{3}$" , nullable . Pattern ) ;
491
+ } ) ;
492
+ }
493
+
494
+ [ Fact ]
495
+ public async Task GetOpenApiSchema_MaxLengthAttribute_StringProperties ( )
496
+ {
497
+ var builder = CreateBuilder ( ) ;
498
+ builder . MapPost ( "/api" , ( PropertiesWithDataAnnotations model ) => { } ) ;
499
+
500
+ await VerifyOpenApiDocument ( builder , document =>
501
+ {
502
+ var schema = document . Paths [ "/api" ] . Operations [ HttpMethod . Post ] . RequestBody . Content . First ( ) . Value . Schema ;
503
+ var nonNullable = schema . Properties [ "maxLengthStringValue" ] ;
504
+ var nullable = schema . Properties [ "nullableMaxLengthStringValue" ] ;
505
+ Assert . Equal ( JsonSchemaType . String , nonNullable . Type ) ;
506
+ Assert . Equal ( 10 , nonNullable . MaxLength ) ;
507
+ Assert . Equal ( JsonSchemaType . String | JsonSchemaType . Null , nullable . Type ) ;
508
+ Assert . Equal ( 10 , nullable . MaxLength ) ;
509
+ } ) ;
510
+ }
511
+
512
+ [ Fact ]
513
+ public async Task GetOpenApiSchema_MaxLengthAttribute_ArrayProperties ( )
514
+ {
515
+ var builder = CreateBuilder ( ) ;
516
+ builder . MapPost ( "/api" , ( PropertiesWithDataAnnotations model ) => { } ) ;
517
+
518
+ await VerifyOpenApiDocument ( builder , document =>
519
+ {
520
+ var schema = document . Paths [ "/api" ] . Operations [ HttpMethod . Post ] . RequestBody . Content . First ( ) . Value . Schema ;
521
+ var nonNullable = schema . Properties [ "maxLengthArrayValue" ] ;
522
+ var nullable = schema . Properties [ "nullableMaxLengthArrayValue" ] ;
523
+ Assert . Equal ( JsonSchemaType . Array , nonNullable . Type ) ;
524
+ Assert . Equal ( 5 , nonNullable . MaxItems ) ;
525
+ Assert . Equal ( JsonSchemaType . Array | JsonSchemaType . Null , nullable . Type ) ;
526
+ Assert . Equal ( 5 , nullable . MaxItems ) ;
527
+ } ) ;
528
+ }
529
+
530
+ [ Fact ]
531
+ public async Task GetOpenApiSchema_MinLengthAttribute_StringProperties ( )
532
+ {
533
+ var builder = CreateBuilder ( ) ;
534
+ builder . MapPost ( "/api" , ( PropertiesWithDataAnnotations model ) => { } ) ;
535
+
536
+ await VerifyOpenApiDocument ( builder , document =>
537
+ {
538
+ var schema = document . Paths [ "/api" ] . Operations [ HttpMethod . Post ] . RequestBody . Content . First ( ) . Value . Schema ;
539
+ var nonNullable = schema . Properties [ "minLengthStringValue" ] ;
540
+ var nullable = schema . Properties [ "nullableMinLengthStringValue" ] ;
541
+ Assert . Equal ( JsonSchemaType . String , nonNullable . Type ) ;
542
+ Assert . Equal ( 3 , nonNullable . MinLength ) ;
543
+ Assert . Equal ( JsonSchemaType . String | JsonSchemaType . Null , nullable . Type ) ;
544
+ Assert . Equal ( 3 , nullable . MinLength ) ;
545
+ } ) ;
546
+ }
547
+
548
+ [ Fact ]
549
+ public async Task GetOpenApiSchema_MinLengthAttribute_ArrayProperties ( )
550
+ {
551
+ var builder = CreateBuilder ( ) ;
552
+ builder . MapPost ( "/api" , ( PropertiesWithDataAnnotations model ) => { } ) ;
553
+
554
+ await VerifyOpenApiDocument ( builder , document =>
555
+ {
556
+ var schema = document . Paths [ "/api" ] . Operations [ HttpMethod . Post ] . RequestBody . Content . First ( ) . Value . Schema ;
557
+ var nonNullable = schema . Properties [ "minLengthArrayValue" ] ;
558
+ var nullable = schema . Properties [ "nullableMinLengthArrayValue" ] ;
559
+ Assert . Equal ( JsonSchemaType . Array , nonNullable . Type ) ;
560
+ Assert . Equal ( 2 , nonNullable . MinItems ) ;
561
+ Assert . Equal ( JsonSchemaType . Array | JsonSchemaType . Null , nullable . Type ) ;
562
+ Assert . Equal ( 2 , nullable . MinItems ) ;
563
+ } ) ;
564
+ }
565
+
566
+ [ Fact ]
567
+ public async Task GetOpenApiSchema_LengthAttribute_StringProperties ( )
568
+ {
569
+ var builder = CreateBuilder ( ) ;
570
+ builder . MapPost ( "/api" , ( PropertiesWithDataAnnotations model ) => { } ) ;
571
+
572
+ await VerifyOpenApiDocument ( builder , document =>
573
+ {
574
+ var schema = document . Paths [ "/api" ] . Operations [ HttpMethod . Post ] . RequestBody . Content . First ( ) . Value . Schema ;
575
+ var nonNullable = schema . Properties [ "lengthStringValue" ] ;
576
+ var nullable = schema . Properties [ "nullableLengthStringValue" ] ;
577
+ Assert . Equal ( JsonSchemaType . String , nonNullable . Type ) ;
578
+ Assert . Equal ( 2 , nonNullable . MinLength ) ;
579
+ Assert . Equal ( 8 , nonNullable . MaxLength ) ;
580
+ Assert . Equal ( JsonSchemaType . String | JsonSchemaType . Null , nullable . Type ) ;
581
+ Assert . Equal ( 2 , nullable . MinLength ) ;
582
+ Assert . Equal ( 8 , nullable . MaxLength ) ;
583
+ } ) ;
584
+ }
585
+
586
+ [ Fact ]
587
+ public async Task GetOpenApiSchema_LengthAttribute_ArrayProperties ( )
588
+ {
589
+ var builder = CreateBuilder ( ) ;
590
+ builder . MapPost ( "/api" , ( PropertiesWithDataAnnotations model ) => { } ) ;
591
+
592
+ await VerifyOpenApiDocument ( builder , document =>
593
+ {
594
+ var schema = document . Paths [ "/api" ] . Operations [ HttpMethod . Post ] . RequestBody . Content . First ( ) . Value . Schema ;
595
+ var nonNullable = schema . Properties [ "lengthArrayValue" ] ;
596
+ var nullable = schema . Properties [ "nullableLengthArrayValue" ] ;
597
+ Assert . Equal ( JsonSchemaType . Array , nonNullable . Type ) ;
598
+ Assert . Equal ( 1 , nonNullable . MinItems ) ;
599
+ Assert . Equal ( 4 , nonNullable . MaxItems ) ;
600
+ Assert . Equal ( JsonSchemaType . Array | JsonSchemaType . Null , nullable . Type ) ;
601
+ Assert . Equal ( 1 , nullable . MinItems ) ;
602
+ Assert . Equal ( 4 , nullable . MaxItems ) ;
603
+ } ) ;
604
+ }
605
+
606
+ [ Fact ]
607
+ public async Task GetOpenApiSchema_UrlAttribute_StringProperties ( )
608
+ {
609
+ var builder = CreateBuilder ( ) ;
610
+ builder . MapPost ( "/api" , ( PropertiesWithDataAnnotations model ) => { } ) ;
611
+
612
+ await VerifyOpenApiDocument ( builder , document =>
613
+ {
614
+ var schema = document . Paths [ "/api" ] . Operations [ HttpMethod . Post ] . RequestBody . Content . First ( ) . Value . Schema ;
615
+ var nonNullable = schema . Properties [ "urlStringValue" ] ;
616
+ var nullable = schema . Properties [ "nullableUrlStringValue" ] ;
617
+ Assert . Equal ( JsonSchemaType . String , nonNullable . Type ) ;
618
+ Assert . Equal ( "uri" , nonNullable . Format ) ;
619
+ Assert . Equal ( JsonSchemaType . String | JsonSchemaType . Null , nullable . Type ) ;
620
+ Assert . Equal ( "uri" , nullable . Format ) ;
621
+ } ) ;
622
+ }
623
+
624
+ [ Fact ]
625
+ public async Task GetOpenApiSchema_StringLengthAttribute_StringProperties ( )
626
+ {
627
+ var builder = CreateBuilder ( ) ;
628
+ builder . MapPost ( "/api" , ( PropertiesWithDataAnnotations model ) => { } ) ;
629
+
630
+ await VerifyOpenApiDocument ( builder , document =>
631
+ {
632
+ var schema = document . Paths [ "/api" ] . Operations [ HttpMethod . Post ] . RequestBody . Content . First ( ) . Value . Schema ;
633
+ var nonNullable = schema . Properties [ "stringLengthValue" ] ;
634
+ var nullable = schema . Properties [ "nullableStringLengthValue" ] ;
635
+ Assert . Equal ( JsonSchemaType . String , nonNullable . Type ) ;
636
+ Assert . Equal ( 5 , nonNullable . MinLength ) ;
637
+ Assert . Equal ( 20 , nonNullable . MaxLength ) ;
638
+ Assert . Equal ( JsonSchemaType . String | JsonSchemaType . Null , nullable . Type ) ;
639
+ Assert . Equal ( 5 , nullable . MinLength ) ;
640
+ Assert . Equal ( 20 , nullable . MaxLength ) ;
641
+ } ) ;
642
+ }
643
+
414
644
#nullable enable
415
645
private class NullablePropertiesTestModel
416
646
{
@@ -452,5 +682,72 @@ private class NullablePropertiesWithValidationModel
452
682
[ Description ( "A description field" ) ]
453
683
public string ? NullableDescription { get ; set ; }
454
684
}
685
+
686
+ private class PropertiesWithDataAnnotations
687
+ {
688
+ // Base64StringAttribute
689
+ [ Base64String ]
690
+ public string Base64StringValue { get ; set ; } = string . Empty ;
691
+ [ Base64String ]
692
+ public string ? NullableBase64StringValue { get ; set ; }
693
+
694
+ // RangeAttribute
695
+ [ Range ( 1 , 100 ) ]
696
+ public int RangeIntValue { get ; set ; } = 0 ;
697
+ [ Range ( 1 , 100 ) ]
698
+ public int ? NullableRangeIntValue { get ; set ; }
699
+ [ Range ( 0.1 , 99.9 ) ]
700
+ public double RangeDoubleValue { get ; set ; } = 0.0 ;
701
+ [ Range ( 0.1 , 99.9 ) ]
702
+ public double ? NullableRangeDoubleValue { get ; set ; }
703
+
704
+ // RegularExpressionAttribute
705
+ [ RegularExpression ( @"^[A-Z]{3}$" ) ]
706
+ public string RegexStringValue { get ; set ; } = string . Empty ;
707
+ [ RegularExpression ( @"^[A-Z]{3}$" ) ]
708
+ public string ? NullableRegexStringValue { get ; set ; }
709
+
710
+ // MaxLengthAttribute
711
+ [ MaxLength ( 10 ) ]
712
+ public string MaxLengthStringValue { get ; set ; } = string . Empty ;
713
+ [ MaxLength ( 10 ) ]
714
+ public string ? NullableMaxLengthStringValue { get ; set ; }
715
+ [ MaxLength ( 5 ) ]
716
+ public int [ ] MaxLengthArrayValue { get ; set ; } = [ ] ;
717
+ [ MaxLength ( 5 ) ]
718
+ public int [ ] ? NullableMaxLengthArrayValue { get ; set ; }
719
+
720
+ // MinLengthAttribute
721
+ [ MinLength ( 3 ) ]
722
+ public string MinLengthStringValue { get ; set ; } = string . Empty ;
723
+ [ MinLength ( 3 ) ]
724
+ public string ? NullableMinLengthStringValue { get ; set ; }
725
+ [ MinLength ( 2 ) ]
726
+ public int [ ] MinLengthArrayValue { get ; set ; } = [ ] ;
727
+ [ MinLength ( 2 ) ]
728
+ public int [ ] ? NullableMinLengthArrayValue { get ; set ; }
729
+
730
+ // LengthAttribute (custom, if available)
731
+ [ Length ( 2 , 8 ) ]
732
+ public string LengthStringValue { get ; set ; } = string . Empty ;
733
+ [ Length ( 2 , 8 ) ]
734
+ public string ? NullableLengthStringValue { get ; set ; }
735
+ [ Length ( 1 , 4 ) ]
736
+ public int [ ] LengthArrayValue { get ; set ; } = [ ] ;
737
+ [ Length ( 1 , 4 ) ]
738
+ public int [ ] ? NullableLengthArrayValue { get ; set ; }
739
+
740
+ // UrlAttribute
741
+ [ Url ]
742
+ public string UrlStringValue { get ; set ; } = string . Empty ;
743
+ [ Url ]
744
+ public string ? NullableUrlStringValue { get ; set ; }
745
+
746
+ // StringLengthAttribute
747
+ [ StringLength ( 20 , MinimumLength = 5 ) ]
748
+ public string StringLengthValue { get ; set ; } = string . Empty ;
749
+ [ StringLength ( 20 , MinimumLength = 5 ) ]
750
+ public string ? NullableStringLengthValue { get ; set ; }
751
+ }
455
752
#nullable restore
456
753
}
0 commit comments