Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ public void ClearParmsMetadata()

public bool isInputParm(string key)
{
return inParmsMetadataHash.Contains(key);
return (inParmsMetadataHash!=null && inParmsMetadataHash.Contains(key));
}

public void Clear()
Expand All @@ -105,7 +105,7 @@ public bool isParmModified(string fieldName, object value)
IGxJSONSerializable jsonValue = value as IGxJSONSerializable;
if (jsonValue!=null)
{
if (!inParmsHashValue.ContainsKey(fieldName))
if (inParmsHashValue!=null && !inParmsHashValue.ContainsKey(fieldName))
return true;
return GXUtil.GetHash(jsonValue.ToJSonString()) != inParmsHashValue[fieldName];
}
Expand Down Expand Up @@ -346,7 +346,7 @@ public void ajax_rsp_assign_sdt_attri(String CmpContext, bool IsMasterPage, Stri
try
{
JObject obj = GetGxObject(AttValues, CmpContext, IsMasterPage);
if (obj != null && (DynAjaxEventContext.isParmModified(AttName, SdtObj) || !isUndefinedOutParam( AttName, SdtObj)))
if (obj != null && (!isUndefinedOutParam(AttName, SdtObj) || DynAjaxEventContext.isParmModified(AttName, SdtObj)))
{
IGxJSONAble SdtObjJson = SdtObj as IGxJSONAble;
if (SdtObjJson != null)
Expand Down
92 changes: 58 additions & 34 deletions dotnet/src/dotnetframework/GxClasses/Domain/GxCollections.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ namespace GeneXus.Utils
using System.Xml.Serialization;
using GeneXus.Application;
using GeneXus.Configuration;
using GeneXus.Data;
using GeneXus.Http;
using GeneXus.Metadata;
using GeneXus.XML;
Expand Down Expand Up @@ -1044,8 +1045,8 @@ public string Name
public class GxUserType : IGxXMLSerializable, ICloneable, IGxJSONAble, IGxJSONSerializable, IGXAssigned
{
static readonly IGXLogger log = GXLoggerFactory.GetLogger<GxUserType>();
protected GXProperties dirties = new GXProperties();

protected ConcurrentDictionary<string,byte> dirties = new ConcurrentDictionary<string, byte>(StringComparer.OrdinalIgnoreCase);
private const string PROPERTY_PREFIX = "gxtpr_";
static object setupChannelObject = null;
static bool setupChannelInitialized;
[XmlIgnore]
Expand Down Expand Up @@ -1103,11 +1104,11 @@ public GxUserType()

public virtual void SetDirty(string fieldName)
{
dirties[fieldName.ToLower()] = "true";
dirties[fieldName] = 1;
}
public virtual bool IsDirty(string fieldName)
{
if (dirties.ContainsKey(fieldName.ToLower()))
if (dirties.ContainsKey(fieldName))
return true;
return false;
}
Expand Down Expand Up @@ -1605,24 +1606,27 @@ public Object GetJSONObject()

private ICollection getFromJSONObjectOrderIterator(ICollection it)
{
List<string> v = new List<string>();
if (GxUploadAttrs.IsEmpty && !typeof(GxSilentTrnSdt).IsAssignableFrom(this.GetType()))
{
return it;
}
List<string> _JsonObjectOrderIterator = new List<string>();

List<string> vAtEnd = new List<string>();
foreach (string name in it)
{
string map = JsonMap(name);
PropertyInfo objProperty = GetTypeProperty("gxtpr_" + (!string.IsNullOrEmpty(map) ? map : name).ToLower());
if (name.EndsWith("_N") || objProperty != null && IsGxUploadAttribute(objProperty))
if (name.EndsWith("_N") || IsGxUploadAttribute(name))
{
vAtEnd.Add(name);
}
else
{
v.Add(name);//keep the order of attributes that do not end with _N.
_JsonObjectOrderIterator.Add(name);//keep the order of attributes that do not end with _N.
}
}
if (vAtEnd.Count > 0)
v.AddRange(vAtEnd);
return v;
_JsonObjectOrderIterator.AddRange(vAtEnd);
return _JsonObjectOrderIterator;
}

public void FromJSONObject(dynamic obj)
Expand All @@ -1635,9 +1639,7 @@ public void FromJSONObject(dynamic obj)
foreach (string name in jsonIterator)
{
object currObj = jobj[name];
string map = JsonMap(name);
PropertyInfo objProperty = GetTypeProperty("gxtpr_" + (map != null ? map : name).ToLower());

PropertyInfo objProperty = GetTypeProperty(JsonNameToInternalName(name));
if (objProperty != null)
{
if (!JSONHelper.IsJsonNull(currObj))
Expand Down Expand Up @@ -1897,32 +1899,51 @@ private bool TryConvertValueToProperty(object Value, PropertyInfo property, out
return success;
}

[System.Diagnostics.CodeAnalysis.SuppressMessage("GxFxCopRules", "CR1000:EnforceThreadSafeType")]
private Dictionary<string, bool> gxuploadAttrs = new Dictionary<string, bool>();
private bool IsGxUploadAttribute(PropertyInfo property)
private GXTypeInfo _compatibilityGxuploadAttrs = null;
private bool IsGxUploadAttribute(string jsonPropertyName)
{
string key = property.Name;
if (!gxuploadAttrs.ContainsKey(key))
{
bool hasAtt = property.IsDefined(typeof(GxUpload), false);
gxuploadAttrs.Add(key, hasAtt);
}
return gxuploadAttrs[key];
return GxUploadAttrs.ContainsKey(JsonNameToInternalName(jsonPropertyName));
}

private Hashtable props;

private PropertyInfo GetTypeProperty(string propName)
private bool IsGxUploadAttribute(PropertyInfo propertyInfo)
{
return GxUploadAttrs.ContainsKey(propertyInfo.Name);
}
private string JsonNameToInternalName(string jsonPropertyName)
{
string map = JsonMap(jsonPropertyName);
if (!string.IsNullOrEmpty(map))
return $"{PROPERTY_PREFIX}{map}";
else
return $"{PROPERTY_PREFIX}{jsonPropertyName}";
}
protected virtual GXTypeInfo TypeInfo { get { return _compatibilityGxuploadAttrs; } set { _compatibilityGxuploadAttrs = value; } }
private ConcurrentDictionary<string, byte> GxUploadAttrs
{
if (props == null)
get
{
props = new Hashtable();
foreach (PropertyInfo prop in this.GetType().GetProperties())
if (TypeInfo == null)
{
props.Add(prop.Name.ToLower(), prop);
TypeInfo = new GXTypeInfo();

TypeInfo.UploadAttrs = new ConcurrentDictionary<string, byte>(StringComparer.OrdinalIgnoreCase);
foreach (PropertyInfo property in this.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance))
{
if (property.Name.StartsWith(PROPERTY_PREFIX, StringComparison.OrdinalIgnoreCase))
{
bool hasAtt = property.IsDefined(typeof(GxUpload), false);
if (hasAtt)
{
TypeInfo.UploadAttrs.TryAdd(property.Name, 1);
}
}
}
}
return TypeInfo.UploadAttrs;
}
return (PropertyInfo)props[propName];
}
private PropertyInfo GetTypeProperty(string propName)
{
return this.GetType().GetProperty(propName, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance);
}

private Hashtable methods;
Expand Down Expand Up @@ -2004,7 +2025,10 @@ public void SetPropertyValue(string propertyName, object propertyValue)
GetType().GetProperty($"gxTpr_{propertyName}").SetValue(this, propertyValue);
}
}

public class GXTypeInfo
{
public ConcurrentDictionary<string, byte> UploadAttrs { get; set; }
}
public interface IGxJSONAble
{
void AddObjectProperty(string name, object prop);
Expand Down
13 changes: 13 additions & 0 deletions dotnet/test/DotNetCoreUnitTest/StringUtil/JsonUtilTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,19 @@ public void DeserializationTrailingCommasCompatibility()
JArray array = JSONHelper.ReadJSON<JArray>(json);
Assert.Equal(7, array.Count);
}
#if NETCORE
[Fact]
public void DeserializationTwoLevels()
{
string json = "{\"Name\":\"MainName\",\"Level\":[{\"LevelName\":\"LevelName1\"}, {\"LevelName\":\"LevelName2\"}]}";
GxContext context = new GxContext();
SdtSDTTwoLevels sdt = new SdtSDTTwoLevels(context);
sdt.FromJSonString(json, null);
Assert.Equal("MainName", sdt.gxTpr_Name);
Assert.Equal("LevelName1",((SdtSDTTwoLevels_LevelItem)sdt.gxTpr_Level.Item(1)).gxTpr_Levelname);
Assert.Equal("LevelName2", ((SdtSDTTwoLevels_LevelItem)sdt.gxTpr_Level.Item(2)).gxTpr_Levelname);
}
#endif
}

[XmlSerializerFormat]
Expand Down
Loading