Browse Source

Added binder for extra properties

pull/3834/head
Halil İbrahim Kalkan 6 years ago
parent
commit
de81fca5db
  1. 1
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpMvcOptionsExtensions.cs
  2. 48
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ModelBinding/AbpExtraPropertiesDictionaryModelBinderProvider.cs
  3. 79
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ModelBinding/AbpExtraPropertyModelBinder.cs

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

@ -48,6 +48,7 @@ namespace Volo.Abp.AspNetCore.Mvc
private static void AddModelBinders(MvcOptions options)
{
options.ModelBinderProviders.Insert(0, new AbpDateTimeModelBinderProvider());
options.ModelBinderProviders.Insert(0, new AbpExtraPropertiesDictionaryModelBinderProvider());
}
private static void AddMetadataProviders(MvcOptions options, IServiceCollection services)

48
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ModelBinding/AbpExtraPropertiesDictionaryModelBinderProvider.cs

@ -0,0 +1,48 @@
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.AspNetCore.Mvc.ModelBinding.Binders;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Volo.Abp.Data;
namespace Volo.Abp.AspNetCore.Mvc.ModelBinding
{
public class AbpExtraPropertiesDictionaryModelBinderProvider : IModelBinderProvider
{
public IModelBinder GetBinder(ModelBinderProviderContext context)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
if (context.Metadata.ModelType != typeof(Dictionary<string, object>))
{
return null;
}
if (!context.Metadata.ContainerType.IsAssignableTo<IHasExtraProperties>())
{
return null;
}
var binderType = typeof(DictionaryModelBinder<string, object>);
var keyBinder = context.CreateBinder(context.MetadataProvider.GetMetadataForType(typeof(string)));
var valueBinder = new AbpExtraPropertyModelBinder(context.Metadata.ContainerType);
var loggerFactory = context.Services.GetRequiredService<ILoggerFactory>();
var mvcOptions = context.Services.GetRequiredService<IOptions<MvcOptions>>().Value;
return (IModelBinder)Activator.CreateInstance(
binderType,
keyBinder,
valueBinder,
loggerFactory,
true /* allowValidatingTopLevelNodes */,
mvcOptions);
}
}
}

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

@ -0,0 +1,79 @@
using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using Volo.Abp.ObjectExtending;
namespace Volo.Abp.AspNetCore.Mvc.ModelBinding
{
public class AbpExtraPropertyModelBinder : IModelBinder
{
public Type ExtensibleObjectType { get; }
public AbpExtraPropertyModelBinder(Type extensibleObjectType)
{
ExtensibleObjectType = extensibleObjectType;
}
public virtual Task BindModelAsync(ModelBindingContext bindingContext)
{
var valueProviderResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
if (valueProviderResult == ValueProviderResult.None)
{
return Task.CompletedTask;
}
bindingContext.ModelState.SetModelValue(bindingContext.ModelName, valueProviderResult);
var model = ConvertStringToPropertyType(
bindingContext,
valueProviderResult.FirstValue
);
bindingContext.Result = ModelBindingResult.Success(model);
return Task.CompletedTask;
}
protected virtual object ConvertStringToPropertyType(ModelBindingContext bindingContext, string value)
{
if (bindingContext.ModelMetadata.ConvertEmptyStringToNull && string.IsNullOrWhiteSpace(value))
{
return null;
}
var extensionInfo = ObjectExtensionManager.Instance.GetOrNull(ExtensibleObjectType);
if (extensionInfo == null)
{
return value;
}
var propertyName = ExtractExtraPropertyName(bindingContext.ModelName);
if (propertyName == null)
{
return value;
}
var propertyInfo = extensionInfo.GetPropertyOrNull(propertyName);
if (propertyInfo == null)
{
return value;
}
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);
}
}
}
Loading…
Cancel
Save