Browse Source

Implemented AbpValidationHtmlAttributeProvider

pull/3834/head
Halil İbrahim Kalkan 7 years ago
parent
commit
932410b2fb
  1. 1
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpMvcOptionsExtensions.cs
  2. 74
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ModelBinding/AbpModelExpressionProvider.cs
  3. 53
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ModelBinding/Metadata/AbpExtraPropertyValidationMetadataProvider.cs
  4. 98
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ViewFeatures/AbpValidationHtmlAttributeProvider.cs

1
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpMvcOptionsExtensions.cs

@ -57,7 +57,6 @@ namespace Volo.Abp.AspNetCore.Mvc
options.ModelMetadataDetailsProviders.Add(
new AbpDataAnnotationAutoLocalizationMetadataDetailsProvider(services)
);
options.ModelMetadataDetailsProviders.Add(new AbpExtraPropertyValidationMetadataProvider());
}
}
}

74
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ModelBinding/AbpModelExpressionProvider.cs

@ -1,74 +0,0 @@
using System;
using System.Linq;
using System.Linq.Expressions;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Volo.Abp.AspNetCore.Mvc.ModelBinding.Metadata;
using Volo.Abp.Data;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.AspNetCore.Mvc.ModelBinding
{
[Dependency(ReplaceServices = true)]
public class AbpModelExpressionProvider : IModelExpressionProvider, ITransientDependency
{
private readonly ModelExpressionProvider _modelExpressionProvider;
public AbpModelExpressionProvider(ModelExpressionProvider modelExpressionProvider)
{
_modelExpressionProvider = modelExpressionProvider;
}
public ModelExpression CreateModelExpression<TModel, TValue>(
ViewDataDictionary<TModel> viewData,
Expression<Func<TModel, TValue>> expression)
{
var result = _modelExpressionProvider.CreateModelExpression(
viewData,
expression
);
AbpExtraPropertyValidationMetadataProvider.CurrentModeInfo.Value = null;
if (result.ModelExplorer.Container == null)
{
return result;
}
var extraPropertyName = ExtraPropertyBindingHelper.ExtractExtraPropertyName(result.Name);
if (extraPropertyName == null)
{
return result;
}
var containerName = ExtraPropertyBindingHelper.ExtractContainerName(result.Name);
if (containerName == null)
{
return result;
}
var containerModelExpolorer = result
.ModelExplorer
.Container
.Properties
.FirstOrDefault(p => p.Metadata.Name == containerName);
if (containerModelExpolorer == null)
{
return result;
}
if (!containerModelExpolorer.ModelType.IsAssignableTo<IHasExtraProperties>())
{
return result;
}
AbpExtraPropertyValidationMetadataProvider.CurrentModeInfo.Value
= new AbpExtraPropertyValidationMetadataProvider.ExtraPropertyModelInfo(
containerModelExpolorer.ModelType,
extraPropertyName
);
return result;
}
}
}

53
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ModelBinding/Metadata/AbpExtraPropertyValidationMetadataProvider.cs

@ -1,53 +0,0 @@
using System;
using System.Threading;
using Microsoft.AspNetCore.Mvc.ModelBinding.Metadata;
using Volo.Abp.ObjectExtending;
namespace Volo.Abp.AspNetCore.Mvc.ModelBinding.Metadata
{
public class AbpExtraPropertyValidationMetadataProvider : IValidationMetadataProvider
{
public static AsyncLocal<ExtraPropertyModelInfo> CurrentModeInfo { get; } = new AsyncLocal<ExtraPropertyModelInfo>();
public void CreateValidationMetadata(ValidationMetadataProviderContext context)
{
if (CurrentModeInfo.Value == null)
{
return;
}
var currentModel = CurrentModeInfo.Value;
CurrentModeInfo.Value = null;
var propertyInfo = ObjectExtensionManager.Instance.GetPropertyOrNull(
currentModel.ExtensibleObjectType,
currentModel.PropertyName
);
if (propertyInfo == null)
{
return;
}
foreach (var validationAttribute in propertyInfo.ValidationAttributes)
{
context.ValidationMetadata.ValidatorMetadata.Add(validationAttribute);
}
}
public class ExtraPropertyModelInfo
{
public Type ExtensibleObjectType { get; }
public string PropertyName { get; }
public ExtraPropertyModelInfo(
Type extensibleObjectType,
string propertyName)
{
ExtensibleObjectType = extensibleObjectType;
PropertyName = propertyName;
}
}
}
}

98
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ViewFeatures/AbpValidationHtmlAttributeProvider.cs

@ -0,0 +1,98 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Reflection;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.DataAnnotations;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.AspNetCore.Mvc.ModelBinding.Metadata;
using Microsoft.AspNetCore.Mvc.ModelBinding.Validation;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Microsoft.Extensions.Localization;
using Microsoft.Extensions.Options;
using Volo.Abp.AspNetCore.Mvc.ModelBinding;
using Volo.Abp.DependencyInjection;
using Volo.Abp.ObjectExtending;
using Volo.Abp.Validation.Localization;
namespace Volo.Abp.AspNetCore.Mvc.ViewFeatures
{
[Dependency(ReplaceServices = true)]
[ExposeServices(typeof(ValidationHtmlAttributeProvider))]
public class AbpValidationHtmlAttributeProvider
: DefaultValidationHtmlAttributeProvider, ISingletonDependency
{
private readonly IModelMetadataProvider _metadataProvider;
private readonly IStringLocalizerFactory _stringLocalizerFactory;
private readonly IStringLocalizer<AbpValidationResource> _validationStringLocalizer;
private readonly IValidationAttributeAdapterProvider _validationAttributeAdapterProvider;
public AbpValidationHtmlAttributeProvider(
IOptions<MvcViewOptions> optionsAccessor,
IModelMetadataProvider metadataProvider,
ClientValidatorCache clientValidatorCache,
IValidationAttributeAdapterProvider validationAttributeAdapterProvider,
IStringLocalizerFactory stringLocalizerFactory,
IStringLocalizer<AbpValidationResource> validationStringLocalizer)
: base(
optionsAccessor,
metadataProvider,
clientValidatorCache)
{
_metadataProvider = metadataProvider;
_validationAttributeAdapterProvider = validationAttributeAdapterProvider;
_stringLocalizerFactory = stringLocalizerFactory;
_validationStringLocalizer = validationStringLocalizer;
}
public override void AddValidationAttributes(
ViewContext viewContext,
ModelExplorer modelExplorer,
IDictionary<string, string> attributes)
{
base.AddValidationAttributes(viewContext, modelExplorer, attributes);
var nameAttribute = attributes.GetOrDefault("name");
var propertyName = ExtraPropertyBindingHelper.ExtractExtraPropertyName(nameAttribute);
if (propertyName == null)
{
return;
}
//NOTE: containerName can be null on controller actions..?
var containerName = ExtraPropertyBindingHelper.ExtractContainerName(nameAttribute);
if (containerName == null)
{
return;
}
var extensibleObjectType = modelExplorer.Container.ModelType
.GetProperty(containerName, BindingFlags.Instance | BindingFlags.Public)
.PropertyType;
var propertyInfo = ObjectExtensionManager.Instance.GetPropertyOrNull(extensibleObjectType, propertyName);
modelExplorer.Metadata.As<DefaultModelMetadata>().DisplayMetadata.DisplayName = () => propertyInfo.DisplayName.Localize(_stringLocalizerFactory);
foreach (var validationAttribute in propertyInfo.ValidationAttributes)
{
var validationContext = new ClientModelValidationContext(
viewContext,
modelExplorer.Metadata,
_metadataProvider,
attributes);
validationAttribute.ErrorMessage = ValidationAttributeErrorMessageStringProperty.GetValue(validationAttribute) as string;
_validationAttributeAdapterProvider.GetAttributeAdapter(validationAttribute, _validationStringLocalizer)
.AddValidation(validationContext);
}
}
private static readonly PropertyInfo ValidationAttributeErrorMessageStringProperty = typeof(ValidationAttribute)
.GetProperty("ErrorMessageString", BindingFlags.Instance | BindingFlags.NonPublic);
}
}
Loading…
Cancel
Save