diff --git a/src/Microsoft.AspNet.Mvc.ModelBinding/Metadata/AssociatedMetadataProvider.cs b/src/Microsoft.AspNet.Mvc.ModelBinding/Metadata/AssociatedMetadataProvider.cs index d84900b92b..c65442291d 100644 --- a/src/Microsoft.AspNet.Mvc.ModelBinding/Metadata/AssociatedMetadataProvider.cs +++ b/src/Microsoft.AspNet.Mvc.ModelBinding/Metadata/AssociatedMetadataProvider.cs @@ -71,13 +71,38 @@ namespace Microsoft.AspNet.Mvc.ModelBinding return GetMetadataForParameterCore(modelAccessor, parameterName, parameter); } - // Override for creating the prototype metadata (without the accessor) + // Override for creating the prototype metadata (without the model accessor). + /// + /// Creates a new instance. + /// + /// The set of attributes relevant for the new instance. + /// + /// containing this property. null unless this + /// describes a property. + /// + /// this describes. + /// + /// Name of the property (in ) or parameter this + /// describes. null or empty if this + /// describes a . + /// + /// A new instance. protected abstract TModelMetadata CreateMetadataPrototype(IEnumerable attributes, Type containerType, Type modelType, string propertyName); - // Override for applying the prototype + modelAccess to yield the final metadata + // Override for applying the prototype + model accessor to yield the final metadata. + /// + /// Creates a new instance based on a . + /// + /// + /// that provides the basis for new instance. + /// + /// Accessor for model value of new instance. + /// + /// A new instance based on . + /// protected abstract TModelMetadata CreateMetadataFromPrototype(TModelMetadata prototype, Func modelAccessor); diff --git a/src/Microsoft.AspNet.Mvc.ModelBinding/Metadata/CachedModelMetadata.cs b/src/Microsoft.AspNet.Mvc.ModelBinding/Metadata/CachedModelMetadata.cs index 8e9b37db46..8ea9dbca04 100644 --- a/src/Microsoft.AspNet.Mvc.ModelBinding/Metadata/CachedModelMetadata.cs +++ b/src/Microsoft.AspNet.Mvc.ModelBinding/Metadata/CachedModelMetadata.cs @@ -86,7 +86,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding // Sealing for consistency with other properties. // ModelMetadata already caches the collection and we have no use case for a ComputeAdditionalValues() method. /// - public sealed override IDictionary AdditionalValues + public sealed override IDictionary AdditionalValues { get { @@ -113,7 +113,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding _binderMetadata = value; _isBinderMetadataComputed = true; } - } + } /// public sealed override string BinderModelName diff --git a/src/Microsoft.AspNet.Mvc.ModelBinding/Metadata/DataAnnotationsModelMetadataProvider.cs b/src/Microsoft.AspNet.Mvc.ModelBinding/Metadata/DataAnnotationsModelMetadataProvider.cs index 3a7acfcd85..a838a7b0dc 100644 --- a/src/Microsoft.AspNet.Mvc.ModelBinding/Metadata/DataAnnotationsModelMetadataProvider.cs +++ b/src/Microsoft.AspNet.Mvc.ModelBinding/Metadata/DataAnnotationsModelMetadataProvider.cs @@ -6,8 +6,14 @@ using System.Collections.Generic; namespace Microsoft.AspNet.Mvc.ModelBinding { + /// + /// An implementation that provides + /// instances. Those instances primarily calculate property values + /// using attributes from the namespace. + /// public class DataAnnotationsModelMetadataProvider : AssociatedMetadataProvider { + /// protected override CachedDataAnnotationsModelMetadata CreateMetadataPrototype( IEnumerable attributes, Type containerType, @@ -17,11 +23,21 @@ namespace Microsoft.AspNet.Mvc.ModelBinding return new CachedDataAnnotationsModelMetadata(this, containerType, modelType, propertyName, attributes); } + /// + /// + /// Copies only a few values from the . Unlikely the rest have been computed. + /// protected override CachedDataAnnotationsModelMetadata CreateMetadataFromPrototype( CachedDataAnnotationsModelMetadata prototype, Func modelAccessor) { - return new CachedDataAnnotationsModelMetadata(prototype, modelAccessor); + var metadata = new CachedDataAnnotationsModelMetadata(prototype, modelAccessor); + foreach (var keyValuePair in prototype.AdditionalValues) + { + metadata.AdditionalValues.Add(keyValuePair); + } + + return metadata; } } } diff --git a/src/Microsoft.AspNet.Mvc.ModelBinding/Metadata/EmptyModelMetadataProvider.cs b/src/Microsoft.AspNet.Mvc.ModelBinding/Metadata/EmptyModelMetadataProvider.cs index eb9b989688..ed5968e5e9 100644 --- a/src/Microsoft.AspNet.Mvc.ModelBinding/Metadata/EmptyModelMetadataProvider.cs +++ b/src/Microsoft.AspNet.Mvc.ModelBinding/Metadata/EmptyModelMetadataProvider.cs @@ -6,24 +6,50 @@ using System.Collections.Generic; namespace Microsoft.AspNet.Mvc.ModelBinding { + /// + /// An that provides base instances and does not + /// set most properties. For example this provider does not use data annotations. + /// + /// + /// Provided for efficiency in scenarios that require minimal information. + /// public class EmptyModelMetadataProvider : AssociatedMetadataProvider { + /// + /// Ignores . protected override ModelMetadata CreateMetadataPrototype(IEnumerable attributes, Type containerType, - Type modelType, + [NotNull] Type modelType, string propertyName) { - return new ModelMetadata(this, containerType, null, modelType, propertyName); + return new ModelMetadata( + this, + containerType, + modelAccessor: null, + modelType: modelType, + propertyName: propertyName); } - protected override ModelMetadata CreateMetadataFromPrototype(ModelMetadata prototype, + /// + /// + /// Copies very few values from the . Likely has not + /// been modified except to add entries. + /// + protected override ModelMetadata CreateMetadataFromPrototype([NotNull] ModelMetadata prototype, Func modelAccessor) { - return new ModelMetadata(this, - prototype.ContainerType, - modelAccessor, - prototype.ModelType, - prototype.PropertyName); + var metadata = new ModelMetadata( + this, + prototype.ContainerType, + modelAccessor, + prototype.ModelType, + prototype.PropertyName); + foreach (var keyValuePair in prototype.AdditionalValues) + { + metadata.AdditionalValues.Add(keyValuePair); + } + + return metadata; } } } diff --git a/src/Microsoft.AspNet.Mvc.ModelBinding/Metadata/ModelMetadata.cs b/src/Microsoft.AspNet.Mvc.ModelBinding/Metadata/ModelMetadata.cs index 07e74cda4e..1391077ec7 100644 --- a/src/Microsoft.AspNet.Mvc.ModelBinding/Metadata/ModelMetadata.cs +++ b/src/Microsoft.AspNet.Mvc.ModelBinding/Metadata/ModelMetadata.cs @@ -50,8 +50,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding /// /// Gets a collection of additional information about the model. /// - public virtual IDictionary AdditionalValues { get; } - = new Dictionary(StringComparer.OrdinalIgnoreCase); + public virtual IDictionary AdditionalValues { get; } = new Dictionary(); /// /// Gets or sets the name of a model if specified explicitly using . diff --git a/test/Microsoft.AspNet.Mvc.ModelBinding.Test/Metadata/ModelMetadataTest.cs b/test/Microsoft.AspNet.Mvc.ModelBinding.Test/Metadata/ModelMetadataTest.cs index d61651162d..aab7483c7d 100644 --- a/test/Microsoft.AspNet.Mvc.ModelBinding.Test/Metadata/ModelMetadataTest.cs +++ b/test/Microsoft.AspNet.Mvc.ModelBinding.Test/Metadata/ModelMetadataTest.cs @@ -150,7 +150,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding modelAccessor: () => null, modelType: typeof(object), propertyName: null); - var valuesDictionary = new Dictionary + var valuesDictionary = new Dictionary { { "key1", new object() }, { "key2", "value2" }, diff --git a/test/WebSites/ModelBindingWebSite/AdditionalValuesMetadataProvider.cs b/test/WebSites/ModelBindingWebSite/AdditionalValuesMetadataProvider.cs index 59a50670d3..2a28f76ec7 100644 --- a/test/WebSites/ModelBindingWebSite/AdditionalValuesMetadataProvider.cs +++ b/test/WebSites/ModelBindingWebSite/AdditionalValuesMetadataProvider.cs @@ -15,19 +15,6 @@ namespace ModelBindingWebSite public static readonly string GroupNameKey = "__GroupName"; private static Guid _guid = new Guid("7d6d0de2-8d59-49ac-99cc-881423b75a76"); - protected override CachedDataAnnotationsModelMetadata CreateMetadataFromPrototype( - CachedDataAnnotationsModelMetadata prototype, - Func modelAccessor) - { - var metadata = base.CreateMetadataFromPrototype(prototype, modelAccessor); - foreach (var keyValuePair in prototype.AdditionalValues) - { - metadata.AdditionalValues.Add(keyValuePair); - } - - return metadata; - } - protected override CachedDataAnnotationsModelMetadata CreateMetadataPrototype( IEnumerable attributes, Type containerType, diff --git a/test/WebSites/ModelBindingWebSite/Controllers/ModelMetadataController.cs b/test/WebSites/ModelBindingWebSite/Controllers/ModelMetadataController.cs index 9af915be98..ae1eca5043 100644 --- a/test/WebSites/ModelBindingWebSite/Controllers/ModelMetadataController.cs +++ b/test/WebSites/ModelBindingWebSite/Controllers/ModelMetadataController.cs @@ -12,7 +12,7 @@ namespace ModelBindingWebSite.Controllers public class ModelMetadataController { [HttpGet(template: "/AdditionalValues")] - public IDictionary GetAdditionalValues([FromServices] IModelMetadataProvider provider) + public IDictionary GetAdditionalValues([FromServices] IModelMetadataProvider provider) { var metadata = provider.GetMetadataForType( modelAccessor: null, diff --git a/test/WebSites/ModelBindingWebSite/Startup.cs b/test/WebSites/ModelBindingWebSite/Startup.cs index 7ceaad66ac..8b1724e451 100644 --- a/test/WebSites/ModelBindingWebSite/Startup.cs +++ b/test/WebSites/ModelBindingWebSite/Startup.cs @@ -18,8 +18,8 @@ namespace ModelBindingWebSite // Set up application services app.UseServices(services => { - // Override the IModelMetadataProvider AddMvc would normally use. Make service a singleton though - // AddMvc would configure DataAnnotationsModelMetadataProvider as transient. + // Override the IModelMetadataProvider AddMvc would normally add. + // ModelMetadataController relies on additional values AdditionalValuesMetadataProvider provides. services.AddSingleton(); // Add MVC services to the services container