Skip to content
This repository has been archived by the owner on Dec 14, 2018. It is now read-only.

Commit

Permalink
Replace IModelBindingMessageProvider with new highly-virtual base cla…
Browse files Browse the repository at this point in the history
…ss (#6241)

Replace IModelBindingMessageProvider with new highly-virtual base class. Fixes #6069
  • Loading branch information
SteveSandersonMS authored May 10, 2017
1 parent f68bea2 commit 014a786
Show file tree
Hide file tree
Showing 17 changed files with 276 additions and 251 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,62 +8,62 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Metadata
/// <summary>
/// Provider for error messages the model binding system detects.
/// </summary>
public interface IModelBindingMessageProvider
public abstract class ModelBindingMessageProvider
{
/// <summary>
/// Error message the model binding system adds when a property with an associated
/// <c>BindRequiredAttribute</c> is not bound.
/// </summary>
/// <value>Default <see cref="string"/> is "A value for the '{0}' property was not provided.".</value>
Func<string, string> MissingBindRequiredValueAccessor { get; }
public virtual Func<string, string> MissingBindRequiredValueAccessor { get; }

/// <summary>
/// Error message the model binding system adds when either the key or the value of a
/// <see cref="System.Collections.Generic.KeyValuePair{TKey, TValue}"/> is bound but not both.
/// </summary>
/// <value>Default <see cref="string"/> is "A value is required.".</value>
Func<string> MissingKeyOrValueAccessor { get; }
public virtual Func<string> MissingKeyOrValueAccessor { get; }

/// <summary>
/// Error message the model binding system adds when no value is provided for the request body,
/// but a value is required.
/// </summary>
/// <value>Default <see cref="string"/> is "A non-empty request body is required.".</value>
Func<string> MissingRequestBodyRequiredValueAccessor { get; }
public virtual Func<string> MissingRequestBodyRequiredValueAccessor { get; }

/// <summary>
/// Error message the model binding system adds when a <c>null</c> value is bound to a
/// non-<see cref="Nullable"/> property.
/// </summary>
/// <value>Default <see cref="string"/> is "The value '{0}' is invalid.".</value>
Func<string, string> ValueMustNotBeNullAccessor { get; }
public virtual Func<string, string> ValueMustNotBeNullAccessor { get; }

/// <summary>
/// Error message the model binding system adds when <see cref="ModelError.Exception"/> is of type
/// <see cref="FormatException"/> or <see cref="OverflowException"/> and value is known.
/// </summary>
/// <value>Default <see cref="string"/> is "The value '{0}' is not valid for {1}.".</value>
Func<string, string, string> AttemptedValueIsInvalidAccessor { get; }
public virtual Func<string, string, string> AttemptedValueIsInvalidAccessor { get; }

/// <summary>
/// Error message the model binding system adds when <see cref="ModelError.Exception"/> is of type
/// <see cref="FormatException"/> or <see cref="OverflowException"/> and value is unknown.
/// </summary>
/// <value>Default <see cref="string"/> is "The supplied value is invalid for {0}.".</value>
Func<string, string> UnknownValueIsInvalidAccessor { get; }
public virtual Func<string, string> UnknownValueIsInvalidAccessor { get; }

/// <summary>
/// Fallback error message HTML and tag helpers display when a property is invalid but the
/// <see cref="ModelError"/>s have <c>null</c> <see cref="ModelError.ErrorMessage"/>s.
/// </summary>
/// <value>Default <see cref="string"/> is "The value '{0}' is invalid.".</value>
Func<string, string> ValueIsInvalidAccessor { get; }
public virtual Func<string, string> ValueIsInvalidAccessor { get; }

/// <summary>
/// Error message HTML and tag helpers add for client-side validation of numeric formats. Visible in the
/// browser if the field for a <c>float</c> property (for example) does not have a correctly-formatted value.
/// </summary>
/// <value>Default <see cref="string"/> is "The field {0} must be a number.".</value>
Func<string, string> ValueMustBeANumberAccessor { get; }
public virtual Func<string, string> ValueMustBeANumberAccessor { get; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -256,9 +256,9 @@ public string PropertyName
public abstract bool IsRequired { get; }

/// <summary>
/// Gets the <see cref="IModelBindingMessageProvider"/> instance.
/// Gets the <see cref="Metadata.ModelBindingMessageProvider"/> instance.
/// </summary>
public abstract IModelBindingMessageProvider ModelBindingMessageProvider { get; }
public abstract ModelBindingMessageProvider ModelBindingMessageProvider { get; }

/// <summary>
/// Gets a value indicating where the current metadata should be ordered relative to other properties
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
[
{
"TypeId": "public interface Microsoft.AspNetCore.Mvc.ModelBinding.Metadata.IModelBindingMessageProvider",
"MemberId": "System.Func<System.String> get_MissingRequestBodyRequiredValueAccessor()",
"Kind": "Addition"
"Kind": "Removal"
},
{
"TypeId": "public abstract class Microsoft.AspNetCore.Mvc.ModelBinding.ModelMetadata : System.IEquatable<Microsoft.AspNetCore.Mvc.ModelBinding.ModelMetadata>",
"MemberId": "public abstract Microsoft.AspNetCore.Mvc.ModelBinding.Metadata.IModelBindingMessageProvider get_ModelBindingMessageProvider()",
"Kind": "Removal"
}
]
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Metadata
/// </summary>
public class BindingMetadata
{
private ModelBindingMessageProvider _messageProvider;
private DefaultModelBindingMessageProvider _messageProvider;

/// <summary>
/// Gets or sets the <see cref="ModelBinding.BindingSource"/>.
Expand Down Expand Up @@ -53,10 +53,10 @@ public class BindingMetadata
public bool? IsReadOnly { get; set; }

/// <summary>
/// Gets the <see cref="Metadata.ModelBindingMessageProvider"/> instance. See
/// Gets the <see cref="Metadata.DefaultModelBindingMessageProvider"/> instance. See
/// <see cref="ModelMetadata.ModelBindingMessageProvider"/>.
/// </summary>
public ModelBindingMessageProvider ModelBindingMessageProvider
public DefaultModelBindingMessageProvider ModelBindingMessageProvider
{
get
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,196 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System;
using Microsoft.AspNetCore.Mvc.Core;

namespace Microsoft.AspNetCore.Mvc.ModelBinding.Metadata
{
/// <summary>
/// Read / write <see cref="ModelBindingMessageProvider"/> implementation.
/// </summary>
public class DefaultModelBindingMessageProvider : ModelBindingMessageProvider
{
private Func<string, string> _missingBindRequiredValueAccessor;
private Func<string> _missingKeyOrValueAccessor;
private Func<string> _missingRequestBodyRequiredValueAccessor;
private Func<string, string> _valueMustNotBeNullAccessor;
private Func<string, string, string> _attemptedValueIsInvalidAccessor;
private Func<string, string> _unknownValueIsInvalidAccessor;
private Func<string, string> _valueIsInvalidAccessor;
private Func<string, string> _valueMustBeANumberAccessor;

/// <summary>
/// Initializes a new instance of the <see cref="DefaultModelBindingMessageProvider"/> class.
/// </summary>
public DefaultModelBindingMessageProvider()
{
SetMissingBindRequiredValueAccessor(Resources.FormatModelBinding_MissingBindRequiredMember);
SetMissingKeyOrValueAccessor(Resources.FormatKeyValuePair_BothKeyAndValueMustBePresent);
SetMissingRequestBodyRequiredValueAccessor(Resources.FormatModelBinding_MissingRequestBodyRequiredMember);
SetValueMustNotBeNullAccessor(Resources.FormatModelBinding_NullValueNotValid);
SetAttemptedValueIsInvalidAccessor(Resources.FormatModelState_AttemptedValueIsInvalid);
SetUnknownValueIsInvalidAccessor(Resources.FormatModelState_UnknownValueIsInvalid);
SetValueIsInvalidAccessor(Resources.FormatHtmlGeneration_ValueIsInvalid);
SetValueMustBeANumberAccessor(Resources.FormatHtmlGeneration_ValueMustBeNumber);
}

/// <summary>
/// Initializes a new instance of the <see cref="DefaultModelBindingMessageProvider"/> class based on
/// <paramref name="originalProvider"/>.
/// </summary>
/// <param name="originalProvider">The <see cref="DefaultModelBindingMessageProvider"/> to duplicate.</param>
public DefaultModelBindingMessageProvider(DefaultModelBindingMessageProvider originalProvider)
{
if (originalProvider == null)
{
throw new ArgumentNullException(nameof(originalProvider));
}

SetMissingBindRequiredValueAccessor(originalProvider.MissingBindRequiredValueAccessor);
SetMissingKeyOrValueAccessor(originalProvider.MissingKeyOrValueAccessor);
SetMissingRequestBodyRequiredValueAccessor(originalProvider.MissingRequestBodyRequiredValueAccessor);
SetValueMustNotBeNullAccessor(originalProvider.ValueMustNotBeNullAccessor);
SetAttemptedValueIsInvalidAccessor(originalProvider.AttemptedValueIsInvalidAccessor);
SetUnknownValueIsInvalidAccessor(originalProvider.UnknownValueIsInvalidAccessor);
SetValueIsInvalidAccessor(originalProvider.ValueIsInvalidAccessor);
SetValueMustBeANumberAccessor(originalProvider.ValueMustBeANumberAccessor);
}

/// <inheritdoc/>
public override Func<string, string> MissingBindRequiredValueAccessor => _missingBindRequiredValueAccessor;

/// <summary>
/// Sets the <see cref="MissingBindRequiredValueAccessor"/> property.
/// </summary>
/// <param name="missingBindRequiredValueAccessor">The value to set.</param>
public void SetMissingBindRequiredValueAccessor(Func<string, string> missingBindRequiredValueAccessor)
{
if (missingBindRequiredValueAccessor == null)
{
throw new ArgumentNullException(nameof(missingBindRequiredValueAccessor));
}

_missingBindRequiredValueAccessor = missingBindRequiredValueAccessor;
}

/// <inheritdoc/>
public override Func<string> MissingKeyOrValueAccessor => _missingKeyOrValueAccessor;

/// <summary>
/// Sets the <see cref="MissingKeyOrValueAccessor"/> property.
/// </summary>
/// <param name="missingKeyOrValueAccessor">The value to set.</param>
public void SetMissingKeyOrValueAccessor(Func<string> missingKeyOrValueAccessor)
{
if (missingKeyOrValueAccessor == null)
{
throw new ArgumentNullException(nameof(missingKeyOrValueAccessor));
}

_missingKeyOrValueAccessor = missingKeyOrValueAccessor;
}

/// <inheritdoc/>
public override Func<string> MissingRequestBodyRequiredValueAccessor => _missingRequestBodyRequiredValueAccessor;

/// <summary>
/// Sets the <see cref="MissingRequestBodyRequiredValueAccessor"/> property.
/// </summary>
/// <param name="missingRequestBodyRequiredValueAccessor">The value to set.</param>
public void SetMissingRequestBodyRequiredValueAccessor(Func<string> missingRequestBodyRequiredValueAccessor)
{
if (missingRequestBodyRequiredValueAccessor == null)
{
throw new ArgumentNullException(nameof(missingRequestBodyRequiredValueAccessor));
}

_missingRequestBodyRequiredValueAccessor = missingRequestBodyRequiredValueAccessor;
}

/// <inheritdoc/>
public override Func<string, string> ValueMustNotBeNullAccessor => _valueMustNotBeNullAccessor;

/// <summary>
/// Sets the <see cref="ValueMustNotBeNullAccessor"/> property.
/// </summary>
/// <param name="valueMustNotBeNullAccessor">The value to set.</param>
public void SetValueMustNotBeNullAccessor(Func<string, string> valueMustNotBeNullAccessor)
{
if (valueMustNotBeNullAccessor == null)
{
throw new ArgumentNullException(nameof(valueMustNotBeNullAccessor));
}

_valueMustNotBeNullAccessor = valueMustNotBeNullAccessor;
}

/// <inheritdoc/>
public override Func<string, string, string> AttemptedValueIsInvalidAccessor => _attemptedValueIsInvalidAccessor;

/// <summary>
/// Sets the <see cref="AttemptedValueIsInvalidAccessor"/> property.
/// </summary>
/// <param name="attemptedValueIsInvalidAccessor">The value to set.</param>
public void SetAttemptedValueIsInvalidAccessor(Func<string, string, string> attemptedValueIsInvalidAccessor)
{
if (attemptedValueIsInvalidAccessor == null)
{
throw new ArgumentNullException(nameof(attemptedValueIsInvalidAccessor));
}

_attemptedValueIsInvalidAccessor = attemptedValueIsInvalidAccessor;
}

/// <inheritdoc/>
public override Func<string, string> UnknownValueIsInvalidAccessor => _unknownValueIsInvalidAccessor;

/// <summary>
/// Sets the <see cref="UnknownValueIsInvalidAccessor"/> property.
/// </summary>
/// <param name="unknownValueIsInvalidAccessor">The value to set.</param>
public void SetUnknownValueIsInvalidAccessor(Func<string, string> unknownValueIsInvalidAccessor)
{
if (unknownValueIsInvalidAccessor == null)
{
throw new ArgumentNullException(nameof(unknownValueIsInvalidAccessor));
}

_unknownValueIsInvalidAccessor = unknownValueIsInvalidAccessor;
}

/// <inheritdoc/>
public override Func<string, string> ValueIsInvalidAccessor => _valueIsInvalidAccessor;

/// <summary>
/// Sets the <see cref="ValueIsInvalidAccessor"/> property.
/// </summary>
/// <param name="valueIsInvalidAccessor">The value to set.</param>
public void SetValueIsInvalidAccessor(Func<string, string> valueIsInvalidAccessor)
{
if (valueIsInvalidAccessor == null)
{
throw new ArgumentNullException(nameof(valueIsInvalidAccessor));
}

_valueIsInvalidAccessor = valueIsInvalidAccessor;
}

/// <inheritdoc/>
public override Func<string, string> ValueMustBeANumberAccessor => _valueMustBeANumberAccessor;

/// <summary>
/// Sets the <see cref="ValueMustBeANumberAccessor"/> property.
/// </summary>
/// <param name="valueMustBeANumberAccessor">The value to set.</param>
public void SetValueMustBeANumberAccessor(Func<string, string> valueMustBeANumberAccessor)
{
if (valueMustBeANumberAccessor == null)
{
throw new ArgumentNullException(nameof(valueMustBeANumberAccessor));
}

_valueMustBeANumberAccessor = valueMustBeANumberAccessor;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public class DefaultModelMetadata : ModelMetadata

// Default message provider for all DefaultModelMetadata instances; cloned before exposing to
// IBindingMetadataProvider instances to ensure customizations are not accidentally shared.
private readonly ModelBindingMessageProvider _modelBindingMessageProvider;
private readonly DefaultModelBindingMessageProvider _modelBindingMessageProvider;

private ReadOnlyDictionary<object, object> _additionalValues;
private ModelMetadata _elementMetadata;
Expand All @@ -41,7 +41,7 @@ public DefaultModelMetadata(
IModelMetadataProvider provider,
ICompositeMetadataDetailsProvider detailsProvider,
DefaultMetadataDetails details)
: this(provider, detailsProvider, details, new ModelBindingMessageProvider())
: this(provider, detailsProvider, details, new DefaultModelBindingMessageProvider())
{
}

Expand All @@ -51,12 +51,12 @@ public DefaultModelMetadata(
/// <param name="provider">The <see cref="IModelMetadataProvider"/>.</param>
/// <param name="detailsProvider">The <see cref="ICompositeMetadataDetailsProvider"/>.</param>
/// <param name="details">The <see cref="DefaultMetadataDetails"/>.</param>
/// <param name="modelBindingMessageProvider">The <see cref="Metadata.ModelBindingMessageProvider"/>.</param>
/// <param name="modelBindingMessageProvider">The <see cref="Metadata.DefaultModelBindingMessageProvider"/>.</param>
public DefaultModelMetadata(
IModelMetadataProvider provider,
ICompositeMetadataDetailsProvider detailsProvider,
DefaultMetadataDetails details,
ModelBindingMessageProvider modelBindingMessageProvider)
DefaultModelBindingMessageProvider modelBindingMessageProvider)
: base(details.Key)
{
if (provider == null)
Expand Down Expand Up @@ -121,7 +121,7 @@ public BindingMetadata BindingMetadata

// Provide a unique ModelBindingMessageProvider instance so providers' customizations are per-type.
context.BindingMetadata.ModelBindingMessageProvider =
new ModelBindingMessageProvider(_modelBindingMessageProvider);
new DefaultModelBindingMessageProvider(_modelBindingMessageProvider);

_detailsProvider.CreateBindingMetadata(context);
_details.BindingMetadata = context.BindingMetadata;
Expand Down Expand Up @@ -440,7 +440,7 @@ public override bool IsRequired
}

/// <inheritdoc />
public override IModelBindingMessageProvider ModelBindingMessageProvider
public override ModelBindingMessageProvider ModelBindingMessageProvider
{
get
{
Expand Down
Loading

0 comments on commit 014a786

Please sign in to comment.