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