PR comments
- change `AdditionalValues` type to `IDictionary<object, object>` - copy `ModelMetadata.AdditionalValues` in `AssociatedMetadataProvider` sub-classes nits: - add XML comments - correct indentation in `CachedModelMetadata`
This commit is contained in:
parent
3303286288
commit
f93fca1077
|
|
@ -71,13 +71,38 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
||||||
return GetMetadataForParameterCore(modelAccessor, parameterName, parameter);
|
return GetMetadataForParameterCore(modelAccessor, parameterName, parameter);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Override for creating the prototype metadata (without the accessor)
|
// Override for creating the prototype metadata (without the model accessor).
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new <typeparamref name="TModelMetadata"/> instance.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="attributes">The set of attributes relevant for the new instance.</param>
|
||||||
|
/// <param name="containerType">
|
||||||
|
/// <see cref="Type"/> containing this property. <c>null</c> unless this <typeparamref name="TModelMetadata"/>
|
||||||
|
/// describes a property.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="modelType"><see cref="Type"/> this <typeparamref name="TModelMetadata"/> describes.</param>
|
||||||
|
/// <param name="propertyName">
|
||||||
|
/// Name of the property (in <paramref name="containerType"/>) or parameter this
|
||||||
|
/// <typeparamref name="TModelMetadata"/> describes. <c>null</c> or empty if this
|
||||||
|
/// <typeparamref name="TModelMetadata"/> describes a <see cref="Type"/>.
|
||||||
|
/// </param>
|
||||||
|
/// <returns>A new <typeparamref name="TModelMetadata"/> instance.</returns>
|
||||||
protected abstract TModelMetadata CreateMetadataPrototype(IEnumerable<object> attributes,
|
protected abstract TModelMetadata CreateMetadataPrototype(IEnumerable<object> attributes,
|
||||||
Type containerType,
|
Type containerType,
|
||||||
Type modelType,
|
Type modelType,
|
||||||
string propertyName);
|
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.
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new <typeparamref name="TModelMetadata"/> instance based on a <paramref name="prototype"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="prototype">
|
||||||
|
/// <typeparamref name="TModelMetadata"/> that provides the basis for new instance.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="modelAccessor">Accessor for model value of new instance.</param>
|
||||||
|
/// <returns>
|
||||||
|
/// A new <typeparamref name="TModelMetadata"/> instance based on <paramref name="prototype"/>.
|
||||||
|
/// </returns>
|
||||||
protected abstract TModelMetadata CreateMetadataFromPrototype(TModelMetadata prototype,
|
protected abstract TModelMetadata CreateMetadataFromPrototype(TModelMetadata prototype,
|
||||||
Func<object> modelAccessor);
|
Func<object> modelAccessor);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -86,7 +86,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
||||||
// Sealing for consistency with other properties.
|
// Sealing for consistency with other properties.
|
||||||
// ModelMetadata already caches the collection and we have no use case for a ComputeAdditionalValues() method.
|
// ModelMetadata already caches the collection and we have no use case for a ComputeAdditionalValues() method.
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public sealed override IDictionary<string, object> AdditionalValues
|
public sealed override IDictionary<object, object> AdditionalValues
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
|
|
@ -113,7 +113,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
||||||
_binderMetadata = value;
|
_binderMetadata = value;
|
||||||
_isBinderMetadataComputed = true;
|
_isBinderMetadataComputed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public sealed override string BinderModelName
|
public sealed override string BinderModelName
|
||||||
|
|
|
||||||
|
|
@ -6,8 +6,14 @@ using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Mvc.ModelBinding
|
namespace Microsoft.AspNet.Mvc.ModelBinding
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// An <see cref="IModelMetadataProvider"/> implementation that provides
|
||||||
|
/// <see cref="CachedDataAnnotationsModelMetadata"/> instances. Those instances primarily calculate property values
|
||||||
|
/// using attributes from the <see cref="System.ComponentModel.DataAnnotations"/> namespace.
|
||||||
|
/// </summary>
|
||||||
public class DataAnnotationsModelMetadataProvider : AssociatedMetadataProvider<CachedDataAnnotationsModelMetadata>
|
public class DataAnnotationsModelMetadataProvider : AssociatedMetadataProvider<CachedDataAnnotationsModelMetadata>
|
||||||
{
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
protected override CachedDataAnnotationsModelMetadata CreateMetadataPrototype(
|
protected override CachedDataAnnotationsModelMetadata CreateMetadataPrototype(
|
||||||
IEnumerable<object> attributes,
|
IEnumerable<object> attributes,
|
||||||
Type containerType,
|
Type containerType,
|
||||||
|
|
@ -17,11 +23,21 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
||||||
return new CachedDataAnnotationsModelMetadata(this, containerType, modelType, propertyName, attributes);
|
return new CachedDataAnnotationsModelMetadata(this, containerType, modelType, propertyName, attributes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
/// <remarks>
|
||||||
|
/// Copies only a few values from the <paramref name="prototype"/>. Unlikely the rest have been computed.
|
||||||
|
/// </remarks>
|
||||||
protected override CachedDataAnnotationsModelMetadata CreateMetadataFromPrototype(
|
protected override CachedDataAnnotationsModelMetadata CreateMetadataFromPrototype(
|
||||||
CachedDataAnnotationsModelMetadata prototype,
|
CachedDataAnnotationsModelMetadata prototype,
|
||||||
Func<object> modelAccessor)
|
Func<object> modelAccessor)
|
||||||
{
|
{
|
||||||
return new CachedDataAnnotationsModelMetadata(prototype, modelAccessor);
|
var metadata = new CachedDataAnnotationsModelMetadata(prototype, modelAccessor);
|
||||||
|
foreach (var keyValuePair in prototype.AdditionalValues)
|
||||||
|
{
|
||||||
|
metadata.AdditionalValues.Add(keyValuePair);
|
||||||
|
}
|
||||||
|
|
||||||
|
return metadata;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,24 +6,50 @@ using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Mvc.ModelBinding
|
namespace Microsoft.AspNet.Mvc.ModelBinding
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// An <see cref="IModelMetadataProvider"/> that provides base <see cref="ModelMetadata"/> instances and does not
|
||||||
|
/// set most <see cref="ModelMetadata"/> properties. For example this provider does not use data annotations.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Provided for efficiency in scenarios that require minimal <see cref="ModelMetadata"/> information.
|
||||||
|
/// </remarks>
|
||||||
public class EmptyModelMetadataProvider : AssociatedMetadataProvider<ModelMetadata>
|
public class EmptyModelMetadataProvider : AssociatedMetadataProvider<ModelMetadata>
|
||||||
{
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
/// <remarks>Ignores <paramref name="attributes"/>.</remarks>
|
||||||
protected override ModelMetadata CreateMetadataPrototype(IEnumerable<object> attributes,
|
protected override ModelMetadata CreateMetadataPrototype(IEnumerable<object> attributes,
|
||||||
Type containerType,
|
Type containerType,
|
||||||
Type modelType,
|
[NotNull] Type modelType,
|
||||||
string propertyName)
|
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,
|
/// <inheritdoc />
|
||||||
|
/// <remarks>
|
||||||
|
/// Copies very few values from the <paramref name="prototype"/>. Likely <paramref name="prototype"/> has not
|
||||||
|
/// been modified except to add <see cref="ModelMetadata.AdditionalValues"/> entries.
|
||||||
|
/// </remarks>
|
||||||
|
protected override ModelMetadata CreateMetadataFromPrototype([NotNull] ModelMetadata prototype,
|
||||||
Func<object> modelAccessor)
|
Func<object> modelAccessor)
|
||||||
{
|
{
|
||||||
return new ModelMetadata(this,
|
var metadata = new ModelMetadata(
|
||||||
prototype.ContainerType,
|
this,
|
||||||
modelAccessor,
|
prototype.ContainerType,
|
||||||
prototype.ModelType,
|
modelAccessor,
|
||||||
prototype.PropertyName);
|
prototype.ModelType,
|
||||||
|
prototype.PropertyName);
|
||||||
|
foreach (var keyValuePair in prototype.AdditionalValues)
|
||||||
|
{
|
||||||
|
metadata.AdditionalValues.Add(keyValuePair);
|
||||||
|
}
|
||||||
|
|
||||||
|
return metadata;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -50,8 +50,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a collection of additional information about the model.
|
/// Gets a collection of additional information about the model.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public virtual IDictionary<string, object> AdditionalValues { get; }
|
public virtual IDictionary<object, object> AdditionalValues { get; } = new Dictionary<object, object>();
|
||||||
= new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the name of a model if specified explicitly using <see cref="IModelNameProvider"/>.
|
/// Gets or sets the name of a model if specified explicitly using <see cref="IModelNameProvider"/>.
|
||||||
|
|
|
||||||
|
|
@ -150,7 +150,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
||||||
modelAccessor: () => null,
|
modelAccessor: () => null,
|
||||||
modelType: typeof(object),
|
modelType: typeof(object),
|
||||||
propertyName: null);
|
propertyName: null);
|
||||||
var valuesDictionary = new Dictionary<string, object>
|
var valuesDictionary = new Dictionary<object, object>
|
||||||
{
|
{
|
||||||
{ "key1", new object() },
|
{ "key1", new object() },
|
||||||
{ "key2", "value2" },
|
{ "key2", "value2" },
|
||||||
|
|
|
||||||
|
|
@ -15,19 +15,6 @@ namespace ModelBindingWebSite
|
||||||
public static readonly string GroupNameKey = "__GroupName";
|
public static readonly string GroupNameKey = "__GroupName";
|
||||||
private static Guid _guid = new Guid("7d6d0de2-8d59-49ac-99cc-881423b75a76");
|
private static Guid _guid = new Guid("7d6d0de2-8d59-49ac-99cc-881423b75a76");
|
||||||
|
|
||||||
protected override CachedDataAnnotationsModelMetadata CreateMetadataFromPrototype(
|
|
||||||
CachedDataAnnotationsModelMetadata prototype,
|
|
||||||
Func<object> modelAccessor)
|
|
||||||
{
|
|
||||||
var metadata = base.CreateMetadataFromPrototype(prototype, modelAccessor);
|
|
||||||
foreach (var keyValuePair in prototype.AdditionalValues)
|
|
||||||
{
|
|
||||||
metadata.AdditionalValues.Add(keyValuePair);
|
|
||||||
}
|
|
||||||
|
|
||||||
return metadata;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override CachedDataAnnotationsModelMetadata CreateMetadataPrototype(
|
protected override CachedDataAnnotationsModelMetadata CreateMetadataPrototype(
|
||||||
IEnumerable<object> attributes,
|
IEnumerable<object> attributes,
|
||||||
Type containerType,
|
Type containerType,
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ namespace ModelBindingWebSite.Controllers
|
||||||
public class ModelMetadataController
|
public class ModelMetadataController
|
||||||
{
|
{
|
||||||
[HttpGet(template: "/AdditionalValues")]
|
[HttpGet(template: "/AdditionalValues")]
|
||||||
public IDictionary<string, object> GetAdditionalValues([FromServices] IModelMetadataProvider provider)
|
public IDictionary<object, object> GetAdditionalValues([FromServices] IModelMetadataProvider provider)
|
||||||
{
|
{
|
||||||
var metadata = provider.GetMetadataForType(
|
var metadata = provider.GetMetadataForType(
|
||||||
modelAccessor: null,
|
modelAccessor: null,
|
||||||
|
|
|
||||||
|
|
@ -18,8 +18,8 @@ namespace ModelBindingWebSite
|
||||||
// Set up application services
|
// Set up application services
|
||||||
app.UseServices(services =>
|
app.UseServices(services =>
|
||||||
{
|
{
|
||||||
// Override the IModelMetadataProvider AddMvc would normally use. Make service a singleton though
|
// Override the IModelMetadataProvider AddMvc would normally add.
|
||||||
// AddMvc would configure DataAnnotationsModelMetadataProvider as transient.
|
// ModelMetadataController relies on additional values AdditionalValuesMetadataProvider provides.
|
||||||
services.AddSingleton<IModelMetadataProvider, AdditionalValuesMetadataProvider>();
|
services.AddSingleton<IModelMetadataProvider, AdditionalValuesMetadataProvider>();
|
||||||
|
|
||||||
// Add MVC services to the services container
|
// Add MVC services to the services container
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue