using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Globalization; using Microsoft.AspNetCore.Mvc.DataAnnotations; using Microsoft.AspNetCore.Mvc.ModelBinding.Validation; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Localization; using Microsoft.Extensions.Options; namespace Infrastructure.Web.DataAnnotations { [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = false)] public sealed class MustBeTrueAttribute : ValidationAttribute, IClientModelValidator { private IStringLocalizer _stringLocalizer; private bool _checkedForLocalizer; public override bool IsValid(object value) { return value != null && (bool)value; } public void AddValidation(ClientModelValidationContext context) { if (context == null) { throw new ArgumentNullException(nameof(context)); } MergeAttribute(context.Attributes, "data-val", "true"); CheckForLocalizer(context); var errorMessage = GetErrorMessage(context.ModelMetadata.GetDisplayName()); MergeAttribute(context.Attributes, "data-val-mustbetrue", errorMessage); } private string GetErrorMessage(string displayName) { if (_stringLocalizer != null && !string.IsNullOrEmpty(ErrorMessage) && string.IsNullOrEmpty(ErrorMessageResourceName) && ErrorMessageResourceType == null) { return _stringLocalizer[ErrorMessage, displayName]; } return FormatErrorMessage(displayName); } private void CheckForLocalizer(ClientModelValidationContext context) { if (!_checkedForLocalizer) { _checkedForLocalizer = true; var services = context.ActionContext.HttpContext.RequestServices; var options = services.GetRequiredService>(); var factory = services.GetService(); var provider = options.Value.DataAnnotationLocalizerProvider; if (factory != null && provider != null) { _stringLocalizer = provider( context.ModelMetadata.ContainerType ?? context.ModelMetadata.ModelType, factory); } } } private bool MergeAttribute( IDictionary attributes, string key, string value) { if (attributes.ContainsKey(key)) { return false; } attributes.Add(key, value); return true; } public override string FormatErrorMessage(string name) { return string.Format(CultureInfo.CurrentCulture, ErrorMessageString, name); } } }