Browse Source

Added AbpModelExpressionProvider and AbpExtraPropertyValidationMetadataProvider

pull/3834/head
Halil İbrahim Kalkan 7 years ago
parent
commit
660ce383fb
  1. 2
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpMvcOptionsExtensions.cs
  2. 16
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ModelBinding/AbpExtraPropertyModelBinder.cs
  3. 37
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ModelBinding/ExtraPropertyBindingHelper.cs
  4. 53
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ModelBinding/Metadata/AbpExtraPropertyValidationMetadataProvider.cs
  5. 72
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ModelBinding/MyModelExpressionProvider.cs
  6. 14
      framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/ObjectExtensionManagerExtensions.cs

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

@ -5,6 +5,7 @@ using Volo.Abp.AspNetCore.Mvc.Conventions;
using Volo.Abp.AspNetCore.Mvc.ExceptionHandling;
using Volo.Abp.AspNetCore.Mvc.Features;
using Volo.Abp.AspNetCore.Mvc.ModelBinding;
using Volo.Abp.AspNetCore.Mvc.ModelBinding.Metadata;
using Volo.Abp.AspNetCore.Mvc.Response;
using Volo.Abp.AspNetCore.Mvc.Uow;
using Volo.Abp.AspNetCore.Mvc.Validation;
@ -56,6 +57,7 @@ namespace Volo.Abp.AspNetCore.Mvc
options.ModelMetadataDetailsProviders.Add(
new AbpDataAnnotationAutoLocalizationMetadataDetailsProvider(services)
);
options.ModelMetadataDetailsProviders.Add(new AbpExtraPropertyValidationMetadataProvider());
}
}
}

16
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ModelBinding/AbpExtraPropertyModelBinder.cs

@ -47,7 +47,7 @@ namespace Volo.Abp.AspNetCore.Mvc.ModelBinding
return value;
}
var propertyName = ExtractExtraPropertyName(bindingContext.ModelName);
var propertyName = ExtraPropertyBindingHelper.ExtractExtraPropertyName(bindingContext.ModelName);
if (propertyName == null)
{
return value;
@ -61,19 +61,5 @@ namespace Volo.Abp.AspNetCore.Mvc.ModelBinding
return Convert.ChangeType(value, propertyInfo.Type);
}
/* modelName is a string like "UserInfo.ExtraProperties[SocialSecurityNumber]"
* This method returns "SocialSecurityNumber" for this example. */
protected virtual string ExtractExtraPropertyName(string modelName)
{
//TODO: Use regex(?) and add unit test (by extracting to a helper class)
var index = modelName.IndexOf(".ExtraProperties[", StringComparison.Ordinal);
if (index < 0)
{
return null;
}
return modelName.Substring(index + 17, modelName.Length - index - 18);
}
}
}

37
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ModelBinding/ExtraPropertyBindingHelper.cs

@ -0,0 +1,37 @@
using System;
namespace Volo.Abp.AspNetCore.Mvc.ModelBinding
{
public static class ExtraPropertyBindingHelper
{
/// <summary>
/// modelName is a string like "UserInfo.ExtraProperties[SocialSecurityNumber]"
/// This method returns "SocialSecurityNumber" for this example. */
/// </summary>
public static string ExtractExtraPropertyName(string modelName)
{
var index = modelName.IndexOf(".ExtraProperties[", StringComparison.Ordinal);
if (index < 0)
{
return null;
}
return modelName.Substring(index + 17, modelName.Length - index - 18);
}
/// <summary>
/// modelName is a string like "UserInfo.ExtraProperties[SocialSecurityNumber]"
/// This method returns "UserInfo" for this example.
/// </summary>
public static string ExtractContainerName(string modelName)
{
var index = modelName.IndexOf(".ExtraProperties[", StringComparison.Ordinal);
if (index < 0)
{
return null;
}
return modelName.Left(index);
}
}
}

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

@ -0,0 +1,53 @@
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;
}
}
}
}

72
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ModelBinding/MyModelExpressionProvider.cs

@ -0,0 +1,72 @@
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
);
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;
}
}
}

14
framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/ObjectExtensionManagerExtensions.cs

@ -79,5 +79,19 @@ namespace Volo.Abp.ObjectExtending
);
});
}
public static ObjectExtensionPropertyInfo GetPropertyOrNull(
[NotNull] this ObjectExtensionManager objectExtensionManager,
[NotNull] Type objectType,
[NotNull] string propertyName)
{
Check.NotNull(objectExtensionManager, nameof(objectExtensionManager));
Check.NotNull(objectType, nameof(objectType));
Check.NotNull(propertyName, nameof(propertyName));
return objectExtensionManager
.GetOrNull(objectType)?
.GetPropertyOrNull(propertyName);
}
}
}
Loading…
Cancel
Save