mirror of https://github.com/abpframework/abp.git
4 changed files with 98 additions and 128 deletions
@ -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; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -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; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -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…
Reference in new issue