@@ -583,11 +583,8 @@ public void CreateModel_ForStructModelType_AsProperty_ThrowsException()
583
583
string . Format (
584
584
CultureInfo . CurrentCulture ,
585
585
"Could not create an instance of type '{0}'. Model bound complex types must not be abstract or " +
586
- "value types and must have a parameterless constructor. Alternatively, set the '{1}' property to" +
587
- " a non-null value in the '{2}' constructor." ,
588
- typeof ( PointStruct ) . FullName ,
589
- nameof ( Location . Point ) ,
590
- typeof ( Location ) . FullName ) ,
586
+ "value types and must have a parameterless constructor." ,
587
+ typeof ( PointStruct ) . FullName ) ,
591
588
exception . Message ) ;
592
589
}
593
590
@@ -997,6 +994,32 @@ public async Task BindModelAsync_Success()
997
994
Assert . True ( bindingContext . ModelState . IsValid ) ;
998
995
}
999
996
997
+ // Validates fix for https://github.com/dotnet/aspnetcore/issues/21916
998
+ [ Fact ]
999
+ public async Task BindModelAsync_PropertyInitializedInNonParameterlessConstructorConstructor ( )
1000
+ {
1001
+ // Arrange
1002
+ var model = new ModelWithPropertyInitializedInConstructor ( "TestName" ) ;
1003
+ var property = GetMetadataForProperty ( model . GetType ( ) , nameof ( ModelWithPropertyInitializedInConstructor . NameContainer ) ) ;
1004
+ var nestedProperty = GetMetadataForProperty ( typeof ( ClassWithNoParameterlessConstructor ) , nameof ( ClassWithNoParameterlessConstructor . Name ) ) ;
1005
+ var bindingContext = CreateContext ( property ) ;
1006
+ bindingContext . IsTopLevelObject = false ;
1007
+ var valueProvider = new Mock < IValueProvider > ( MockBehavior . Strict ) ;
1008
+ valueProvider
1009
+ . Setup ( provider => provider . ContainsPrefix ( "theModel.Name" ) )
1010
+ . Returns ( true ) ;
1011
+ bindingContext . ValueProvider = valueProvider . Object ;
1012
+ var binder = CreateBinder ( bindingContext . ModelMetadata ) ;
1013
+
1014
+ binder . Results [ nestedProperty ] = ModelBindingResult . Success ( null ) ;
1015
+
1016
+ // Act
1017
+ var exception = await Assert . ThrowsAsync < InvalidOperationException > ( async ( ) => await binder . BindModelAsync ( bindingContext ) ) ;
1018
+ // Assert
1019
+ var unexpectedMessage = "Alternatively, set the 'NameContainer' property to a non-null value in the 'Microsoft.AspNetCore.Mvc.ModelBinding.Binders.ComplexTypeModelBinderTest+ModelWithPropertyInitializedInConstructor' constructor." ;
1020
+ Assert . DoesNotContain ( exception . Message , unexpectedMessage ) ;
1021
+ }
1022
+
1000
1023
[ Fact ]
1001
1024
public void SetProperty_PropertyHasDefaultValue_DefaultValueAttributeDoesNothing ( )
1002
1025
{
@@ -1297,6 +1320,17 @@ public ClassWithNoParameterlessConstructor(string name)
1297
1320
public string Name { get ; set ; }
1298
1321
}
1299
1322
1323
+ private class ModelWithPropertyInitializedInConstructor
1324
+ {
1325
+ public ModelWithPropertyInitializedInConstructor ( string name )
1326
+ {
1327
+ NameContainer = new ClassWithNoParameterlessConstructor ( name ) ;
1328
+ }
1329
+
1330
+ [ ValueBinderMetadataAttribute ]
1331
+ public ClassWithNoParameterlessConstructor NameContainer { get ; set ; }
1332
+ }
1333
+
1300
1334
private class BindingOptionalProperty
1301
1335
{
1302
1336
[ BindingBehavior ( BindingBehavior . Optional ) ]
0 commit comments