Add localizers to validation attributes
This commit is contained in:
parent
49acfd562e
commit
0889b18f95
|
|
@ -5,13 +5,14 @@ using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.ComponentModel.DataAnnotations;
|
using System.ComponentModel.DataAnnotations;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
|
using Microsoft.Framework.Localization;
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
||||||
{
|
{
|
||||||
public class CompareAttributeAdapter : DataAnnotationsClientModelValidator<CompareAttribute>
|
public class CompareAttributeAdapter : DataAnnotationsClientModelValidator<CompareAttribute>
|
||||||
{
|
{
|
||||||
public CompareAttributeAdapter(CompareAttribute attribute)
|
public CompareAttributeAdapter(CompareAttribute attribute, IStringLocalizer stringLocalizer)
|
||||||
: base(new CompareAttributeWrapper(attribute))
|
: base(new CompareAttributeWrapper(attribute), stringLocalizer)
|
||||||
{
|
{
|
||||||
if (attribute == null)
|
if (attribute == null)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.ComponentModel.DataAnnotations;
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using Microsoft.Framework.Localization;
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
||||||
{
|
{
|
||||||
|
|
@ -14,13 +15,16 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
||||||
public abstract class DataAnnotationsClientModelValidator<TAttribute> : IClientModelValidator
|
public abstract class DataAnnotationsClientModelValidator<TAttribute> : IClientModelValidator
|
||||||
where TAttribute : ValidationAttribute
|
where TAttribute : ValidationAttribute
|
||||||
{
|
{
|
||||||
|
private readonly IStringLocalizer _stringLocalizer;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a new instance of <see cref="DataAnnotationsClientModelValidator{TAttribute}"/>.
|
/// Create a new instance of <see cref="DataAnnotationsClientModelValidator{TAttribute}"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="attribute">The <typeparamref name="TAttribute"/> instance to validate.</param>
|
/// <param name="attribute">The <typeparamref name="TAttribute"/> instance to validate.</param>
|
||||||
public DataAnnotationsClientModelValidator(TAttribute attribute)
|
/// <param name="stringLocalizer">The <see cref="IStringLocalizer"/>.</param>
|
||||||
|
public DataAnnotationsClientModelValidator(TAttribute attribute, IStringLocalizer stringLocalizer)
|
||||||
{
|
{
|
||||||
Attribute = attribute;
|
Attribute = attribute;
|
||||||
|
_stringLocalizer = stringLocalizer;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -48,7 +52,16 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
||||||
throw new ArgumentNullException(nameof(modelMetadata));
|
throw new ArgumentNullException(nameof(modelMetadata));
|
||||||
}
|
}
|
||||||
|
|
||||||
return Attribute.FormatErrorMessage(modelMetadata.GetDisplayName());
|
var displayName = modelMetadata.GetDisplayName();
|
||||||
|
if (_stringLocalizer != null &&
|
||||||
|
!string.IsNullOrEmpty(Attribute.ErrorMessage) &&
|
||||||
|
string.IsNullOrEmpty(Attribute.ErrorMessageResourceName) &&
|
||||||
|
Attribute.ErrorMessageResourceType == null)
|
||||||
|
{
|
||||||
|
return _stringLocalizer[displayName];
|
||||||
|
}
|
||||||
|
|
||||||
|
return Attribute.FormatErrorMessage(displayName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,8 @@ using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.ComponentModel.DataAnnotations;
|
using System.ComponentModel.DataAnnotations;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using Microsoft.Framework.Localization;
|
||||||
|
using Microsoft.Framework.OptionsModel;
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
||||||
{
|
{
|
||||||
|
|
@ -18,11 +20,27 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
||||||
public class DataAnnotationsClientModelValidatorProvider : IClientModelValidatorProvider
|
public class DataAnnotationsClientModelValidatorProvider : IClientModelValidatorProvider
|
||||||
{
|
{
|
||||||
// A factory for validators based on ValidationAttribute.
|
// A factory for validators based on ValidationAttribute.
|
||||||
internal delegate IClientModelValidator
|
internal delegate IClientModelValidator DataAnnotationsClientModelValidationFactory(
|
||||||
DataAnnotationsClientModelValidationFactory(ValidationAttribute attribute);
|
ValidationAttribute attribute,
|
||||||
|
IStringLocalizer stringLocalizer);
|
||||||
|
|
||||||
private readonly Dictionary<Type, DataAnnotationsClientModelValidationFactory> _attributeFactories =
|
private readonly Dictionary<Type, DataAnnotationsClientModelValidationFactory> _attributeFactories =
|
||||||
BuildAttributeFactoriesDictionary();
|
BuildAttributeFactoriesDictionary();
|
||||||
|
private readonly IOptions<MvcDataAnnotationsLocalizationOptions> _options;
|
||||||
|
private readonly IStringLocalizerFactory _stringLocalizerFactory;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Create a new instance of <see cref="DataAnnotationsClientModelValidatorProvider"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="options">The <see cref="IOptions{MvcDataAnnotationsLocalizationOptions}"/>.</param>
|
||||||
|
/// <param name="stringLocalizerFactory">The <see cref="IStringLocalizerFactory"/>.</param>
|
||||||
|
public DataAnnotationsClientModelValidatorProvider(
|
||||||
|
IOptions<MvcDataAnnotationsLocalizationOptions> options,
|
||||||
|
IStringLocalizerFactory stringLocalizerFactory)
|
||||||
|
{
|
||||||
|
_options = options;
|
||||||
|
_stringLocalizerFactory = stringLocalizerFactory;
|
||||||
|
}
|
||||||
|
|
||||||
internal Dictionary<Type, DataAnnotationsClientModelValidationFactory> AttributeFactories
|
internal Dictionary<Type, DataAnnotationsClientModelValidationFactory> AttributeFactories
|
||||||
{
|
{
|
||||||
|
|
@ -36,6 +54,15 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
||||||
{
|
{
|
||||||
throw new ArgumentNullException(nameof(context));
|
throw new ArgumentNullException(nameof(context));
|
||||||
}
|
}
|
||||||
|
IStringLocalizer stringLocalizer = null;
|
||||||
|
if (_options.Value.DataAnnotationLocalizerProvider != null && _stringLocalizerFactory != null)
|
||||||
|
{
|
||||||
|
// This will pass first non-null type (either containerType or modelType) to delegate.
|
||||||
|
// Pass the root model type(container type) if it is non null, else pass the model type.
|
||||||
|
stringLocalizer = _options.Value.DataAnnotationLocalizerProvider(
|
||||||
|
context.ModelMetadata.ContainerType ?? context.ModelMetadata.ModelType,
|
||||||
|
_stringLocalizerFactory);
|
||||||
|
}
|
||||||
|
|
||||||
var hasRequiredAttribute = false;
|
var hasRequiredAttribute = false;
|
||||||
|
|
||||||
|
|
@ -46,14 +73,14 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
||||||
DataAnnotationsClientModelValidationFactory factory;
|
DataAnnotationsClientModelValidationFactory factory;
|
||||||
if (_attributeFactories.TryGetValue(attribute.GetType(), out factory))
|
if (_attributeFactories.TryGetValue(attribute.GetType(), out factory))
|
||||||
{
|
{
|
||||||
context.Validators.Add(factory(attribute));
|
context.Validators.Add(factory(attribute, stringLocalizer));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!hasRequiredAttribute && context.ModelMetadata.IsRequired)
|
if (!hasRequiredAttribute && context.ModelMetadata.IsRequired)
|
||||||
{
|
{
|
||||||
// Add a default '[Required]' validator for generating HTML if necessary.
|
// Add a default '[Required]' validator for generating HTML if necessary.
|
||||||
context.Validators.Add(new RequiredAttributeAdapter(new RequiredAttribute()));
|
context.Validators.Add(new RequiredAttributeAdapter(new RequiredAttribute(), stringLocalizer));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -63,47 +90,73 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
typeof(RegularExpressionAttribute),
|
typeof(RegularExpressionAttribute),
|
||||||
(attribute) => new RegularExpressionAttributeAdapter((RegularExpressionAttribute)attribute)
|
(attribute, stringLocalizer) => new RegularExpressionAttributeAdapter(
|
||||||
|
(RegularExpressionAttribute)attribute,
|
||||||
|
stringLocalizer)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
typeof(MaxLengthAttribute),
|
typeof(MaxLengthAttribute),
|
||||||
(attribute) => new MaxLengthAttributeAdapter((MaxLengthAttribute)attribute)
|
(attribute, stringLocalizer) => new MaxLengthAttributeAdapter(
|
||||||
|
(MaxLengthAttribute)attribute,
|
||||||
|
stringLocalizer)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
typeof(MinLengthAttribute),
|
typeof(MinLengthAttribute),
|
||||||
(attribute) => new MinLengthAttributeAdapter((MinLengthAttribute)attribute)
|
(attribute, stringLocalizer) => new MinLengthAttributeAdapter(
|
||||||
|
(MinLengthAttribute)attribute,
|
||||||
|
stringLocalizer)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
typeof(CompareAttribute),
|
typeof(CompareAttribute),
|
||||||
(attribute) => new CompareAttributeAdapter((CompareAttribute)attribute)
|
(attribute, stringLocalizer) => new CompareAttributeAdapter(
|
||||||
|
(CompareAttribute)attribute,
|
||||||
|
stringLocalizer)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
typeof(RequiredAttribute),
|
typeof(RequiredAttribute),
|
||||||
(attribute) => new RequiredAttributeAdapter((RequiredAttribute)attribute)
|
(attribute, stringLocalizer) => new RequiredAttributeAdapter(
|
||||||
|
(RequiredAttribute)attribute,
|
||||||
|
stringLocalizer)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
typeof(RangeAttribute),
|
typeof(RangeAttribute),
|
||||||
(attribute) => new RangeAttributeAdapter((RangeAttribute)attribute)
|
(attribute, stringLocalizer) => new RangeAttributeAdapter(
|
||||||
|
(RangeAttribute)attribute,
|
||||||
|
stringLocalizer)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
typeof(StringLengthAttribute),
|
typeof(StringLengthAttribute),
|
||||||
(attribute) => new StringLengthAttributeAdapter((StringLengthAttribute)attribute)
|
(attribute, stringLocalizer) => new StringLengthAttributeAdapter(
|
||||||
|
(StringLengthAttribute)attribute,
|
||||||
|
stringLocalizer)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
typeof(CreditCardAttribute),
|
typeof(CreditCardAttribute),
|
||||||
(attribute) => new DataTypeAttributeAdapter((DataTypeAttribute)attribute, "creditcard")
|
(attribute, stringLocalizer) => new DataTypeAttributeAdapter(
|
||||||
|
(DataTypeAttribute)attribute,
|
||||||
|
"creditcard",
|
||||||
|
stringLocalizer)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
typeof(EmailAddressAttribute),
|
typeof(EmailAddressAttribute),
|
||||||
(attribute) => new DataTypeAttributeAdapter((DataTypeAttribute)attribute, "email")
|
(attribute, stringLocalizer) => new DataTypeAttributeAdapter(
|
||||||
|
(DataTypeAttribute)attribute,
|
||||||
|
"email",
|
||||||
|
stringLocalizer)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
typeof(PhoneAttribute),
|
typeof(PhoneAttribute),
|
||||||
(attribute) => new DataTypeAttributeAdapter((DataTypeAttribute)attribute, "phone")
|
(attribute, stringLocalizer) => new DataTypeAttributeAdapter(
|
||||||
|
(DataTypeAttribute)attribute,
|
||||||
|
"phone",
|
||||||
|
stringLocalizer)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
typeof(UrlAttribute),
|
typeof(UrlAttribute),
|
||||||
(attribute) => new DataTypeAttributeAdapter((DataTypeAttribute)attribute, "url")
|
(attribute, stringLocalizer) => new DataTypeAttributeAdapter(
|
||||||
|
(DataTypeAttribute)attribute,
|
||||||
|
"url",
|
||||||
|
stringLocalizer)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,12 +5,15 @@ using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.ComponentModel.DataAnnotations;
|
using System.ComponentModel.DataAnnotations;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using Microsoft.Framework.Localization;
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
||||||
{
|
{
|
||||||
public class DataAnnotationsModelValidator : IModelValidator
|
public class DataAnnotationsModelValidator : IModelValidator
|
||||||
{
|
{
|
||||||
public DataAnnotationsModelValidator(ValidationAttribute attribute)
|
private IStringLocalizer _stringLocalizer;
|
||||||
|
|
||||||
|
public DataAnnotationsModelValidator(ValidationAttribute attribute, IStringLocalizer stringLocalizer)
|
||||||
{
|
{
|
||||||
if (attribute == null)
|
if (attribute == null)
|
||||||
{
|
{
|
||||||
|
|
@ -18,9 +21,10 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
||||||
}
|
}
|
||||||
|
|
||||||
Attribute = attribute;
|
Attribute = attribute;
|
||||||
|
_stringLocalizer = stringLocalizer;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ValidationAttribute Attribute { get; private set; }
|
public ValidationAttribute Attribute { get; }
|
||||||
|
|
||||||
public bool IsRequired
|
public bool IsRequired
|
||||||
{
|
{
|
||||||
|
|
@ -59,7 +63,16 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
||||||
errorMemberName = null;
|
errorMemberName = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
var validationResult = new ModelValidationResult(errorMemberName, result.ErrorMessage);
|
string errorMessage = null;
|
||||||
|
if (_stringLocalizer != null &&
|
||||||
|
!string.IsNullOrEmpty(Attribute.ErrorMessage) &&
|
||||||
|
string.IsNullOrEmpty(Attribute.ErrorMessageResourceName) &&
|
||||||
|
Attribute.ErrorMessageResourceType == null)
|
||||||
|
{
|
||||||
|
errorMessage = _stringLocalizer[Attribute.ErrorMessage];
|
||||||
|
}
|
||||||
|
|
||||||
|
var validationResult = new ModelValidationResult(errorMemberName, errorMessage ?? result.ErrorMessage);
|
||||||
return new ModelValidationResult[] { validationResult };
|
return new ModelValidationResult[] { validationResult };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,10 +2,11 @@
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.ComponentModel.DataAnnotations;
|
using System.ComponentModel.DataAnnotations;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
using Microsoft.Framework.Localization;
|
||||||
|
using Microsoft.Framework.OptionsModel;
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
||||||
{
|
{
|
||||||
|
|
@ -16,11 +17,35 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class DataAnnotationsModelValidatorProvider : IModelValidatorProvider
|
public class DataAnnotationsModelValidatorProvider : IModelValidatorProvider
|
||||||
{
|
{
|
||||||
|
private readonly IOptions<MvcDataAnnotationsLocalizationOptions> _options;
|
||||||
|
private readonly IStringLocalizerFactory _stringLocalizerFactory;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Create a new instance of <see cref="DataAnnotationsModelValidatorProvider"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="options">The <see cref="IOptions{MvcDataAnnotationsLocalizationOptions}"/>.</param>
|
||||||
|
/// <param name="stringLocalizerFactory">The <see cref="IStringLocalizerFactory"/>.</param>
|
||||||
|
public DataAnnotationsModelValidatorProvider(
|
||||||
|
IOptions<MvcDataAnnotationsLocalizationOptions> options,
|
||||||
|
IStringLocalizerFactory stringLocalizerFactory)
|
||||||
|
{
|
||||||
|
_options = options;
|
||||||
|
_stringLocalizerFactory = stringLocalizerFactory;
|
||||||
|
}
|
||||||
|
|
||||||
public void GetValidators(ModelValidatorProviderContext context)
|
public void GetValidators(ModelValidatorProviderContext context)
|
||||||
{
|
{
|
||||||
|
IStringLocalizer stringLocalizer = null;
|
||||||
|
if (_options.Value.DataAnnotationLocalizerProvider != null && _stringLocalizerFactory != null)
|
||||||
|
{
|
||||||
|
stringLocalizer = _options.Value.DataAnnotationLocalizerProvider(
|
||||||
|
context.ModelMetadata.ContainerType ?? context.ModelMetadata.ModelType,
|
||||||
|
_stringLocalizerFactory);
|
||||||
|
}
|
||||||
|
|
||||||
foreach (var attribute in context.ValidatorMetadata.OfType<ValidationAttribute>())
|
foreach (var attribute in context.ValidatorMetadata.OfType<ValidationAttribute>())
|
||||||
{
|
{
|
||||||
context.Validators.Add(new DataAnnotationsModelValidator(attribute));
|
context.Validators.Add(new DataAnnotationsModelValidator(attribute, stringLocalizer));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Produce a validator if the type supports IValidatableObject
|
// Produce a validator if the type supports IValidatableObject
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.ComponentModel.DataAnnotations;
|
using System.ComponentModel.DataAnnotations;
|
||||||
using Microsoft.AspNet.Mvc.DataAnnotations;
|
using Microsoft.AspNet.Mvc.DataAnnotations;
|
||||||
|
using Microsoft.Framework.Localization;
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
||||||
{
|
{
|
||||||
|
|
@ -14,10 +15,8 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class DataTypeAttributeAdapter : DataAnnotationsClientModelValidator<DataTypeAttribute>
|
public class DataTypeAttributeAdapter : DataAnnotationsClientModelValidator<DataTypeAttribute>
|
||||||
{
|
{
|
||||||
public DataTypeAttributeAdapter(
|
public DataTypeAttributeAdapter(DataTypeAttribute attribute, string ruleName, IStringLocalizer stringLocalizer)
|
||||||
DataTypeAttribute attribute,
|
: base(attribute, stringLocalizer)
|
||||||
string ruleName)
|
|
||||||
: base(attribute)
|
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(ruleName))
|
if (string.IsNullOrEmpty(ruleName))
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,53 @@
|
||||||
|
// 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.AspNet.Mvc.DataAnnotations.Internal;
|
||||||
|
using Microsoft.AspNet.Mvc.ModelBinding.Validation;
|
||||||
|
|
||||||
|
namespace Microsoft.Framework.DependencyInjection
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Extension methods for configuring MVC data annotations localization.
|
||||||
|
/// </summary>
|
||||||
|
public static class MvcDataAnnotationsMvcBuilderExtensions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Adds MVC data annotations localization to the application.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="builder">The <see cref="IMvcBuilder"/>.</param>
|
||||||
|
/// <returns>The <see cref="IMvcBuilder"/>.</returns>
|
||||||
|
public static IMvcBuilder AddDataAnnotationsLocalization(this IMvcBuilder builder)
|
||||||
|
{
|
||||||
|
if (builder == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(builder));
|
||||||
|
}
|
||||||
|
|
||||||
|
return AddDataAnnotationsLocalization(builder, setupAction: null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds MVC data annotations localization to the application.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="builder">The <see cref="IMvcBuilder"/>.</param>
|
||||||
|
/// <param name="setupAction">The action to configure <see cref="MvcDataAnnotationsLocalizationOptions"/>.
|
||||||
|
/// </param>
|
||||||
|
/// <returns>The <see cref="IMvcBuilder"/>.</returns>
|
||||||
|
public static IMvcBuilder AddDataAnnotationsLocalization(
|
||||||
|
this IMvcBuilder builder,
|
||||||
|
Action<MvcDataAnnotationsLocalizationOptions> setupAction)
|
||||||
|
{
|
||||||
|
if (builder == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(builder));
|
||||||
|
}
|
||||||
|
|
||||||
|
DataAnnotationsLocalizationServices.AddDataAnnotationsLocalizationServices(
|
||||||
|
builder.Services,
|
||||||
|
setupAction);
|
||||||
|
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -4,13 +4,22 @@
|
||||||
using System;
|
using System;
|
||||||
using Microsoft.AspNet.Mvc;
|
using Microsoft.AspNet.Mvc;
|
||||||
using Microsoft.AspNet.Mvc.DataAnnotations.Internal;
|
using Microsoft.AspNet.Mvc.DataAnnotations.Internal;
|
||||||
|
using Microsoft.AspNet.Mvc.ModelBinding.Validation;
|
||||||
using Microsoft.Framework.DependencyInjection.Extensions;
|
using Microsoft.Framework.DependencyInjection.Extensions;
|
||||||
using Microsoft.Framework.OptionsModel;
|
using Microsoft.Framework.OptionsModel;
|
||||||
|
|
||||||
namespace Microsoft.Framework.DependencyInjection
|
namespace Microsoft.Framework.DependencyInjection
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Extensions for configuring MVC data annotations using an <see cref="IMvcBuilder"/>.
|
||||||
|
/// </summary>
|
||||||
public static class MvcDataAnnotationsMvcCoreBuilderExtensions
|
public static class MvcDataAnnotationsMvcCoreBuilderExtensions
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Registers MVC data annotations.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="builder">The <see cref="IMvcBuilder"/>.</param>
|
||||||
|
/// <returns>The <see cref="IMvcBuilder"/>.</returns>
|
||||||
public static IMvcCoreBuilder AddDataAnnotations(this IMvcCoreBuilder builder)
|
public static IMvcCoreBuilder AddDataAnnotations(this IMvcCoreBuilder builder)
|
||||||
{
|
{
|
||||||
if (builder == null)
|
if (builder == null)
|
||||||
|
|
@ -22,11 +31,39 @@ namespace Microsoft.Framework.DependencyInjection
|
||||||
return builder;
|
return builder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Registers an action to configure <see cref="MvcDataAnnotationsLocalizationOptions"/> for MVC data
|
||||||
|
/// annotations localization.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="builder">The <see cref="IMvcBuilder"/>.</param>
|
||||||
|
/// <param name="setupAction">An <see cref="Action{MvcDataAnnotationsLocalizationOptions}"/>.</param>
|
||||||
|
/// <returns>The <see cref="IMvcBuilder"/>.</returns>
|
||||||
|
public static IMvcCoreBuilder AddDataAnnotationsLocalization(
|
||||||
|
this IMvcCoreBuilder builder,
|
||||||
|
Action<MvcDataAnnotationsLocalizationOptions> setupAction)
|
||||||
|
{
|
||||||
|
if (builder == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(builder));
|
||||||
|
}
|
||||||
|
|
||||||
|
AddDataAnnotationsLocalizationServices(builder.Services, setupAction);
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
|
||||||
// Internal for testing.
|
// Internal for testing.
|
||||||
internal static void AddDataAnnotationsServices(IServiceCollection services)
|
internal static void AddDataAnnotationsServices(IServiceCollection services)
|
||||||
{
|
{
|
||||||
services.TryAddEnumerable(
|
services.TryAddEnumerable(
|
||||||
ServiceDescriptor.Transient<IConfigureOptions<MvcOptions>, MvcDataAnnotationsMvcOptionsSetup>());
|
ServiceDescriptor.Transient<IConfigureOptions<MvcOptions>, MvcDataAnnotationsMvcOptionsSetup>());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Internal for testing.
|
||||||
|
internal static void AddDataAnnotationsLocalizationServices(
|
||||||
|
IServiceCollection services,
|
||||||
|
Action<MvcDataAnnotationsLocalizationOptions> setupAction)
|
||||||
|
{
|
||||||
|
DataAnnotationsLocalizationServices.AddDataAnnotationsLocalizationServices(services, setupAction);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
// 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.AspNet.Mvc.ModelBinding.Validation;
|
||||||
|
using Microsoft.Framework.DependencyInjection;
|
||||||
|
using Microsoft.Framework.DependencyInjection.Extensions;
|
||||||
|
using Microsoft.Framework.OptionsModel;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.Mvc.DataAnnotations.Internal
|
||||||
|
{
|
||||||
|
public static class DataAnnotationsLocalizationServices
|
||||||
|
{
|
||||||
|
public static void AddDataAnnotationsLocalizationServices(
|
||||||
|
IServiceCollection services,
|
||||||
|
Action<MvcDataAnnotationsLocalizationOptions> setupAction)
|
||||||
|
{
|
||||||
|
services.AddLocalization();
|
||||||
|
|
||||||
|
if (setupAction != null)
|
||||||
|
{
|
||||||
|
services.Configure(setupAction);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
services.TryAddEnumerable(
|
||||||
|
ServiceDescriptor.Transient
|
||||||
|
<IConfigureOptions<MvcDataAnnotationsLocalizationOptions>,
|
||||||
|
MvcDataAnnotationsLocalizationOptionsSetup>());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
// 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.AspNet.Mvc.ModelBinding.Validation;
|
||||||
|
using Microsoft.Framework.OptionsModel;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.Mvc.DataAnnotations.Internal
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Sets up default options for <see cref="MvcDataAnnotationsLocalizationOptions"/>.
|
||||||
|
/// </summary>
|
||||||
|
public class MvcDataAnnotationsLocalizationOptionsSetup : ConfigureOptions<MvcDataAnnotationsLocalizationOptions>
|
||||||
|
{
|
||||||
|
public MvcDataAnnotationsLocalizationOptionsSetup()
|
||||||
|
: base(ConfigureMvc)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void ConfigureMvc(MvcDataAnnotationsLocalizationOptions options)
|
||||||
|
{
|
||||||
|
if (options == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(options));
|
||||||
|
}
|
||||||
|
|
||||||
|
options.DataAnnotationLocalizerProvider = (modelType, stringLocalizerFactory) =>
|
||||||
|
stringLocalizerFactory.Create(modelType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,8 +1,11 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
// 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.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
using Microsoft.AspNet.Mvc.ModelBinding.Metadata;
|
using Microsoft.AspNet.Mvc.ModelBinding.Metadata;
|
||||||
using Microsoft.AspNet.Mvc.ModelBinding.Validation;
|
using Microsoft.AspNet.Mvc.ModelBinding.Validation;
|
||||||
|
using Microsoft.Framework.DependencyInjection;
|
||||||
|
using Microsoft.Framework.Localization;
|
||||||
using Microsoft.Framework.OptionsModel;
|
using Microsoft.Framework.OptionsModel;
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Mvc.DataAnnotations.Internal
|
namespace Microsoft.AspNet.Mvc.DataAnnotations.Internal
|
||||||
|
|
@ -12,15 +15,23 @@ namespace Microsoft.AspNet.Mvc.DataAnnotations.Internal
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class MvcDataAnnotationsMvcOptionsSetup : ConfigureOptions<MvcOptions>
|
public class MvcDataAnnotationsMvcOptionsSetup : ConfigureOptions<MvcOptions>
|
||||||
{
|
{
|
||||||
public MvcDataAnnotationsMvcOptionsSetup()
|
public MvcDataAnnotationsMvcOptionsSetup(IServiceProvider serviceProvider)
|
||||||
: base(ConfigureMvc)
|
: base(options => ConfigureMvc(options, serviceProvider))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void ConfigureMvc(MvcOptions options)
|
public static void ConfigureMvc(MvcOptions options, IServiceProvider serviceProvider)
|
||||||
{
|
{
|
||||||
|
var dataAnnotationLocalizationOptions =
|
||||||
|
serviceProvider.GetRequiredService<IOptions<MvcDataAnnotationsLocalizationOptions>>();
|
||||||
|
|
||||||
|
// This service will be registered only if AddDataAnnotationsLocalization() is added to service collection.
|
||||||
|
var stringLocalizerFactory = serviceProvider.GetService<IStringLocalizerFactory>();
|
||||||
|
|
||||||
options.ModelMetadataDetailsProviders.Add(new DataAnnotationsMetadataProvider());
|
options.ModelMetadataDetailsProviders.Add(new DataAnnotationsMetadataProvider());
|
||||||
options.ModelValidatorProviders.Add(new DataAnnotationsModelValidatorProvider());
|
options.ModelValidatorProviders.Add(new DataAnnotationsModelValidatorProvider(
|
||||||
|
dataAnnotationLocalizationOptions,
|
||||||
|
stringLocalizerFactory));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -4,13 +4,14 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.ComponentModel.DataAnnotations;
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using Microsoft.Framework.Localization;
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
||||||
{
|
{
|
||||||
public class MaxLengthAttributeAdapter : DataAnnotationsClientModelValidator<MaxLengthAttribute>
|
public class MaxLengthAttributeAdapter : DataAnnotationsClientModelValidator<MaxLengthAttribute>
|
||||||
{
|
{
|
||||||
public MaxLengthAttributeAdapter(MaxLengthAttribute attribute)
|
public MaxLengthAttributeAdapter(MaxLengthAttribute attribute, IStringLocalizer stringLocalizer)
|
||||||
: base(attribute)
|
: base(attribute, stringLocalizer)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,13 +4,14 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.ComponentModel.DataAnnotations;
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using Microsoft.Framework.Localization;
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
||||||
{
|
{
|
||||||
public class MinLengthAttributeAdapter : DataAnnotationsClientModelValidator<MinLengthAttribute>
|
public class MinLengthAttributeAdapter : DataAnnotationsClientModelValidator<MinLengthAttribute>
|
||||||
{
|
{
|
||||||
public MinLengthAttributeAdapter(MinLengthAttribute attribute)
|
public MinLengthAttributeAdapter(MinLengthAttribute attribute, IStringLocalizer stringLocalizer)
|
||||||
: base(attribute)
|
: base(attribute, stringLocalizer)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
// 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.Framework.Localization;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Provides programmatic configuration for DataAnnotations localization in the MVC framework.
|
||||||
|
/// </summary>
|
||||||
|
public class MvcDataAnnotationsLocalizationOptions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The delegate to invoke for creating <see cref="IStringLocalizer"/>.
|
||||||
|
/// </summary>
|
||||||
|
public Func<Type, IStringLocalizerFactory, IStringLocalizer> DataAnnotationLocalizerProvider;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -4,13 +4,14 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.ComponentModel.DataAnnotations;
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using Microsoft.Framework.Localization;
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
||||||
{
|
{
|
||||||
public class RangeAttributeAdapter : DataAnnotationsClientModelValidator<RangeAttribute>
|
public class RangeAttributeAdapter : DataAnnotationsClientModelValidator<RangeAttribute>
|
||||||
{
|
{
|
||||||
public RangeAttributeAdapter(RangeAttribute attribute)
|
public RangeAttributeAdapter(RangeAttribute attribute, IStringLocalizer stringLocalizer)
|
||||||
: base(attribute)
|
: base(attribute, stringLocalizer)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,13 +4,14 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.ComponentModel.DataAnnotations;
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using Microsoft.Framework.Localization;
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
||||||
{
|
{
|
||||||
public class RegularExpressionAttributeAdapter : DataAnnotationsClientModelValidator<RegularExpressionAttribute>
|
public class RegularExpressionAttributeAdapter : DataAnnotationsClientModelValidator<RegularExpressionAttribute>
|
||||||
{
|
{
|
||||||
public RegularExpressionAttributeAdapter(RegularExpressionAttribute attribute)
|
public RegularExpressionAttributeAdapter(RegularExpressionAttribute attribute, IStringLocalizer stringLocalizer)
|
||||||
: base(attribute)
|
: base(attribute, stringLocalizer)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,13 +4,14 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.ComponentModel.DataAnnotations;
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using Microsoft.Framework.Localization;
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
||||||
{
|
{
|
||||||
public class RequiredAttributeAdapter : DataAnnotationsClientModelValidator<RequiredAttribute>
|
public class RequiredAttributeAdapter : DataAnnotationsClientModelValidator<RequiredAttribute>
|
||||||
{
|
{
|
||||||
public RequiredAttributeAdapter(RequiredAttribute attribute)
|
public RequiredAttributeAdapter(RequiredAttribute attribute, IStringLocalizer stringLocalizer)
|
||||||
: base(attribute)
|
: base(attribute, stringLocalizer)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,13 +4,14 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.ComponentModel.DataAnnotations;
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using Microsoft.Framework.Localization;
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
||||||
{
|
{
|
||||||
public class StringLengthAttributeAdapter : DataAnnotationsClientModelValidator<StringLengthAttribute>
|
public class StringLengthAttributeAdapter : DataAnnotationsClientModelValidator<StringLengthAttribute>
|
||||||
{
|
{
|
||||||
public StringLengthAttributeAdapter(StringLengthAttribute attribute)
|
public StringLengthAttributeAdapter(StringLengthAttribute attribute, IStringLocalizer stringLocalizer)
|
||||||
: base(attribute)
|
: base(attribute, stringLocalizer)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,8 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"Microsoft.AspNet.Mvc.Core": "6.0.0-*",
|
"Microsoft.AspNet.Mvc.Core": "6.0.0-*",
|
||||||
"Microsoft.Framework.ClosedGenericMatcher.Sources": { "version": "1.0.0-*", "type": "build" },
|
"Microsoft.Framework.ClosedGenericMatcher.Sources": { "version": "1.0.0-*", "type": "build" },
|
||||||
"Microsoft.Framework.CopyOnWriteDictionary.Sources": { "version": "1.0.0-*", "type": "build" }
|
"Microsoft.Framework.CopyOnWriteDictionary.Sources": { "version": "1.0.0-*", "type": "build" },
|
||||||
|
"Microsoft.Framework.Localization": "1.0.0-*"
|
||||||
},
|
},
|
||||||
|
|
||||||
"frameworks": {
|
"frameworks": {
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,10 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
// 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.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
using Microsoft.AspNet.Mvc.ModelBinding.Validation;
|
using Microsoft.AspNet.Mvc.ModelBinding.Validation;
|
||||||
|
using Microsoft.Framework.DependencyInjection;
|
||||||
|
using Microsoft.Framework.Localization;
|
||||||
using Microsoft.Framework.OptionsModel;
|
using Microsoft.Framework.OptionsModel;
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Mvc.ViewFeatures.Internal
|
namespace Microsoft.AspNet.Mvc.ViewFeatures.Internal
|
||||||
|
|
@ -14,16 +17,24 @@ namespace Microsoft.AspNet.Mvc.ViewFeatures.Internal
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of <see cref="MvcViewOptionsSetup"/>.
|
/// Initializes a new instance of <see cref="MvcViewOptionsSetup"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public MvcViewOptionsSetup()
|
public MvcViewOptionsSetup(IServiceProvider serviceProvider)
|
||||||
: base(ConfigureMvc)
|
: base(options => ConfigureMvc(options, serviceProvider))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void ConfigureMvc(MvcViewOptions options)
|
public static void ConfigureMvc(
|
||||||
|
MvcViewOptions options,
|
||||||
|
IServiceProvider serviceProvider)
|
||||||
{
|
{
|
||||||
|
var dataAnnotationsLocalizationOptions =
|
||||||
|
serviceProvider.GetRequiredService<IOptions<MvcDataAnnotationsLocalizationOptions>>();
|
||||||
|
var stringLocalizerFactory = serviceProvider.GetService<IStringLocalizerFactory>();
|
||||||
|
|
||||||
// Set up client validators
|
// Set up client validators
|
||||||
options.ClientModelValidatorProviders.Add(new DefaultClientModelValidatorProvider());
|
options.ClientModelValidatorProviders.Add(new DefaultClientModelValidatorProvider());
|
||||||
options.ClientModelValidatorProviders.Add(new DataAnnotationsClientModelValidatorProvider());
|
options.ClientModelValidatorProviders.Add(new DataAnnotationsClientModelValidatorProvider(
|
||||||
|
dataAnnotationsLocalizationOptions,
|
||||||
|
stringLocalizerFactory));
|
||||||
options.ClientModelValidatorProviders.Add(new NumericClientModelValidatorProvider());
|
options.ClientModelValidatorProviders.Add(new NumericClientModelValidatorProvider());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -242,7 +242,9 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
|
||||||
{
|
{
|
||||||
ModelBinder = innerBinder ?? CreateIntBinder(),
|
ModelBinder = innerBinder ?? CreateIntBinder(),
|
||||||
MetadataProvider = metataProvider,
|
MetadataProvider = metataProvider,
|
||||||
ValidatorProvider = new DataAnnotationsModelValidatorProvider()
|
ValidatorProvider = new DataAnnotationsModelValidatorProvider(
|
||||||
|
new TestOptionsManager<MvcDataAnnotationsLocalizationOptions>(),
|
||||||
|
stringLocalizerFactory: null)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
return bindingContext;
|
return bindingContext;
|
||||||
|
|
|
||||||
|
|
@ -72,7 +72,9 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
||||||
new MutableObjectModelBinder()
|
new MutableObjectModelBinder()
|
||||||
};
|
};
|
||||||
|
|
||||||
var validator = new DataAnnotationsModelValidatorProvider();
|
var validator = new DataAnnotationsModelValidatorProvider(
|
||||||
|
new TestOptionsManager<MvcDataAnnotationsLocalizationOptions>(),
|
||||||
|
stringLocalizerFactory: null);
|
||||||
var model = new MyModel();
|
var model = new MyModel();
|
||||||
var modelStateDictionary = new ModelStateDictionary();
|
var modelStateDictionary = new ModelStateDictionary();
|
||||||
var values = new Dictionary<string, object>
|
var values = new Dictionary<string, object>
|
||||||
|
|
@ -111,7 +113,9 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
||||||
new MutableObjectModelBinder()
|
new MutableObjectModelBinder()
|
||||||
};
|
};
|
||||||
|
|
||||||
var validator = new DataAnnotationsModelValidatorProvider();
|
var validator = new DataAnnotationsModelValidatorProvider(
|
||||||
|
new TestOptionsManager<MvcDataAnnotationsLocalizationOptions>(),
|
||||||
|
stringLocalizerFactory: null);
|
||||||
var model = new MyModel { MyProperty = "Old-Value" };
|
var model = new MyModel { MyProperty = "Old-Value" };
|
||||||
var modelStateDictionary = new ModelStateDictionary();
|
var modelStateDictionary = new ModelStateDictionary();
|
||||||
var values = new Dictionary<string, object>
|
var values = new Dictionary<string, object>
|
||||||
|
|
@ -185,7 +189,9 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
||||||
new MutableObjectModelBinder()
|
new MutableObjectModelBinder()
|
||||||
};
|
};
|
||||||
|
|
||||||
var validator = new DataAnnotationsModelValidatorProvider();
|
var validator = new DataAnnotationsModelValidatorProvider(
|
||||||
|
new TestOptionsManager<MvcDataAnnotationsLocalizationOptions>(),
|
||||||
|
stringLocalizerFactory: null);
|
||||||
var model = new MyModel {
|
var model = new MyModel {
|
||||||
MyProperty = "Old-Value",
|
MyProperty = "Old-Value",
|
||||||
IncludedProperty = "Old-IncludedPropertyValue",
|
IncludedProperty = "Old-IncludedPropertyValue",
|
||||||
|
|
@ -274,7 +280,9 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
||||||
new MutableObjectModelBinder()
|
new MutableObjectModelBinder()
|
||||||
};
|
};
|
||||||
|
|
||||||
var validator = new DataAnnotationsModelValidatorProvider();
|
var validator = new DataAnnotationsModelValidatorProvider(
|
||||||
|
new TestOptionsManager<MvcDataAnnotationsLocalizationOptions>(),
|
||||||
|
stringLocalizerFactory: null);
|
||||||
var model = new MyModel
|
var model = new MyModel
|
||||||
{
|
{
|
||||||
MyProperty = "Old-Value",
|
MyProperty = "Old-Value",
|
||||||
|
|
@ -326,7 +334,9 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
||||||
new MutableObjectModelBinder()
|
new MutableObjectModelBinder()
|
||||||
};
|
};
|
||||||
|
|
||||||
var validator = new DataAnnotationsModelValidatorProvider();
|
var validator = new DataAnnotationsModelValidatorProvider(
|
||||||
|
new TestOptionsManager<MvcDataAnnotationsLocalizationOptions>(),
|
||||||
|
stringLocalizerFactory: null);
|
||||||
var model = new MyModel
|
var model = new MyModel
|
||||||
{
|
{
|
||||||
MyProperty = "Old-Value",
|
MyProperty = "Old-Value",
|
||||||
|
|
@ -532,7 +542,9 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
||||||
new MutableObjectModelBinder()
|
new MutableObjectModelBinder()
|
||||||
};
|
};
|
||||||
|
|
||||||
var validator = new DataAnnotationsModelValidatorProvider();
|
var validator = new DataAnnotationsModelValidatorProvider(
|
||||||
|
new TestOptionsManager<MvcDataAnnotationsLocalizationOptions>(),
|
||||||
|
stringLocalizerFactory: null);
|
||||||
var model = new MyModel
|
var model = new MyModel
|
||||||
{
|
{
|
||||||
MyProperty = "Old-Value",
|
MyProperty = "Old-Value",
|
||||||
|
|
@ -623,7 +635,9 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
||||||
new MutableObjectModelBinder()
|
new MutableObjectModelBinder()
|
||||||
};
|
};
|
||||||
|
|
||||||
var validator = new DataAnnotationsModelValidatorProvider();
|
var validator = new DataAnnotationsModelValidatorProvider(
|
||||||
|
new TestOptionsManager<MvcDataAnnotationsLocalizationOptions>(),
|
||||||
|
stringLocalizerFactory: null);
|
||||||
var model = new MyModel { MyProperty = "Old-Value" };
|
var model = new MyModel { MyProperty = "Old-Value" };
|
||||||
var modelStateDictionary = new ModelStateDictionary();
|
var modelStateDictionary = new ModelStateDictionary();
|
||||||
var values = new Dictionary<string, object>
|
var values = new Dictionary<string, object>
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
||||||
var metadata = metadataProvider.GetMetadataForProperty(typeof(PropertyDisplayNameModel), "MyProperty");
|
var metadata = metadataProvider.GetMetadataForProperty(typeof(PropertyDisplayNameModel), "MyProperty");
|
||||||
|
|
||||||
var attribute = new CompareAttribute("OtherProperty");
|
var attribute = new CompareAttribute("OtherProperty");
|
||||||
var adapter = new CompareAttributeAdapter(attribute);
|
var adapter = new CompareAttributeAdapter(attribute, stringLocalizer: null);
|
||||||
|
|
||||||
var serviceCollection = new ServiceCollection();
|
var serviceCollection = new ServiceCollection();
|
||||||
var requestServices = serviceCollection.BuildServiceProvider();
|
var requestServices = serviceCollection.BuildServiceProvider();
|
||||||
|
|
@ -50,7 +50,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
||||||
var serviceCollection = new ServiceCollection();
|
var serviceCollection = new ServiceCollection();
|
||||||
var requestServices = serviceCollection.BuildServiceProvider();
|
var requestServices = serviceCollection.BuildServiceProvider();
|
||||||
var context = new ClientModelValidationContext(metadata, metadataProvider, requestServices);
|
var context = new ClientModelValidationContext(metadata, metadataProvider, requestServices);
|
||||||
var adapter = new CompareAttributeAdapter(attribute);
|
var adapter = new CompareAttributeAdapter(attribute, stringLocalizer: null);
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var rules = adapter.GetClientValidationRules(context);
|
var rules = adapter.GetClientValidationRules(context);
|
||||||
|
|
@ -76,7 +76,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
||||||
var serviceCollection = new ServiceCollection();
|
var serviceCollection = new ServiceCollection();
|
||||||
var requestServices = serviceCollection.BuildServiceProvider();
|
var requestServices = serviceCollection.BuildServiceProvider();
|
||||||
var context = new ClientModelValidationContext(metadata, metadataProvider, requestServices);
|
var context = new ClientModelValidationContext(metadata, metadataProvider, requestServices);
|
||||||
var adapter = new CompareAttributeAdapter(attribute);
|
var adapter = new CompareAttributeAdapter(attribute, stringLocalizer: null);
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var rules = adapter.GetClientValidationRules(context);
|
var rules = adapter.GetClientValidationRules(context);
|
||||||
|
|
@ -102,7 +102,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
||||||
var serviceCollection = new ServiceCollection();
|
var serviceCollection = new ServiceCollection();
|
||||||
var requestServices = serviceCollection.BuildServiceProvider();
|
var requestServices = serviceCollection.BuildServiceProvider();
|
||||||
var context = new ClientModelValidationContext(metadata, metadataProvider, requestServices);
|
var context = new ClientModelValidationContext(metadata, metadataProvider, requestServices);
|
||||||
var adapter = new CompareAttributeAdapter(attribute);
|
var adapter = new CompareAttributeAdapter(attribute, stringLocalizer: null);
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var rules = adapter.GetClientValidationRules(context);
|
var rules = adapter.GetClientValidationRules(context);
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,9 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
||||||
public void GetValidators_AddsRequiredAttribute_ForIsRequiredTrue()
|
public void GetValidators_AddsRequiredAttribute_ForIsRequiredTrue()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var provider = new DataAnnotationsClientModelValidatorProvider();
|
var provider = new DataAnnotationsClientModelValidatorProvider(
|
||||||
|
new TestOptionsManager<MvcDataAnnotationsLocalizationOptions>(),
|
||||||
|
stringLocalizerFactory: null);
|
||||||
|
|
||||||
var metadata = _metadataProvider.GetMetadataForProperty(
|
var metadata = _metadataProvider.GetMetadataForProperty(
|
||||||
typeof(DummyRequiredAttributeHelperClass),
|
typeof(DummyRequiredAttributeHelperClass),
|
||||||
|
|
@ -37,7 +39,9 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
||||||
public void GetValidators_DoesNotAddRequiredAttribute_ForIsRequiredFalse()
|
public void GetValidators_DoesNotAddRequiredAttribute_ForIsRequiredFalse()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var provider = new DataAnnotationsClientModelValidatorProvider();
|
var provider = new DataAnnotationsClientModelValidatorProvider(
|
||||||
|
new TestOptionsManager<MvcDataAnnotationsLocalizationOptions>(),
|
||||||
|
stringLocalizerFactory: null);
|
||||||
|
|
||||||
var metadata = _metadataProvider.GetMetadataForProperty(
|
var metadata = _metadataProvider.GetMetadataForProperty(
|
||||||
typeof(DummyRequiredAttributeHelperClass),
|
typeof(DummyRequiredAttributeHelperClass),
|
||||||
|
|
@ -56,7 +60,9 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
||||||
public void GetValidators_DoesNotAddExtraRequiredAttribute_IfAttributeIsSpecifiedExplicitly()
|
public void GetValidators_DoesNotAddExtraRequiredAttribute_IfAttributeIsSpecifiedExplicitly()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var provider = new DataAnnotationsClientModelValidatorProvider();
|
var provider = new DataAnnotationsClientModelValidatorProvider(
|
||||||
|
new TestOptionsManager<MvcDataAnnotationsLocalizationOptions>(),
|
||||||
|
stringLocalizerFactory: null);
|
||||||
|
|
||||||
var metadata = _metadataProvider.GetMetadataForProperty(
|
var metadata = _metadataProvider.GetMetadataForProperty(
|
||||||
typeof(DummyRequiredAttributeHelperClass),
|
typeof(DummyRequiredAttributeHelperClass),
|
||||||
|
|
@ -122,11 +128,14 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
||||||
Type expectedAdapterType)
|
Type expectedAdapterType)
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var adapters = new DataAnnotationsClientModelValidatorProvider().AttributeFactories;
|
var adapters = new DataAnnotationsClientModelValidatorProvider(
|
||||||
|
new TestOptionsManager<MvcDataAnnotationsLocalizationOptions>(),
|
||||||
|
stringLocalizerFactory: null)
|
||||||
|
.AttributeFactories;
|
||||||
var adapterFactory = adapters.Single(kvp => kvp.Key == attribute.GetType()).Value;
|
var adapterFactory = adapters.Single(kvp => kvp.Key == attribute.GetType()).Value;
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var adapter = adapterFactory(attribute);
|
var adapter = adapterFactory(attribute, stringLocalizer: null);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.IsType(expectedAdapterType, adapter);
|
Assert.IsType(expectedAdapterType, adapter);
|
||||||
|
|
@ -150,11 +159,14 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
||||||
string expectedRuleName)
|
string expectedRuleName)
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var adapters = new DataAnnotationsClientModelValidatorProvider().AttributeFactories;
|
var adapters = new DataAnnotationsClientModelValidatorProvider(
|
||||||
|
new TestOptionsManager<MvcDataAnnotationsLocalizationOptions>(),
|
||||||
|
stringLocalizerFactory: null)
|
||||||
|
.AttributeFactories;
|
||||||
var adapterFactory = adapters.Single(kvp => kvp.Key == attribute.GetType()).Value;
|
var adapterFactory = adapters.Single(kvp => kvp.Key == attribute.GetType()).Value;
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var adapter = adapterFactory(attribute);
|
var adapter = adapterFactory(attribute, stringLocalizer: null);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
var dataTypeAdapter = Assert.IsType<DataTypeAttributeAdapter>(adapter);
|
var dataTypeAdapter = Assert.IsType<DataTypeAttributeAdapter>(adapter);
|
||||||
|
|
@ -165,7 +177,9 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
||||||
public void UnknownValidationAttribute_IsNotAddedAsValidator()
|
public void UnknownValidationAttribute_IsNotAddedAsValidator()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var provider = new DataAnnotationsClientModelValidatorProvider();
|
var provider = new DataAnnotationsClientModelValidatorProvider(
|
||||||
|
new TestOptionsManager<MvcDataAnnotationsLocalizationOptions>(),
|
||||||
|
stringLocalizerFactory: null);
|
||||||
var metadata = _metadataProvider.GetMetadataForType(typeof(DummyClassWithDummyValidationAttribute));
|
var metadata = _metadataProvider.GetMetadataForType(typeof(DummyClassWithDummyValidationAttribute));
|
||||||
|
|
||||||
var providerContext = new ClientValidatorProviderContext(metadata);
|
var providerContext = new ClientValidatorProviderContext(metadata);
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,9 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
||||||
public void GetValidators_ReturnsValidatorForIValidatableObject()
|
public void GetValidators_ReturnsValidatorForIValidatableObject()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var provider = new DataAnnotationsModelValidatorProvider();
|
var provider = new DataAnnotationsModelValidatorProvider(
|
||||||
|
new TestOptionsManager<MvcDataAnnotationsLocalizationOptions>(),
|
||||||
|
stringLocalizerFactory: null);
|
||||||
var mockValidatable = Mock.Of<IValidatableObject>();
|
var mockValidatable = Mock.Of<IValidatableObject>();
|
||||||
var metadata = _metadataProvider.GetMetadataForType(mockValidatable.GetType());
|
var metadata = _metadataProvider.GetMetadataForType(mockValidatable.GetType());
|
||||||
|
|
||||||
|
|
@ -40,7 +42,9 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
||||||
public void UnknownValidationAttributeGetsDefaultAdapter()
|
public void UnknownValidationAttributeGetsDefaultAdapter()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var provider = new DataAnnotationsModelValidatorProvider();
|
var provider = new DataAnnotationsModelValidatorProvider(
|
||||||
|
new TestOptionsManager<MvcDataAnnotationsLocalizationOptions>(),
|
||||||
|
stringLocalizerFactory: null);
|
||||||
var metadata = _metadataProvider.GetMetadataForType(typeof(DummyClassWithDummyValidationAttribute));
|
var metadata = _metadataProvider.GetMetadataForType(typeof(DummyClassWithDummyValidationAttribute));
|
||||||
|
|
||||||
var providerContext = new ModelValidatorProviderContext(metadata);
|
var providerContext = new ModelValidatorProviderContext(metadata);
|
||||||
|
|
@ -69,7 +73,9 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
||||||
public void IValidatableObjectGetsAValidator()
|
public void IValidatableObjectGetsAValidator()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var provider = new DataAnnotationsModelValidatorProvider();
|
var provider = new DataAnnotationsModelValidatorProvider(
|
||||||
|
new TestOptionsManager<MvcDataAnnotationsLocalizationOptions>(),
|
||||||
|
stringLocalizerFactory: null);
|
||||||
var mockValidatable = new Mock<IValidatableObject>();
|
var mockValidatable = new Mock<IValidatableObject>();
|
||||||
var metadata = _metadataProvider.GetMetadataForType(mockValidatable.Object.GetType());
|
var metadata = _metadataProvider.GetMetadataForType(mockValidatable.Object.GetType());
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ using System.ComponentModel.DataAnnotations;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
#endif
|
#endif
|
||||||
using Microsoft.Framework.DependencyInjection;
|
using Microsoft.Framework.DependencyInjection;
|
||||||
|
using Microsoft.Framework.Localization;
|
||||||
#if DNX451
|
#if DNX451
|
||||||
using Moq;
|
using Moq;
|
||||||
using Moq.Protected;
|
using Moq.Protected;
|
||||||
|
|
@ -26,7 +27,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
||||||
var attribute = new RequiredAttribute();
|
var attribute = new RequiredAttribute();
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var validator = new DataAnnotationsModelValidator(attribute);
|
var validator = new DataAnnotationsModelValidator(attribute, stringLocalizer : null);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Same(attribute, validator.Attribute);
|
Assert.Same(attribute, validator.Attribute);
|
||||||
|
|
@ -67,7 +68,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
||||||
})
|
})
|
||||||
.Returns(ValidationResult.Success)
|
.Returns(ValidationResult.Success)
|
||||||
.Verifiable();
|
.Verifiable();
|
||||||
var validator = new DataAnnotationsModelValidator(attribute.Object);
|
var validator = new DataAnnotationsModelValidator(attribute.Object, stringLocalizer: null);
|
||||||
var validationContext = CreateValidationContext(modelExplorer);
|
var validationContext = CreateValidationContext(modelExplorer);
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
|
|
@ -89,7 +90,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
||||||
var attribute = new Mock<ValidationAttribute> { CallBase = true };
|
var attribute = new Mock<ValidationAttribute> { CallBase = true };
|
||||||
attribute.Setup(a => a.IsValid(modelExplorer.Model)).Returns(true);
|
attribute.Setup(a => a.IsValid(modelExplorer.Model)).Returns(true);
|
||||||
|
|
||||||
var validator = new DataAnnotationsModelValidator(attribute.Object);
|
var validator = new DataAnnotationsModelValidator(attribute.Object, stringLocalizer: null);
|
||||||
var validationContext = CreateValidationContext(modelExplorer);
|
var validationContext = CreateValidationContext(modelExplorer);
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
|
|
@ -110,7 +111,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
||||||
var attribute = new Mock<ValidationAttribute> { CallBase = true };
|
var attribute = new Mock<ValidationAttribute> { CallBase = true };
|
||||||
attribute.Setup(a => a.IsValid(modelExplorer.Model)).Returns(false);
|
attribute.Setup(a => a.IsValid(modelExplorer.Model)).Returns(false);
|
||||||
|
|
||||||
var validator = new DataAnnotationsModelValidator(attribute.Object);
|
var validator = new DataAnnotationsModelValidator(attribute.Object, stringLocalizer: null);
|
||||||
var validationContext = CreateValidationContext(modelExplorer);
|
var validationContext = CreateValidationContext(modelExplorer);
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
|
|
@ -134,7 +135,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
||||||
attribute.Protected()
|
attribute.Protected()
|
||||||
.Setup<ValidationResult>("IsValid", ItExpr.IsAny<object>(), ItExpr.IsAny<ValidationContext>())
|
.Setup<ValidationResult>("IsValid", ItExpr.IsAny<object>(), ItExpr.IsAny<ValidationContext>())
|
||||||
.Returns(ValidationResult.Success);
|
.Returns(ValidationResult.Success);
|
||||||
var validator = new DataAnnotationsModelValidator(attribute.Object);
|
var validator = new DataAnnotationsModelValidator(attribute.Object, stringLocalizer: null);
|
||||||
var validationContext = CreateValidationContext(modelExplorer);
|
var validationContext = CreateValidationContext(modelExplorer);
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
|
|
@ -158,7 +159,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
||||||
attribute.Protected()
|
attribute.Protected()
|
||||||
.Setup<ValidationResult>("IsValid", ItExpr.IsAny<object>(), ItExpr.IsAny<ValidationContext>())
|
.Setup<ValidationResult>("IsValid", ItExpr.IsAny<object>(), ItExpr.IsAny<ValidationContext>())
|
||||||
.Returns(new ValidationResult(errorMessage, memberNames: null));
|
.Returns(new ValidationResult(errorMessage, memberNames: null));
|
||||||
var validator = new DataAnnotationsModelValidator(attribute.Object);
|
var validator = new DataAnnotationsModelValidator(attribute.Object, stringLocalizer: null);
|
||||||
|
|
||||||
var validationContext = CreateValidationContext(modelExplorer);
|
var validationContext = CreateValidationContext(modelExplorer);
|
||||||
|
|
||||||
|
|
@ -184,7 +185,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
||||||
.Setup<ValidationResult>("IsValid", ItExpr.IsAny<object>(), ItExpr.IsAny<ValidationContext>())
|
.Setup<ValidationResult>("IsValid", ItExpr.IsAny<object>(), ItExpr.IsAny<ValidationContext>())
|
||||||
.Returns(new ValidationResult(errorMessage, new[] { "FirstName" }));
|
.Returns(new ValidationResult(errorMessage, new[] { "FirstName" }));
|
||||||
|
|
||||||
var validator = new DataAnnotationsModelValidator(attribute.Object);
|
var validator = new DataAnnotationsModelValidator(attribute.Object, stringLocalizer: null);
|
||||||
var validationContext = CreateValidationContext(modelExplorer);
|
var validationContext = CreateValidationContext(modelExplorer);
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
|
|
@ -207,7 +208,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
||||||
.Setup<ValidationResult>("IsValid", ItExpr.IsAny<object>(), ItExpr.IsAny<ValidationContext>())
|
.Setup<ValidationResult>("IsValid", ItExpr.IsAny<object>(), ItExpr.IsAny<ValidationContext>())
|
||||||
.Returns(new ValidationResult("Name error", new[] { "Name" }));
|
.Returns(new ValidationResult("Name error", new[] { "Name" }));
|
||||||
|
|
||||||
var validator = new DataAnnotationsModelValidator(attribute.Object);
|
var validator = new DataAnnotationsModelValidator(attribute.Object, stringLocalizer: null);
|
||||||
var validationContext = CreateValidationContext(modelExplorer);
|
var validationContext = CreateValidationContext(modelExplorer);
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
|
|
@ -217,15 +218,46 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
||||||
ModelValidationResult validationResult = Assert.Single(results);
|
ModelValidationResult validationResult = Assert.Single(results);
|
||||||
Assert.Equal("Name", validationResult.MemberName);
|
Assert.Equal("Name", validationResult.MemberName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ValidateWithIsValidFalse_StringLocalizerReturnsLocalizerErrorMessage()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var modelExplorer = _metadataProvider
|
||||||
|
.GetModelExplorerForType(typeof(string), "Hello")
|
||||||
|
.GetExplorerForProperty("Length");
|
||||||
|
|
||||||
|
var attribute = new Mock<ValidationAttribute> { CallBase = true };
|
||||||
|
attribute.Setup(a => a.IsValid(modelExplorer.Model)).Returns(false);
|
||||||
|
|
||||||
|
attribute.Object.ErrorMessage = "Length";
|
||||||
|
|
||||||
|
var localizedString = new LocalizedString("Length", "Longueur est invalide");
|
||||||
|
var stringLocalizer = new Mock<IStringLocalizer>();
|
||||||
|
stringLocalizer.Setup(s => s["Length"]).Returns(localizedString);
|
||||||
|
|
||||||
|
var validator = new DataAnnotationsModelValidator(attribute.Object, stringLocalizer.Object);
|
||||||
|
var validationContext = CreateValidationContext(modelExplorer);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = validator.Validate(validationContext);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
var validationResult = result.Single();
|
||||||
|
Assert.Equal("", validationResult.MemberName);
|
||||||
|
Assert.Equal("Longueur est invalide", validationResult.Message);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void IsRequiredTests()
|
public void IsRequiredTests()
|
||||||
{
|
{
|
||||||
// Arrange & Act & Assert
|
// Arrange & Act & Assert
|
||||||
Assert.False(new DataAnnotationsModelValidator(new RangeAttribute(10, 20)).IsRequired);
|
Assert.False(new DataAnnotationsModelValidator(new RangeAttribute(10, 20), stringLocalizer: null)
|
||||||
Assert.True(new DataAnnotationsModelValidator(new RequiredAttribute()).IsRequired);
|
.IsRequired);
|
||||||
Assert.True(new DataAnnotationsModelValidator(new DerivedRequiredAttribute()).IsRequired);
|
Assert.True(new DataAnnotationsModelValidator(new RequiredAttribute(), stringLocalizer: null).IsRequired);
|
||||||
|
Assert.True(new DataAnnotationsModelValidator(new DerivedRequiredAttribute(), stringLocalizer: null)
|
||||||
|
.IsRequired);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ModelValidationContext CreateValidationContext(ModelExplorer modelExplorer)
|
private static ModelValidationContext CreateValidationContext(ModelExplorer modelExplorer)
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,8 @@
|
||||||
using System.ComponentModel.DataAnnotations;
|
using System.ComponentModel.DataAnnotations;
|
||||||
using Microsoft.AspNet.Testing;
|
using Microsoft.AspNet.Testing;
|
||||||
using Microsoft.Framework.DependencyInjection;
|
using Microsoft.Framework.DependencyInjection;
|
||||||
|
using Microsoft.Framework.Localization;
|
||||||
|
using Moq;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
||||||
|
|
@ -18,7 +20,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
||||||
var provider = TestModelMetadataProvider.CreateDefaultProvider();
|
var provider = TestModelMetadataProvider.CreateDefaultProvider();
|
||||||
var metadata = provider.GetMetadataForProperty(typeof(string), "Length");
|
var metadata = provider.GetMetadataForProperty(typeof(string), "Length");
|
||||||
var attribute = new MaxLengthAttribute(10);
|
var attribute = new MaxLengthAttribute(10);
|
||||||
var adapter = new MaxLengthAttributeAdapter(attribute);
|
var adapter = new MaxLengthAttributeAdapter(attribute, stringLocalizer: null);
|
||||||
var serviceCollection = new ServiceCollection();
|
var serviceCollection = new ServiceCollection();
|
||||||
var requestServices = serviceCollection.BuildServiceProvider();
|
var requestServices = serviceCollection.BuildServiceProvider();
|
||||||
var context = new ClientModelValidationContext(metadata, provider, requestServices);
|
var context = new ClientModelValidationContext(metadata, provider, requestServices);
|
||||||
|
|
@ -44,7 +46,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
||||||
var provider = TestModelMetadataProvider.CreateDefaultProvider();
|
var provider = TestModelMetadataProvider.CreateDefaultProvider();
|
||||||
var metadata = provider.GetMetadataForProperty(typeof(string), propertyName);
|
var metadata = provider.GetMetadataForProperty(typeof(string), propertyName);
|
||||||
var attribute = new MaxLengthAttribute(5) { ErrorMessage = message };
|
var attribute = new MaxLengthAttribute(5) { ErrorMessage = message };
|
||||||
var adapter = new MaxLengthAttributeAdapter(attribute);
|
var adapter = new MaxLengthAttributeAdapter(attribute, stringLocalizer: null);
|
||||||
var serviceCollection = new ServiceCollection();
|
var serviceCollection = new ServiceCollection();
|
||||||
var requestServices = serviceCollection.BuildServiceProvider();
|
var requestServices = serviceCollection.BuildServiceProvider();
|
||||||
var context = new ClientModelValidationContext(metadata, provider, requestServices);
|
var context = new ClientModelValidationContext(metadata, provider, requestServices);
|
||||||
|
|
@ -59,5 +61,38 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
||||||
Assert.Equal(5, rule.ValidationParameters["max"]);
|
Assert.Equal(5, rule.ValidationParameters["max"]);
|
||||||
Assert.Equal("Length must be at most 5", rule.ErrorMessage);
|
Assert.Equal("Length must be at most 5", rule.ErrorMessage);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
#if DNX451
|
||||||
|
[Fact]
|
||||||
|
[ReplaceCulture]
|
||||||
|
public void ClientRulesWithMaxLengthAttribute_StringLocalizer_ReturnsLocalizedErrorString()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var provider = TestModelMetadataProvider.CreateDefaultProvider();
|
||||||
|
var metadata = provider.GetMetadataForProperty(typeof(string), "Length");
|
||||||
|
var errorKey = metadata.GetDisplayName();
|
||||||
|
var attribute = new MaxLengthAttribute(10);
|
||||||
|
attribute.ErrorMessage = errorKey;
|
||||||
|
|
||||||
|
var localizedString = new LocalizedString(errorKey, "Longueur est invalide");
|
||||||
|
var stringLocalizer = new Mock<IStringLocalizer>();
|
||||||
|
stringLocalizer.Setup(s => s[errorKey]).Returns(localizedString);
|
||||||
|
|
||||||
|
var adapter = new MaxLengthAttributeAdapter(attribute, stringLocalizer.Object);
|
||||||
|
var serviceCollection = new ServiceCollection();
|
||||||
|
var requestServices = serviceCollection.BuildServiceProvider();
|
||||||
|
var context = new ClientModelValidationContext(metadata, provider, requestServices);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var rules = adapter.GetClientValidationRules(context);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
var rule = Assert.Single(rules);
|
||||||
|
Assert.Equal("maxlength", rule.ValidationType);
|
||||||
|
Assert.Equal(1, rule.ValidationParameters.Count);
|
||||||
|
Assert.Equal(10, rule.ValidationParameters["max"]);
|
||||||
|
Assert.Equal("Longueur est invalide", rule.ErrorMessage);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -18,7 +18,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
||||||
var provider = TestModelMetadataProvider.CreateDefaultProvider();
|
var provider = TestModelMetadataProvider.CreateDefaultProvider();
|
||||||
var metadata = provider.GetMetadataForProperty(typeof(string), "Length");
|
var metadata = provider.GetMetadataForProperty(typeof(string), "Length");
|
||||||
var attribute = new MinLengthAttribute(6);
|
var attribute = new MinLengthAttribute(6);
|
||||||
var adapter = new MinLengthAttributeAdapter(attribute);
|
var adapter = new MinLengthAttributeAdapter(attribute, stringLocalizer: null);
|
||||||
var serviceCollection = new ServiceCollection();
|
var serviceCollection = new ServiceCollection();
|
||||||
var requestServices = serviceCollection.BuildServiceProvider();
|
var requestServices = serviceCollection.BuildServiceProvider();
|
||||||
var context = new ClientModelValidationContext(metadata, provider, requestServices);
|
var context = new ClientModelValidationContext(metadata, provider, requestServices);
|
||||||
|
|
@ -44,7 +44,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
||||||
var provider = TestModelMetadataProvider.CreateDefaultProvider();
|
var provider = TestModelMetadataProvider.CreateDefaultProvider();
|
||||||
var metadata = provider.GetMetadataForProperty(typeof(string), propertyName);
|
var metadata = provider.GetMetadataForProperty(typeof(string), propertyName);
|
||||||
var attribute = new MinLengthAttribute(2) { ErrorMessage = message };
|
var attribute = new MinLengthAttribute(2) { ErrorMessage = message };
|
||||||
var adapter = new MinLengthAttributeAdapter(attribute);
|
var adapter = new MinLengthAttributeAdapter(attribute, stringLocalizer: null);
|
||||||
var serviceCollection = new ServiceCollection();
|
var serviceCollection = new ServiceCollection();
|
||||||
var requestServices = serviceCollection.BuildServiceProvider();
|
var requestServices = serviceCollection.BuildServiceProvider();
|
||||||
var context = new ClientModelValidationContext(metadata, provider, requestServices);
|
var context = new ClientModelValidationContext(metadata, provider, requestServices);
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
||||||
var provider = TestModelMetadataProvider.CreateDefaultProvider();
|
var provider = TestModelMetadataProvider.CreateDefaultProvider();
|
||||||
var metadata = provider.GetMetadataForProperty(typeof(string), "Length");
|
var metadata = provider.GetMetadataForProperty(typeof(string), "Length");
|
||||||
var attribute = new RangeAttribute(typeof(decimal), "0", "100");
|
var attribute = new RangeAttribute(typeof(decimal), "0", "100");
|
||||||
var adapter = new RangeAttributeAdapter(attribute);
|
var adapter = new RangeAttributeAdapter(attribute, stringLocalizer: null);
|
||||||
var serviceCollection = new ServiceCollection();
|
var serviceCollection = new ServiceCollection();
|
||||||
var requestServices = serviceCollection.BuildServiceProvider();
|
var requestServices = serviceCollection.BuildServiceProvider();
|
||||||
var context = new ClientModelValidationContext(metadata, provider, requestServices);
|
var context = new ClientModelValidationContext(metadata, provider, requestServices);
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
||||||
var provider = TestModelMetadataProvider.CreateDefaultProvider();
|
var provider = TestModelMetadataProvider.CreateDefaultProvider();
|
||||||
var metadata = provider.GetMetadataForProperty(typeof(string), "Length");
|
var metadata = provider.GetMetadataForProperty(typeof(string), "Length");
|
||||||
var attribute = new RequiredAttribute();
|
var attribute = new RequiredAttribute();
|
||||||
var adapter = new RequiredAttributeAdapter(attribute);
|
var adapter = new RequiredAttributeAdapter(attribute, stringLocalizer: null);
|
||||||
var serviceCollection = new ServiceCollection();
|
var serviceCollection = new ServiceCollection();
|
||||||
var requestServices = serviceCollection.BuildServiceProvider();
|
var requestServices = serviceCollection.BuildServiceProvider();
|
||||||
var context = new ClientModelValidationContext(metadata, provider, requestServices);
|
var context = new ClientModelValidationContext(metadata, provider, requestServices);
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
||||||
var provider = TestModelMetadataProvider.CreateDefaultProvider();
|
var provider = TestModelMetadataProvider.CreateDefaultProvider();
|
||||||
var metadata = provider.GetMetadataForProperty(typeof(string), "Length");
|
var metadata = provider.GetMetadataForProperty(typeof(string), "Length");
|
||||||
var attribute = new StringLengthAttribute(8);
|
var attribute = new StringLengthAttribute(8);
|
||||||
var adapter = new StringLengthAttributeAdapter(attribute);
|
var adapter = new StringLengthAttributeAdapter(attribute, stringLocalizer: null);
|
||||||
var serviceCollection = new ServiceCollection();
|
var serviceCollection = new ServiceCollection();
|
||||||
var requestServices = serviceCollection.BuildServiceProvider();
|
var requestServices = serviceCollection.BuildServiceProvider();
|
||||||
var context = new ClientModelValidationContext(metadata, provider, requestServices);
|
var context = new ClientModelValidationContext(metadata, provider, requestServices);
|
||||||
|
|
@ -42,7 +42,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
||||||
var provider = TestModelMetadataProvider.CreateDefaultProvider();
|
var provider = TestModelMetadataProvider.CreateDefaultProvider();
|
||||||
var metadata = provider.GetMetadataForProperty(typeof(string), "Length");
|
var metadata = provider.GetMetadataForProperty(typeof(string), "Length");
|
||||||
var attribute = new StringLengthAttribute(10) { MinimumLength = 3 };
|
var attribute = new StringLengthAttribute(10) { MinimumLength = 3 };
|
||||||
var adapter = new StringLengthAttributeAdapter(attribute);
|
var adapter = new StringLengthAttributeAdapter(attribute, stringLocalizer: null);
|
||||||
var serviceCollection = new ServiceCollection();
|
var serviceCollection = new ServiceCollection();
|
||||||
var requestServices = serviceCollection.BuildServiceProvider();
|
var requestServices = serviceCollection.BuildServiceProvider();
|
||||||
var context = new ClientModelValidationContext(metadata, provider, requestServices);
|
var context = new ClientModelValidationContext(metadata, provider, requestServices);
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ using System.Reflection;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNet.Testing;
|
using Microsoft.AspNet.Testing;
|
||||||
using Microsoft.Net.Http.Headers;
|
using Microsoft.Net.Http.Headers;
|
||||||
|
using Newtonsoft.Json;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Mvc.FunctionalTests
|
namespace Microsoft.AspNet.Mvc.FunctionalTests
|
||||||
|
|
@ -121,5 +122,32 @@ Salut John ! Vous êtes en 2015 an aujourd'hui est Thursday";
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Equal(expected, body.Trim());
|
Assert.Equal(expected, body.Trim());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task Localization_InvalidModel_ValidationAttributes_ReturnsLocalizedErrorMessage()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var expected =
|
||||||
|
@"<span class=""field-validation-error"" data-valmsg-for=""Name"" data-valmsg-replace=""true"">Nom non valide. Longueur minimale de nom est 4</span>
|
||||||
|
<span class=""field-validation-error"" data-valmsg-for=""Product.ProductName"" data-valmsg-replace=""true"">Nom du produit est invalide</span>
|
||||||
|
<div class=""editor-label""><label for=""Name"">Name</label></div>
|
||||||
|
<div class=""editor-field""><input class=""input-validation-error text-box single-line"" data-val=""true"" data-val-minlength=""Nom non valide. Longueur minimale de nom est 4"" data-val-minlength-min=""4"" id=""Name"" name=""Name"" type=""text"" value=""A"" /> <span class=""field-validation-error"" data-valmsg-for=""Name"" data-valmsg-replace=""true"">Nom non valide. Longueur minimale de nom est 4</span></div>
|
||||||
|
|
||||||
|
<div class=""editor-label""><label for=""Product_ProductName"">ProductName</label></div>
|
||||||
|
<div class=""editor-field""><input class=""input-validation-error text-box single-line"" data-val=""true"" data-val-required=""Nom du produit est invalide"" id=""Product_ProductName"" name=""Product.ProductName"" type=""text"" value="""" /> <span class=""field-validation-error"" data-valmsg-for=""Product.ProductName"" data-valmsg-replace=""true"">Nom du produit est invalide</span></div>";
|
||||||
|
|
||||||
|
var cultureCookie = "c=fr|uic=fr";
|
||||||
|
var request = new HttpRequestMessage(HttpMethod.Get, "http://localhost/Home/GetInvalidUser");
|
||||||
|
request.Headers.Add(
|
||||||
|
"Cookie",
|
||||||
|
new CookieHeaderValue("ASPNET_CULTURE", cultureCookie).ToString());
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var response = await Client.SendAsync(request);
|
||||||
|
var body = await response.Content.ReadAsStringAsync();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(expected, body.Trim(), ignoreLineEndingDifferences: true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,11 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
// 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.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using System;
|
|
||||||
using Microsoft.AspNet.Mvc.DataAnnotations.Internal;
|
using Microsoft.AspNet.Mvc.DataAnnotations.Internal;
|
||||||
using Microsoft.AspNet.Mvc.Formatters.Json.Internal;
|
using Microsoft.AspNet.Mvc.Formatters.Json.Internal;
|
||||||
using Microsoft.AspNet.Mvc.Internal;
|
using Microsoft.AspNet.Mvc.Internal;
|
||||||
|
using Microsoft.AspNet.Mvc.TestCommon;
|
||||||
|
using Microsoft.Framework.DependencyInjection;
|
||||||
using Microsoft.Framework.OptionsModel;
|
using Microsoft.Framework.OptionsModel;
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Mvc.IntegrationTests
|
namespace Microsoft.AspNet.Mvc.IntegrationTests
|
||||||
|
|
@ -15,7 +16,10 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
|
||||||
{
|
{
|
||||||
Value = new MvcOptions();
|
Value = new MvcOptions();
|
||||||
MvcCoreMvcOptionsSetup.ConfigureMvc(Value);
|
MvcCoreMvcOptionsSetup.ConfigureMvc(Value);
|
||||||
MvcDataAnnotationsMvcOptionsSetup.ConfigureMvc(Value);
|
var collection = new ServiceCollection().AddOptions();
|
||||||
|
MvcDataAnnotationsMvcOptionsSetup.ConfigureMvc(
|
||||||
|
Value,
|
||||||
|
collection.BuildServiceProvider());
|
||||||
MvcJsonMvcOptionsSetup.ConfigureMvc(Value, SerializerSettingsProvider.CreateSerializerSettings());
|
MvcJsonMvcOptionsSetup.ConfigureMvc(Value, SerializerSettingsProvider.CreateSerializerSettings());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,9 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
||||||
var providers = new IClientModelValidatorProvider[]
|
var providers = new IClientModelValidatorProvider[]
|
||||||
{
|
{
|
||||||
new DefaultClientModelValidatorProvider(),
|
new DefaultClientModelValidatorProvider(),
|
||||||
new DataAnnotationsClientModelValidatorProvider(),
|
new DataAnnotationsClientModelValidatorProvider(
|
||||||
|
new TestOptionsManager<MvcDataAnnotationsLocalizationOptions>(),
|
||||||
|
stringLocalizerFactory: null),
|
||||||
};
|
};
|
||||||
|
|
||||||
return new TestClientModelValidatorProvider(providers);
|
return new TestClientModelValidatorProvider(providers);
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,9 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
||||||
var providers = new IModelValidatorProvider[]
|
var providers = new IModelValidatorProvider[]
|
||||||
{
|
{
|
||||||
new DefaultModelValidatorProvider(),
|
new DefaultModelValidatorProvider(),
|
||||||
new DataAnnotationsModelValidatorProvider(),
|
new DataAnnotationsModelValidatorProvider(
|
||||||
|
new TestOptionsManager<MvcDataAnnotationsLocalizationOptions>(),
|
||||||
|
stringLocalizerFactory: null),
|
||||||
};
|
};
|
||||||
|
|
||||||
return new TestModelValidatorProvider(providers);
|
return new TestModelValidatorProvider(providers);
|
||||||
|
|
|
||||||
|
|
@ -1753,7 +1753,9 @@ namespace Microsoft.AspNet.Mvc.Test
|
||||||
{
|
{
|
||||||
ModelBinder = binder,
|
ModelBinder = binder,
|
||||||
ValueProvider = provider,
|
ValueProvider = provider,
|
||||||
ValidatorProvider = new DataAnnotationsModelValidatorProvider()
|
ValidatorProvider = new DataAnnotationsModelValidatorProvider(
|
||||||
|
options: null,
|
||||||
|
stringLocalizerFactory: null)
|
||||||
};
|
};
|
||||||
|
|
||||||
return new TestableController()
|
return new TestableController()
|
||||||
|
|
|
||||||
|
|
@ -219,7 +219,13 @@ namespace Microsoft.AspNet.Mvc.Rendering
|
||||||
{
|
{
|
||||||
options.HtmlHelperOptions.IdAttributeDotReplacement = idAttributeDotReplacement;
|
options.HtmlHelperOptions.IdAttributeDotReplacement = idAttributeDotReplacement;
|
||||||
}
|
}
|
||||||
options.ClientModelValidatorProviders.Add(new DataAnnotationsClientModelValidatorProvider());
|
var localizationOptionsAccesor = new Mock<IOptions<MvcDataAnnotationsLocalizationOptions>>();
|
||||||
|
|
||||||
|
localizationOptionsAccesor.SetupGet(o => o.Value).Returns(new MvcDataAnnotationsLocalizationOptions());
|
||||||
|
|
||||||
|
options.ClientModelValidatorProviders.Add(new DataAnnotationsClientModelValidatorProvider(
|
||||||
|
localizationOptionsAccesor.Object,
|
||||||
|
stringLocalizerFactory: null));
|
||||||
var optionsAccessor = new Mock<IOptions<MvcViewOptions>>();
|
var optionsAccessor = new Mock<IOptions<MvcViewOptions>>();
|
||||||
optionsAccessor
|
optionsAccessor
|
||||||
.SetupGet(o => o.Value)
|
.SetupGet(o => o.Value)
|
||||||
|
|
@ -235,6 +241,9 @@ namespace Microsoft.AspNet.Mvc.Rendering
|
||||||
serviceProvider
|
serviceProvider
|
||||||
.Setup(s => s.GetService(typeof(IViewComponentHelper)))
|
.Setup(s => s.GetService(typeof(IViewComponentHelper)))
|
||||||
.Returns(new Mock<IViewComponentHelper>().Object);
|
.Returns(new Mock<IViewComponentHelper>().Object);
|
||||||
|
serviceProvider
|
||||||
|
.Setup(s => s.GetService(typeof(IViewComponentHelper)))
|
||||||
|
.Returns(new Mock<IViewComponentHelper>().Object);
|
||||||
|
|
||||||
httpContext.RequestServices = serviceProvider.Object;
|
httpContext.RequestServices = serviceProvider.Object;
|
||||||
if (htmlGenerator == null)
|
if (htmlGenerator == null)
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
// 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.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using LocalizationWebSite.Models;
|
||||||
using Microsoft.AspNet.Mvc;
|
using Microsoft.AspNet.Mvc;
|
||||||
using Microsoft.AspNet.Mvc.Localization;
|
using Microsoft.AspNet.Mvc.Localization;
|
||||||
|
|
||||||
|
|
@ -25,5 +26,17 @@ namespace LocalizationWebSite.Controllers
|
||||||
ViewData["Message"] = _localizer["Learn More"];
|
ViewData["Message"] = _localizer["Learn More"];
|
||||||
return View();
|
return View();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public IActionResult GetInvalidUser()
|
||||||
|
{
|
||||||
|
var user = new User
|
||||||
|
{
|
||||||
|
Name = "A",
|
||||||
|
Product = new Product()
|
||||||
|
};
|
||||||
|
|
||||||
|
TryValidateModel(user);
|
||||||
|
return View(user);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
// 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.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
|
namespace LocalizationWebSite.Models
|
||||||
|
{
|
||||||
|
public class User
|
||||||
|
{
|
||||||
|
[MinLength(4, ErrorMessage = "Name")]
|
||||||
|
public string Name { get; set; }
|
||||||
|
|
||||||
|
public Product Product { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Product
|
||||||
|
{
|
||||||
|
[Required(ErrorMessage = "ProductName")]
|
||||||
|
public string ProductName { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,123 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<root>
|
||||||
|
<!--
|
||||||
|
Microsoft ResX Schema
|
||||||
|
|
||||||
|
Version 2.0
|
||||||
|
|
||||||
|
The primary goals of this format is to allow a simple XML format
|
||||||
|
that is mostly human readable. The generation and parsing of the
|
||||||
|
various data types are done through the TypeConverter classes
|
||||||
|
associated with the data types.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
... ado.net/XML headers & schema ...
|
||||||
|
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||||
|
<resheader name="version">2.0</resheader>
|
||||||
|
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||||
|
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||||
|
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||||
|
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||||
|
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||||
|
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||||
|
</data>
|
||||||
|
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||||
|
<comment>This is a comment</comment>
|
||||||
|
</data>
|
||||||
|
|
||||||
|
There are any number of "resheader" rows that contain simple
|
||||||
|
name/value pairs.
|
||||||
|
|
||||||
|
Each data row contains a name, and value. The row also contains a
|
||||||
|
type or mimetype. Type corresponds to a .NET class that support
|
||||||
|
text/value conversion through the TypeConverter architecture.
|
||||||
|
Classes that don't support this are serialized and stored with the
|
||||||
|
mimetype set.
|
||||||
|
|
||||||
|
The mimetype is used for serialized objects, and tells the
|
||||||
|
ResXResourceReader how to depersist the object. This is currently not
|
||||||
|
extensible. For a given mimetype the value must be set accordingly:
|
||||||
|
|
||||||
|
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||||
|
that the ResXResourceWriter will generate, however the reader can
|
||||||
|
read any of the formats listed below.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.binary.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.soap.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||||
|
value : The object must be serialized into a byte array
|
||||||
|
: using a System.ComponentModel.TypeConverter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
-->
|
||||||
|
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||||
|
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||||
|
<xsd:element name="root" msdata:IsDataSet="true">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:choice maxOccurs="unbounded">
|
||||||
|
<xsd:element name="metadata">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="assembly">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:attribute name="alias" type="xsd:string" />
|
||||||
|
<xsd:attribute name="name" type="xsd:string" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="data">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="resheader">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:choice>
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:schema>
|
||||||
|
<resheader name="resmimetype">
|
||||||
|
<value>text/microsoft-resx</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="version">
|
||||||
|
<value>2.0</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="reader">
|
||||||
|
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="writer">
|
||||||
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<data name="ProductName" xml:space="preserve">
|
||||||
|
<value>Nom du produit est invalide</value>
|
||||||
|
</data>
|
||||||
|
</root>
|
||||||
|
|
@ -0,0 +1,123 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<root>
|
||||||
|
<!--
|
||||||
|
Microsoft ResX Schema
|
||||||
|
|
||||||
|
Version 2.0
|
||||||
|
|
||||||
|
The primary goals of this format is to allow a simple XML format
|
||||||
|
that is mostly human readable. The generation and parsing of the
|
||||||
|
various data types are done through the TypeConverter classes
|
||||||
|
associated with the data types.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
... ado.net/XML headers & schema ...
|
||||||
|
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||||
|
<resheader name="version">2.0</resheader>
|
||||||
|
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||||
|
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||||
|
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||||
|
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||||
|
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||||
|
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||||
|
</data>
|
||||||
|
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||||
|
<comment>This is a comment</comment>
|
||||||
|
</data>
|
||||||
|
|
||||||
|
There are any number of "resheader" rows that contain simple
|
||||||
|
name/value pairs.
|
||||||
|
|
||||||
|
Each data row contains a name, and value. The row also contains a
|
||||||
|
type or mimetype. Type corresponds to a .NET class that support
|
||||||
|
text/value conversion through the TypeConverter architecture.
|
||||||
|
Classes that don't support this are serialized and stored with the
|
||||||
|
mimetype set.
|
||||||
|
|
||||||
|
The mimetype is used for serialized objects, and tells the
|
||||||
|
ResXResourceReader how to depersist the object. This is currently not
|
||||||
|
extensible. For a given mimetype the value must be set accordingly:
|
||||||
|
|
||||||
|
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||||
|
that the ResXResourceWriter will generate, however the reader can
|
||||||
|
read any of the formats listed below.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.binary.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.soap.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||||
|
value : The object must be serialized into a byte array
|
||||||
|
: using a System.ComponentModel.TypeConverter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
-->
|
||||||
|
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||||
|
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||||
|
<xsd:element name="root" msdata:IsDataSet="true">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:choice maxOccurs="unbounded">
|
||||||
|
<xsd:element name="metadata">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="assembly">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:attribute name="alias" type="xsd:string" />
|
||||||
|
<xsd:attribute name="name" type="xsd:string" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="data">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="resheader">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:choice>
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:schema>
|
||||||
|
<resheader name="resmimetype">
|
||||||
|
<value>text/microsoft-resx</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="version">
|
||||||
|
<value>2.0</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="reader">
|
||||||
|
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="writer">
|
||||||
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<data name="Name" xml:space="preserve">
|
||||||
|
<value>Nom non valide. Longueur minimale de nom est 4</value>
|
||||||
|
</data>
|
||||||
|
</root>
|
||||||
|
|
@ -10,7 +10,10 @@ namespace LocalizationWebSite
|
||||||
{
|
{
|
||||||
public void ConfigureServices(IServiceCollection services)
|
public void ConfigureServices(IServiceCollection services)
|
||||||
{
|
{
|
||||||
services.AddMvc().AddViewLocalization(options => options.ResourcesPath = "Resources");
|
services
|
||||||
|
.AddMvc()
|
||||||
|
.AddViewLocalization(options => options.ResourcesPath = "Resources")
|
||||||
|
.AddDataAnnotationsLocalization();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Configure(IApplicationBuilder app)
|
public void Configure(IApplicationBuilder app)
|
||||||
|
|
@ -18,7 +21,7 @@ namespace LocalizationWebSite
|
||||||
app.UseCultureReplacer();
|
app.UseCultureReplacer();
|
||||||
|
|
||||||
app.UseRequestLocalization();
|
app.UseRequestLocalization();
|
||||||
|
|
||||||
app.UseMvcWithDefaultRoute();
|
app.UseMvcWithDefaultRoute();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
@model LocalizationWebSite.Models.User
|
||||||
|
|
||||||
|
@Html.ValidationMessage("Name")
|
||||||
|
@Html.ValidationMessage("Product.ProductName")
|
||||||
|
@Html.EditorForModel()
|
||||||
|
@Html.EditorFor(model => model.Product)
|
||||||
|
|
||||||
|
|
||||||
Loading…
Reference in New Issue