Skip to content

Commit 5902afc

Browse files
committed
Throw descriptive exception if multiple attributes applied
1 parent b4f5608 commit 5902afc

File tree

2 files changed

+25
-1
lines changed

2 files changed

+25
-1
lines changed

src/Mvc/Mvc.Core/src/ModelBinding/Metadata/ModelAttributes.cs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,14 @@ public static ModelAttributes GetAttributesForParameter(ParameterInfo parameterI
225225
// To avoid this, we call `GetCustomAttributes` directly
226226
// to avoid examining the inheritance hierarchy.
227227
// See https://source.dot.net/#System.Private.CoreLib/src/System/Attribute.CoreCLR.cs,677
228-
return type.GetCustomAttributes<ModelMetadataTypeAttribute>(inherit: false).SingleOrDefault()?.MetadataType;
228+
var modelMetadataTypeAttributes = type.GetCustomAttributes<ModelMetadataTypeAttribute>(inherit: false);
229+
try
230+
{
231+
return modelMetadataTypeAttributes?.SingleOrDefault()?.MetadataType;
232+
}
233+
catch (InvalidOperationException e)
234+
{
235+
throw new InvalidOperationException("Only one ModelMetadataType attribute is permitted per type.", e);
236+
}
229237
}
230238
}

src/Mvc/Mvc.Core/test/ModelBinding/Metadata/ModelAttributesTest.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,18 @@ public void GetAttributesForProperty_WithModelType_IncludesTypeAttributes()
287287
attribute => Assert.IsType<ClassValidator>(attribute));
288288
}
289289

290+
[Fact]
291+
public void GetAttributeForProperty_WithModelType_HandlesMultipleAttributesOnType()
292+
{
293+
// Arrange
294+
var modelType = typeof(InvalidBaseViewModel);
295+
var property = modelType.GetRuntimeProperties().FirstOrDefault(p => p.Name == nameof(BaseModel.RouteValue));
296+
297+
// Assert
298+
var exception = Assert.Throws<InvalidOperationException>(() => ModelAttributes.GetAttributesForProperty(modelType, property));
299+
Assert.Equal("Only one ModelMetadataType attribute is permitted per type.", exception.Message);
300+
}
301+
290302
[ClassValidator]
291303
private class BaseModel
292304
{
@@ -335,6 +347,10 @@ private class BaseViewModel
335347
public string RouteValue { get; set; }
336348
}
337349

350+
[ModelMetadataType<BaseModel>]
351+
[ModelMetadataType(typeof(BaseModel))]
352+
private class InvalidBaseViewModel : BaseViewModel { }
353+
338354
[ModelMetadataType<DerivedModel>]
339355
private class DerivedViewModel : BaseViewModel
340356
{

0 commit comments

Comments
 (0)