From 7dd3afe3d154cc92c90c0c40ba38f45cde001433 Mon Sep 17 00:00:00 2001 From: Doug Bunting Date: Fri, 20 Mar 2015 18:26:04 -0700 Subject: [PATCH] Add `enum`-related details to `ModelMetadata` - #438 part 1/2 and #2027 part 1/3 slight oddity in the XML docs - unfortunately Roslyn seems to ignore `TypeInfo` being a subclass of `Type` nit: use correct `warningsAsErrors` datatype in test project.json --- .../DataAnnotationsMetadataProvider.cs | 56 ++- .../Metadata/DefaultModelMetadata.cs | 38 +- .../Metadata/DisplayMetadata.cs | 30 ++ .../ModelMetadata.cs | 41 ++ .../DataAnnotationsMetadataProviderTest.cs | 439 +++++++++++++++++- .../Metadata/DefaultModelMetadataTest.cs | 4 + .../Metadata/ModelMetadataTest.cs | 32 ++ .../project.json | 2 +- 8 files changed, 635 insertions(+), 7 deletions(-) diff --git a/src/Microsoft.AspNet.Mvc.ModelBinding/Metadata/DataAnnotationsMetadataProvider.cs b/src/Microsoft.AspNet.Mvc.ModelBinding/Metadata/DataAnnotationsMetadataProvider.cs index 6ae291a1d2..57317f3dad 100644 --- a/src/Microsoft.AspNet.Mvc.ModelBinding/Metadata/DataAnnotationsMetadataProvider.cs +++ b/src/Microsoft.AspNet.Mvc.ModelBinding/Metadata/DataAnnotationsMetadataProvider.cs @@ -1,8 +1,11 @@ // Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System; +using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Linq; +using System.Reflection; using Microsoft.Framework.Internal; namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata @@ -91,6 +94,39 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata displayMetadata.EditFormatString = displayFormatAttribute.DataFormatString; } + // IsEnum et cetera + var underlyingType = Nullable.GetUnderlyingType(context.Key.ModelType) ?? context.Key.ModelType; + if (underlyingType.IsEnum()) + { + // IsEnum + displayMetadata.IsEnum = true; + + // IsFlagsEnum + var underlyingTypeInfo = underlyingType.GetTypeInfo(); + displayMetadata.IsFlagsEnum = + underlyingTypeInfo.GetCustomAttribute(inherit: false) != null; + + // EnumDisplayNamesAndValues and EnumNamesAndValues + // + // Order EnumDisplayNamesAndValues to match Enum.GetNames(). That method orders by absolute value, + // then its behavior is undefined (but hopefully stable). Add to EnumNamesAndValues in same order but + // Dictionary does not guarantee order will be preserved. + var displayNamesAndValues = new List>(); + var namesAndValues = new Dictionary(); + foreach (var name in Enum.GetNames(underlyingType)) + { + var field = underlyingType.GetField(name); + var displayName = GetDisplayName(field); + var value = ((Enum)field.GetValue(obj: null)).ToString("d"); + + displayNamesAndValues.Add(new KeyValuePair(displayName, value)); + namesAndValues.Add(name, value); + } + + displayMetadata.EnumDisplayNamesAndValues = displayNamesAndValues; + displayMetadata.EnumNamesAndValues = namesAndValues; + } + // HasNonDefaultEditFormat if (!string.IsNullOrEmpty(displayFormatAttribute?.DataFormatString) && displayFormatAttribute?.ApplyFormatInEditMode == true) @@ -139,7 +175,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata displayMetadata.Order = displayAttribute.GetOrder().Value; } - // ShowForDisplay + // ShowForDisplay if (scaffoldColumnAttribute != null) { displayMetadata.ShowForDisplay = scaffoldColumnAttribute.Scaffold; @@ -157,7 +193,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata displayMetadata.SimpleDisplayProperty = displayColumnAttribute.DisplayColumn; } - // TemplateHinte + // TemplateHint if (uiHintAttribute != null) { displayMetadata.TemplateHint = uiHintAttribute.UIHint; @@ -176,5 +212,21 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata context.ValidationMetadata.ValiatorMetadata.Add(attribute); } } + + // Return non-empty name specified in a [Display] attribute for a field, if any; field.Name otherwise. + private static string GetDisplayName(FieldInfo field) + { + var display = field.GetCustomAttribute(inherit: false); + if (display != null) + { + var name = display.GetName(); + if (!string.IsNullOrEmpty(name)) + { + return name; + } + } + + return field.Name; + } } } \ No newline at end of file diff --git a/src/Microsoft.AspNet.Mvc.ModelBinding/Metadata/DefaultModelMetadata.cs b/src/Microsoft.AspNet.Mvc.ModelBinding/Metadata/DefaultModelMetadata.cs index 9ad5e8369b..66414b25c3 100644 --- a/src/Microsoft.AspNet.Mvc.ModelBinding/Metadata/DefaultModelMetadata.cs +++ b/src/Microsoft.AspNet.Mvc.ModelBinding/Metadata/DefaultModelMetadata.cs @@ -210,6 +210,24 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata } } + /// + public override IEnumerable> EnumDisplayNamesAndValues + { + get + { + return DisplayMetadata.EnumDisplayNamesAndValues; + } + } + + /// + public override IReadOnlyDictionary EnumNamesAndValues + { + get + { + return DisplayMetadata.EnumNamesAndValues; + } + } + /// public override bool HasNonDefaultEditFormat { @@ -237,6 +255,24 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata } } + /// + public override bool IsEnum + { + get + { + return DisplayMetadata.IsEnum; + } + } + + /// + public override bool IsFlagsEnum + { + get + { + return DisplayMetadata.IsFlagsEnum; + } + } + /// public override bool IsReadOnly { @@ -274,7 +310,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata _isRequired = !ModelType.AllowsNullValue(); } } - + return _isRequired.Value; } } diff --git a/src/Microsoft.AspNet.Mvc.ModelBinding/Metadata/DisplayMetadata.cs b/src/Microsoft.AspNet.Mvc.ModelBinding/Metadata/DisplayMetadata.cs index 0b8718cd18..5d3a17496c 100644 --- a/src/Microsoft.AspNet.Mvc.ModelBinding/Metadata/DisplayMetadata.cs +++ b/src/Microsoft.AspNet.Mvc.ModelBinding/Metadata/DisplayMetadata.cs @@ -55,6 +55,20 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata /// public string EditFormatString { get; set; } + /// + /// Gets the ordered display names and values of all values in + /// or Nullable.GetUnderlyingType(ModelType). See + /// . + /// + public IEnumerable> EnumDisplayNamesAndValues { get; set; } + + /// + /// Gets the names and values of all values in + /// or Nullable.GetUnderlyingType(ModelType). See . + /// + // This could be implemented in DefaultModelMetadata. But value should be cached. + public IReadOnlyDictionary EnumNamesAndValues { get; set; } + /// /// Gets or sets a value indicating whether or not the model has a non-default edit format. /// See @@ -73,6 +87,22 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata /// public bool HtmlEncode { get; set; } = true; + /// + /// Gets a value indicating whether or + /// Nullable.GetUnderlyingType(ModelType) is for an . See + /// . + /// + // This could be implemented in DefaultModelMetadata. But value is needed in the details provider. + public bool IsEnum { get; set; } + + /// + /// Gets a value indicating whether or + /// Nullable.GetUnderlyingType(ModelType) is for an with an associated + /// . See . + /// + // This could be implemented in DefaultModelMetadata. But value is needed in the details provider. + public bool IsFlagsEnum { get; set; } + /// /// Gets or sets the text to display when the model value is null. /// See diff --git a/src/Microsoft.AspNet.Mvc.ModelBinding/ModelMetadata.cs b/src/Microsoft.AspNet.Mvc.ModelBinding/ModelMetadata.cs index a166a0d505..8fa258a340 100644 --- a/src/Microsoft.AspNet.Mvc.ModelBinding/ModelMetadata.cs +++ b/src/Microsoft.AspNet.Mvc.ModelBinding/ModelMetadata.cs @@ -120,6 +120,26 @@ namespace Microsoft.AspNet.Mvc.ModelBinding /// public abstract string EditFormatString { get; } + /// + /// Gets the ordered display names and values of all values in or + /// Nullable.GetUnderlyingType(ModelType). + /// + /// + /// An of mappings between field names + /// and values. null if is false. + /// + public abstract IEnumerable> EnumDisplayNamesAndValues { get; } + + /// + /// Gets the names and values of all values in or + /// Nullable.GetUnderlyingType(ModelType). + /// + /// + /// An of mappings between field names + /// and values. null if is false. + /// + public abstract IReadOnlyDictionary EnumNamesAndValues { get; } + /// /// Gets a value indicating whether has a non-null, non-empty /// value different from the default for the datatype. @@ -145,6 +165,27 @@ namespace Microsoft.AspNet.Mvc.ModelBinding /// public abstract bool HideSurroundingHtml { get; } + /// + /// Gets a value indicating whether or Nullable.GetUnderlyingType(ModelType) is + /// for an . + /// + /// + /// true if type.IsEnum (type.GetTypeInfo().IsEnum for DNX Core 5.0) is true for + /// or Nullable.GetUnderlyingType(ModelType); false otherwise. + /// + public abstract bool IsEnum { get; } + + /// + /// Gets a value indicating whether or Nullable.GetUnderlyingType(ModelType) is + /// for an with an associated . + /// + /// + /// true if is true and or + /// Nullable.GetUnderlyingType(ModelType) has an associated ; false + /// otherwise. + /// + public abstract bool IsFlagsEnum { get; } + /// /// Gets a value indicating whether or not the model value is read-only. This is only applicable when /// the current instance represents a property. diff --git a/test/Microsoft.AspNet.Mvc.ModelBinding.Test/Metadata/DataAnnotationsMetadataProviderTest.cs b/test/Microsoft.AspNet.Mvc.ModelBinding.Test/Metadata/DataAnnotationsMetadataProviderTest.cs index f684f7164e..b379e073a5 100644 --- a/test/Microsoft.AspNet.Mvc.ModelBinding.Test/Metadata/DataAnnotationsMetadataProviderTest.cs +++ b/test/Microsoft.AspNet.Mvc.ModelBinding.Test/Metadata/DataAnnotationsMetadataProviderTest.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using Xunit; @@ -9,7 +10,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata { public class DataAnnotationsMetadataProviderTest { - // Includes attributes with a 'simple' effect on display details. + // Includes attributes with a 'simple' effect on display details. public static TheoryData, object> DisplayDetailsData { get @@ -47,8 +48,8 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata [Theory] [MemberData(nameof(DisplayDetailsData))] public void GetDisplayDetails_SimpleAttributes( - object attribute, - Func accessor, + object attribute, + Func accessor, object expected) { // Arrange @@ -193,5 +194,437 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata // Assert Assert.Equal("description from resources", context.DisplayMetadata.Description); } + + [Theory] + [InlineData(typeof(EmptyClass), false)] + [InlineData(typeof(ClassWithFields), false)] + [InlineData(typeof(ClassWithProperties), false)] + [InlineData(typeof(EmptyEnum), true)] + [InlineData(typeof(EmptyEnum?), true)] + [InlineData(typeof(EnumWithDisplayNames), true)] + [InlineData(typeof(EnumWithDisplayNames?), true)] + [InlineData(typeof(EnumWithDuplicates), true)] + [InlineData(typeof(EnumWithDuplicates?), true)] + [InlineData(typeof(EnumWithFlags), true)] + [InlineData(typeof(EnumWithFlags?), true)] + [InlineData(typeof(EnumWithFields), true)] + [InlineData(typeof(EnumWithFields?), true)] + [InlineData(typeof(EmptyStruct), false)] + [InlineData(typeof(StructWithFields), false)] + [InlineData(typeof(StructWithFields?), false)] + [InlineData(typeof(StructWithProperties), false)] + public void GetDisplayDetails_IsEnum_ReflectsModelType(Type type, bool expectedIsEnum) + { + // Arrange + var provider = new DataAnnotationsMetadataProvider(); + + var key = ModelMetadataIdentity.ForType(type); + var attributes = new object[0]; + var context = new DisplayMetadataProviderContext(key, attributes); + + // Act + provider.GetDisplayMetadata(context); + + // Assert + Assert.Equal(expectedIsEnum, context.DisplayMetadata.IsEnum); + } + + [Theory] + [InlineData(typeof(EmptyClass), false)] + [InlineData(typeof(ClassWithFields), false)] + [InlineData(typeof(ClassWithProperties), false)] + [InlineData(typeof(EmptyEnum), false)] + [InlineData(typeof(EmptyEnum?), false)] + [InlineData(typeof(EnumWithDisplayNames), false)] + [InlineData(typeof(EnumWithDisplayNames?), false)] + [InlineData(typeof(EnumWithDuplicates), false)] + [InlineData(typeof(EnumWithDuplicates?), false)] + [InlineData(typeof(EnumWithFlags), true)] + [InlineData(typeof(EnumWithFlags?), true)] + [InlineData(typeof(EnumWithFields), false)] + [InlineData(typeof(EnumWithFields?), false)] + [InlineData(typeof(EmptyStruct), false)] + [InlineData(typeof(StructWithFields), false)] + [InlineData(typeof(StructWithFields?), false)] + [InlineData(typeof(StructWithProperties), false)] + public void GetDisplayDetails_IsFlagsEnum_ReflectsModelType(Type type, bool expectedIsFlagsEnum) + { + // Arrange + var provider = new DataAnnotationsMetadataProvider(); + + var key = ModelMetadataIdentity.ForType(type); + var attributes = new object[0]; + var context = new DisplayMetadataProviderContext(key, attributes); + + // Act + provider.GetDisplayMetadata(context); + + // Assert + Assert.Equal(expectedIsFlagsEnum, context.DisplayMetadata.IsFlagsEnum); + } + + // Type -> expected EnumNamesAndValues + public static TheoryData> EnumNamesData + { + get + { + return new TheoryData> + { + { typeof(ClassWithFields), null }, + { typeof(StructWithFields), null }, + { typeof(StructWithFields?), null }, + { typeof(EmptyEnum), new Dictionary() }, + { typeof(EmptyEnum?), new Dictionary() }, + { + typeof(EnumWithDisplayNames), + new Dictionary + { + { nameof(EnumWithDisplayNames.MinusTwo), "-2" }, + { nameof(EnumWithDisplayNames.MinusOne), "-1" }, + { nameof(EnumWithDisplayNames.Zero), "0" }, + { nameof(EnumWithDisplayNames.One), "1" }, + { nameof(EnumWithDisplayNames.Two), "2" }, + { nameof(EnumWithDisplayNames.Three), "3" }, + } + }, + { + typeof(EnumWithDisplayNames?), + new Dictionary + { + { nameof(EnumWithDisplayNames.MinusTwo), "-2" }, + { nameof(EnumWithDisplayNames.MinusOne), "-1" }, + { nameof(EnumWithDisplayNames.Zero), "0" }, + { nameof(EnumWithDisplayNames.One), "1" }, + { nameof(EnumWithDisplayNames.Two), "2" }, + { nameof(EnumWithDisplayNames.Three), "3" }, + } + }, + { + typeof(EnumWithDuplicates), + new Dictionary + { + { nameof(EnumWithDuplicates.Zero), "0" }, + { nameof(EnumWithDuplicates.None), "0" }, + { nameof(EnumWithDuplicates.One), "1" }, + { nameof(EnumWithDuplicates.Two), "2" }, + { nameof(EnumWithDuplicates.Duece), "2" }, + { nameof(EnumWithDuplicates.Three), "3" }, + { nameof(EnumWithDuplicates.MoreThanTwo), "3" }, + } + }, + { + typeof(EnumWithDuplicates?), + new Dictionary + { + { nameof(EnumWithDuplicates.Zero), "0" }, + { nameof(EnumWithDuplicates.None), "0" }, + { nameof(EnumWithDuplicates.One), "1" }, + { nameof(EnumWithDuplicates.Two), "2" }, + { nameof(EnumWithDuplicates.Duece), "2" }, + { nameof(EnumWithDuplicates.Three), "3" }, + { nameof(EnumWithDuplicates.MoreThanTwo), "3" }, + } + }, + { + typeof(EnumWithFlags), + new Dictionary + { + { nameof(EnumWithFlags.All), "-1" }, + { nameof(EnumWithFlags.Zero), "0" }, + { nameof(EnumWithFlags.One), "1" }, + { nameof(EnumWithFlags.Two), "2" }, + { nameof(EnumWithFlags.Four), "4" }, + } + }, + { + typeof(EnumWithFlags?), + new Dictionary + { + { nameof(EnumWithFlags.All), "-1" }, + { nameof(EnumWithFlags.Zero), "0" }, + { nameof(EnumWithFlags.One), "1" }, + { nameof(EnumWithFlags.Two), "2" }, + { nameof(EnumWithFlags.Four), "4" }, + } + }, + { + typeof(EnumWithFields), + new Dictionary + { + { nameof(EnumWithFields.MinusTwo), "-2" }, + { nameof(EnumWithFields.MinusOne), "-1" }, + { nameof(EnumWithFields.Zero), "0" }, + { nameof(EnumWithFields.One), "1" }, + { nameof(EnumWithFields.Two), "2" }, + { nameof(EnumWithFields.Three), "3" }, + } + }, + { + typeof(EnumWithFields?), + new Dictionary + { + { nameof(EnumWithFields.MinusTwo), "-2" }, + { nameof(EnumWithFields.MinusOne), "-1" }, + { nameof(EnumWithFields.Zero), "0" }, + { nameof(EnumWithFields.One), "1" }, + { nameof(EnumWithFields.Two), "2" }, + { nameof(EnumWithFields.Three), "3" }, + } + }, + }; + } + } + + [Theory] + [MemberData(nameof(EnumNamesData))] + public void GetDisplayDetails_EnumNamesAndValues_ReflectsModelType( + Type type, + IReadOnlyDictionary expectedDictionary) + { + // Arrange + var provider = new DataAnnotationsMetadataProvider(); + + var key = ModelMetadataIdentity.ForType(type); + var attributes = new object[0]; + var context = new DisplayMetadataProviderContext(key, attributes); + + // Act + provider.GetDisplayMetadata(context); + + // Assert + // This assertion does *not* require entry orders to match. + Assert.Equal(expectedDictionary, context.DisplayMetadata.EnumNamesAndValues); + } + + // Type -> expected EnumDisplayNamesAndValues + public static TheoryData>> EnumDisplayNamesData + { + get + { + return new TheoryData>> + { + { typeof(ClassWithFields), null }, + { typeof(StructWithFields), null }, + { typeof(EmptyEnum), new List>() }, + { typeof(EmptyEnum?), new List>() }, + { + typeof(EnumWithDisplayNames), + new List> + { + new KeyValuePair("cero", "0"), + new KeyValuePair("uno", "1"), + new KeyValuePair("dos", "2"), + new KeyValuePair("tres", "3"), + new KeyValuePair("name from resources", "-2"), + new KeyValuePair("menos uno", "-1"), + } + }, + { + typeof(EnumWithDisplayNames?), + new List> + { + new KeyValuePair("cero", "0"), + new KeyValuePair("uno", "1"), + new KeyValuePair("dos", "2"), + new KeyValuePair("tres", "3"), + new KeyValuePair("name from resources", "-2"), + new KeyValuePair("menos uno", "-1"), + } + }, + { + // Note order duplicates appear cannot be inferred easily e.g. does not match the source. + // Zero is before None but Two is before Duece in the class below. + typeof(EnumWithDuplicates), + new List> + { + new KeyValuePair(nameof(EnumWithDuplicates.Zero), "0"), + new KeyValuePair(nameof(EnumWithDuplicates.None), "0"), + new KeyValuePair(nameof(EnumWithDuplicates.One), "1"), + new KeyValuePair(nameof(EnumWithDuplicates.Duece), "2"), + new KeyValuePair(nameof(EnumWithDuplicates.Two), "2"), + new KeyValuePair(nameof(EnumWithDuplicates.MoreThanTwo), "3"), + new KeyValuePair(nameof(EnumWithDuplicates.Three), "3"), + } + }, + { + typeof(EnumWithDuplicates?), + new List> + { + new KeyValuePair(nameof(EnumWithDuplicates.Zero), "0"), + new KeyValuePair(nameof(EnumWithDuplicates.None), "0"), + new KeyValuePair(nameof(EnumWithDuplicates.One), "1"), + new KeyValuePair(nameof(EnumWithDuplicates.Duece), "2"), + new KeyValuePair(nameof(EnumWithDuplicates.Two), "2"), + new KeyValuePair(nameof(EnumWithDuplicates.MoreThanTwo), "3"), + new KeyValuePair(nameof(EnumWithDuplicates.Three), "3"), + } + }, + { + typeof(EnumWithFlags), + new List> + { + new KeyValuePair(nameof(EnumWithFlags.Zero), "0"), + new KeyValuePair(nameof(EnumWithFlags.One), "1"), + new KeyValuePair(nameof(EnumWithFlags.Two), "2"), + new KeyValuePair(nameof(EnumWithFlags.Four), "4"), + new KeyValuePair(nameof(EnumWithFlags.All), "-1"), + } + }, + { + typeof(EnumWithFlags?), + new List> + { + new KeyValuePair(nameof(EnumWithFlags.Zero), "0"), + new KeyValuePair(nameof(EnumWithFlags.One), "1"), + new KeyValuePair(nameof(EnumWithFlags.Two), "2"), + new KeyValuePair(nameof(EnumWithFlags.Four), "4"), + new KeyValuePair(nameof(EnumWithFlags.All), "-1"), + } + }, + { + typeof(EnumWithFields), + new List> + { + new KeyValuePair(nameof(EnumWithFields.Zero), "0"), + new KeyValuePair(nameof(EnumWithFields.One), "1"), + new KeyValuePair(nameof(EnumWithFields.Two), "2"), + new KeyValuePair(nameof(EnumWithFields.Three), "3"), + new KeyValuePair(nameof(EnumWithFields.MinusTwo), "-2"), + new KeyValuePair(nameof(EnumWithFields.MinusOne), "-1"), + } + }, + { + typeof(EnumWithFields?), + new List> + { + new KeyValuePair(nameof(EnumWithFields.Zero), "0"), + new KeyValuePair(nameof(EnumWithFields.One), "1"), + new KeyValuePair(nameof(EnumWithFields.Two), "2"), + new KeyValuePair(nameof(EnumWithFields.Three), "3"), + new KeyValuePair(nameof(EnumWithFields.MinusTwo), "-2"), + new KeyValuePair(nameof(EnumWithFields.MinusOne), "-1"), + } + }, + }; + } + } + + [Theory] + [MemberData(nameof(EnumDisplayNamesData))] + public void GetDisplayDetails_EnumDisplayNamesAndValues_ReflectsModelType( + Type type, + IEnumerable> expectedKeyValuePairs) + { + // Arrange + var provider = new DataAnnotationsMetadataProvider(); + + var key = ModelMetadataIdentity.ForType(type); + var attributes = new object[0]; + var context = new DisplayMetadataProviderContext(key, attributes); + + // Act + provider.GetDisplayMetadata(context); + + // Assert + Assert.Equal(expectedKeyValuePairs, context.DisplayMetadata.EnumDisplayNamesAndValues); + } + + private class EmptyClass + { + } + + private class ClassWithFields + { + public const int Zero = 0; + + public const int One = 1; + } + + private class ClassWithProperties + { + public int Id { get; set; } + + public string Name { get; set; } + } + + private enum EmptyEnum + { + } + + private enum EnumWithDisplayNames + { + [Display(Name = "tres")] + Three = 3, + + [Display(Name = "dos")] + Two = 2, + + [Display(Name = "uno")] + One = 1, + + [Display(Name = "cero")] + Zero = 0, + + [Display(Name = "menos uno")] + MinusOne = -1, + + [Display(Name = nameof(Test.TestResources.DisplayAttribute_Name), ResourceType = typeof(Test.TestResources))] + MinusTwo = -2, + } + + private enum EnumWithDuplicates + { + Zero = 0, + One = 1, + Three = 3, + MoreThanTwo = 3, + Two = 2, + None = 0, + Duece = 2, + } + + [Flags] + private enum EnumWithFlags + { + Four = 4, + Two = 2, + One = 1, + Zero = 0, + All = -1, + } + + private enum EnumWithFields + { + MinusTwo = -2, + MinusOne = -1, + Three = 3, + Two = 2, + One = 1, + Zero = 0, + } + + private struct EmptyStruct + { + } + + private struct StructWithFields + { + public const int Zero = 0; + + public const int One = 1; + } + + private struct StructWithProperties + { + public StructWithProperties(int id, string name) + { + Id = id; + Name = name; + } + + public int Id { get; private set; } + + public string Name { get; private set; } + } } } \ No newline at end of file diff --git a/test/Microsoft.AspNet.Mvc.ModelBinding.Test/Metadata/DefaultModelMetadataTest.cs b/test/Microsoft.AspNet.Mvc.ModelBinding.Test/Metadata/DefaultModelMetadataTest.cs index 801316c31f..f1e624824d 100644 --- a/test/Microsoft.AspNet.Mvc.ModelBinding.Test/Metadata/DefaultModelMetadataTest.cs +++ b/test/Microsoft.AspNet.Mvc.ModelBinding.Test/Metadata/DefaultModelMetadataTest.cs @@ -39,6 +39,8 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata Assert.True(metadata.HtmlEncode); Assert.False(metadata.IsComplexType); Assert.False(metadata.IsCollectionType); + Assert.False(metadata.IsEnum); + Assert.False(metadata.IsFlagsEnum); Assert.False(metadata.IsNullableValueType); Assert.False(metadata.IsReadOnly); Assert.False(metadata.IsRequired); @@ -50,6 +52,8 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata Assert.Null(metadata.DisplayFormatString); Assert.Null(metadata.DisplayName); Assert.Null(metadata.EditFormatString); + Assert.Null(metadata.EnumDisplayNamesAndValues); + Assert.Null(metadata.EnumNamesAndValues); Assert.Null(metadata.NullDisplayText); Assert.Null(metadata.TemplateHint); Assert.Null(metadata.SimpleDisplayProperty); diff --git a/test/Microsoft.AspNet.Mvc.ModelBinding.Test/Metadata/ModelMetadataTest.cs b/test/Microsoft.AspNet.Mvc.ModelBinding.Test/Metadata/ModelMetadataTest.cs index 4da7aaf73b..774e4b5b0e 100644 --- a/test/Microsoft.AspNet.Mvc.ModelBinding.Test/Metadata/ModelMetadataTest.cs +++ b/test/Microsoft.AspNet.Mvc.ModelBinding.Test/Metadata/ModelMetadataTest.cs @@ -269,6 +269,22 @@ namespace Microsoft.AspNet.Mvc.ModelBinding } } + public override IEnumerable> EnumDisplayNamesAndValues + { + get + { + throw new NotImplementedException(); + } + } + + public override IReadOnlyDictionary EnumNamesAndValues + { + get + { + throw new NotImplementedException(); + } + } + public override bool HasNonDefaultEditFormat { get @@ -293,6 +309,22 @@ namespace Microsoft.AspNet.Mvc.ModelBinding } } + public override bool IsEnum + { + get + { + throw new NotImplementedException(); + } + } + + public override bool IsFlagsEnum + { + get + { + throw new NotImplementedException(); + } + } + public override bool IsReadOnly { get diff --git a/test/Microsoft.AspNet.Mvc.ModelBinding.Test/project.json b/test/Microsoft.AspNet.Mvc.ModelBinding.Test/project.json index d5d5ad4607..e75a66b415 100644 --- a/test/Microsoft.AspNet.Mvc.ModelBinding.Test/project.json +++ b/test/Microsoft.AspNet.Mvc.ModelBinding.Test/project.json @@ -1,6 +1,6 @@ { "compilationOptions": { - "warningsAsErrors": "true" + "warningsAsErrors": true }, "dependencies": { "Microsoft.AspNet.FileProviders": "1.0.0-*",