From 8a9180af2788fa9220c1b9245a41cd7df1cb51de Mon Sep 17 00:00:00 2001 From: maliming Date: Thu, 2 Feb 2023 11:23:11 +0800 Subject: [PATCH] Validate `ExtensibleObject` when `MapExtraPropertiesTo`. Resolve #15549 --- .../ObjectExtending/ExtensibleObjectMapper.cs | 35 +++++++++++++------ ...opertiesObjectExtendingExtensions_Tests.cs | 31 +++++++++++++++- 2 files changed, 55 insertions(+), 11 deletions(-) diff --git a/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/ExtensibleObjectMapper.cs b/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/ExtensibleObjectMapper.cs index e667f7880d..2de527866b 100644 --- a/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/ExtensibleObjectMapper.cs +++ b/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/ExtensibleObjectMapper.cs @@ -11,7 +11,7 @@ public static class ExtensibleObjectMapper /// /// Copies extra properties from the object /// to the object. - /// + /// /// Checks property definitions (over the ) /// based on the preference. /// @@ -34,14 +34,29 @@ public static class ExtensibleObjectMapper Check.NotNull(source, nameof(source)); Check.NotNull(destination, nameof(destination)); - ExtensibleObjectMapper.MapExtraPropertiesTo( - typeof(TSource), - typeof(TDestination), - source.ExtraProperties, - destination.ExtraProperties, - definitionChecks, - ignoredProperties - ); + var sourceType = typeof(TSource); + var destinationType = typeof(TDestination); + + Check.AssignableTo(sourceType, nameof(sourceType)); + Check.AssignableTo(destinationType, nameof(destinationType)); + Check.NotNull(source.ExtraProperties, nameof(source.ExtraProperties)); + Check.NotNull(destination.ExtraProperties, nameof(destination.ExtraProperties)); + + var sourceObjectExtension = ObjectExtensionManager.Instance.GetOrNull(sourceType); + var destinationObjectExtension = ObjectExtensionManager.Instance.GetOrNull(destinationType); + + foreach (var keyValue in source.ExtraProperties) + { + if (CanMapProperty( + keyValue.Key, + sourceObjectExtension, + destinationObjectExtension, + definitionChecks, + ignoredProperties)) + { + destination.SetProperty(keyValue.Key, keyValue.Value); + } + } } /// @@ -80,7 +95,7 @@ public static class ExtensibleObjectMapper /// /// Copies extra properties from the object /// to the object. - /// + /// /// Checks property definitions (over the ) /// based on the preference. /// diff --git a/framework/test/Volo.Abp.ObjectExtending.Tests/Volo/Abp/ObjectExtending/HasExtraPropertiesObjectExtendingExtensions_Tests.cs b/framework/test/Volo.Abp.ObjectExtending.Tests/Volo/Abp/ObjectExtending/HasExtraPropertiesObjectExtendingExtensions_Tests.cs index 5bf34515ef..bc31c60ac5 100644 --- a/framework/test/Volo.Abp.ObjectExtending.Tests/Volo/Abp/ObjectExtending/HasExtraPropertiesObjectExtendingExtensions_Tests.cs +++ b/framework/test/Volo.Abp.ObjectExtending.Tests/Volo/Abp/ObjectExtending/HasExtraPropertiesObjectExtendingExtensions_Tests.cs @@ -1,6 +1,10 @@ -using Shouldly; +using System.ComponentModel.DataAnnotations; +using System.Globalization; +using Shouldly; using Volo.Abp.Data; +using Volo.Abp.Localization; using Volo.Abp.ObjectExtending.TestObjects; +using Volo.Abp.Validation; using Xunit; namespace Volo.Abp.ObjectExtending; @@ -90,4 +94,29 @@ public class HasExtraPropertiesObjectExtendingExtensions_Tests : AbpObjectExtend _personDto.GetProperty("Sex").ShouldBe("male"); _personDto.GetProperty("ExistingDtoProperty").ShouldBe("existing-value"); //Should not clear existing values } + + [Fact] + public void MapExtraPropertiesTo_Should_Validate_Properties() + { + using (CultureHelper.Use(CultureInfo.InvariantCulture)) + { + ObjectExtensionManager.Instance + .AddOrUpdateProperty( + "Name", + options => + { + options.Attributes.Add(new StringLengthAttribute(4)); + }); + + var person = new ExtensibleTestPerson().SetProperty("Name", "John"); + var personDto = new ExtensibleTestPersonDto(); + + person.MapExtraPropertiesTo(personDto); + + person.SetProperty("Name", "John Bush"); + Assert.Throws(() => person.MapExtraPropertiesTo(personDto)).ValidationErrors.ShouldContain(x => x.ErrorMessage == "The field Name must be a string with a maximum length of 4."); + } + + } + }