private void UpdateFields(Content content, JObject model) { Field field; var isNew = content.Id == 0; foreach (var prop in model.Properties()) { if (string.IsNullOrEmpty(prop.Name) || prop.Name == "__ContentType" || prop.Name == "Type" || prop.Name == "ContentType") { continue; } var hasField = content.Fields.TryGetValue(prop.Name, out field); if (!hasField && content.SupportsAddingFieldsOnTheFly && prop.Value is JValue && ((JValue)prop.Value).Value != null) { var value = ((JValue)prop.Value).Value; var fieldSetting = FieldSetting.InferFieldSettingFromType(value.GetType(), prop.Name); var meta = new FieldMetadata(true, true, prop.Name, prop.Name, fieldSetting); hasField = content.AddFieldsOnTheFly(new[] { meta }) && content.Fields.TryGetValue(prop.Name, out field); } if (hasField) { if (!field.ReadOnly) { var jvalue = prop.Value as JValue; if (jvalue != null) { if (field is IntegerField) { field.SetData(Convert.ToInt32(jvalue.Value)); continue; } if (field is DateTimeField && jvalue.Value == null) { continue; } if (isNew && field is ReferenceField && jvalue.Value == null) { if (field.Name == "CreatedBy" || field.Name == "ModifiedBy") { continue; } } if (field is ReferenceField && jvalue.Value != null) { var refNode = jvalue.Type == JTokenType.Integer ? Node.LoadNode(Convert.ToInt32(jvalue.Value)) : Node.LoadNode(jvalue.Value.ToString()); field.SetData(refNode); continue; } if (isNew && field.Name == "Name" && jvalue.Value != null) { field.SetData(ContentNamingHelper.GetNameFromDisplayName(jvalue.Value.ToString())); continue; } field.SetData(jvalue.Value); continue; } var ovalue = prop.Value as JObject; if (ovalue != null) { //TODO: ODATA: setting field when posted value is JObject. //field.SetData(jvalue.Value); continue; } var avalue = prop.Value as JArray; if (avalue != null) { if (field is ReferenceField) { var refValues = avalue.Values().ToList(); if (refValues.Count == 0) { field.SetData(null); continue; } var fsetting = field.FieldSetting as ReferenceFieldSetting; var nodes = refValues.Select(rv => rv.Type == JTokenType.Integer ? Node.LoadNode(Convert.ToInt32(rv.ToString())) : Node.LoadNode(rv.ToString())); if (fsetting.AllowMultiple.HasValue && fsetting.AllowMultiple.Value) { field.SetData(nodes); } else { field.SetData(nodes.First()); } continue; } else if (field is ChoiceField) { // ChoiceField expects the value to be of type List<string> var list = new List <string>(); foreach (var token in avalue) { if (token is JValue) { list.Add(((JValue)token).Value.ToString()); } else { throw new Exception(string.Format("Token type {0} for field {1} (type {2}) is not supported.", token.GetType().Name, field.Name, field.GetType().Name)); } } field.SetData(list); } continue; } throw new NotImplementedException(); } } } }
/// <summary> /// Helper method for updating the given <see cref="Content"/> with a model represented by JObject. /// The <see cref="Content"/> will not be saved. /// </summary> /// <param name="content">The <see cref="Content"/> that will be modified. Cannot be null.</param> /// <param name="model">The modifier JObject instance. Cannot be null.</param> public static void UpdateFields(Content content, JObject model) { if (content == null) { throw new ArgumentNullException(nameof(content)); } if (model == null) { throw new ArgumentNullException(nameof(model)); } var isNew = content.Id == 0; foreach (var prop in model.Properties()) { if (string.IsNullOrEmpty(prop.Name) || prop.Name == "__ContentType" || prop.Name == "__ContentTemplate" || prop.Name == "Type" || prop.Name == "ContentType") { continue; } var hasField = content.Fields.TryGetValue(prop.Name, out var field); if (!hasField && content.SupportsAddingFieldsOnTheFly && (prop.Value as JValue)?.Value != null) { var value = ((JValue)prop.Value).Value; var fieldSetting = FieldSetting.InferFieldSettingFromType(value.GetType(), prop.Name); var meta = new FieldMetadata(true, true, prop.Name, prop.Name, fieldSetting); hasField = content.AddFieldsOnTheFly(new[] { meta }) && content.Fields.TryGetValue(prop.Name, out field); } if (hasField) { if (!field.ReadOnly) { if (prop.Value is JValue jvalue) { if (field is IntegerField) { field.SetData(Convert.ToInt32(jvalue.Value)); continue; } if (field is DateTimeField && jvalue.Value == null) { continue; } if (isNew && field is ReferenceField && jvalue.Value == null) { if (field.Name == "CreatedBy" || field.Name == "ModifiedBy") { continue; } } if (field is ReferenceField && jvalue.Value != null) { var refNode = jvalue.Type == JTokenType.Integer ? Node.LoadNode(Convert.ToInt32(jvalue.Value)) : Node.LoadNode(jvalue.Value.ToString()); field.SetData(refNode); continue; } if (isNew && field.Name == "Name" && jvalue.Value != null) { field.SetData(ContentNamingProvider.GetNameFromDisplayName(jvalue.Value.ToString())); continue; } field.SetData(jvalue.Value); continue; } if (prop.Value is JObject) { //TODO: ODATA: setting field when posted value is JObject. // field.SetData(jvalue.Value); continue; } if (prop.Value is JArray avalue) { if (field is ReferenceField) { var refValues = avalue.Values().ToList(); if (refValues.Count == 0) { field.SetData(null); continue; } var fsetting = field.FieldSetting as ReferenceFieldSetting; var nodes = refValues.Select(rv => rv.Type == JTokenType.Integer ? Node.LoadNode(Convert.ToInt32(rv.ToString())) : Node.LoadNode(rv.ToString())); if (fsetting?.AllowMultiple != null && fsetting.AllowMultiple.Value) { field.SetData(nodes); } else { field.SetData(nodes.First()); } } else if (field is ChoiceField) { // ChoiceField expects the value to be of type List<string> var list = new List <string>(); foreach (var token in avalue) { if (token is JValue value) { list.Add(value.Value.ToString()); } else { throw new Exception( $"Token type {token.GetType().Name} for field {field.Name} (type {field.GetType().Name}) is not supported."); } } field.SetData(list); } else if (field is AllowedChildTypesField && field.Name == "AllowedChildTypes" && content.ContentHandler is GenericContent gc) { var types = avalue.Values().Select(rv => { switch (rv.Type) { case JTokenType.Integer: return(Node.LoadNode(Convert.ToInt32(rv.ToString())) as ContentType); default: var typeId = rv.ToString(); if (RepositoryPath.IsValidPath(typeId) == RepositoryPath.PathResult.Correct) { return(Node.LoadNode(typeId) as ContentType); } return(ContentType.GetByName(typeId)); } }).Where(ct => ct != null).ToArray(); gc.SetAllowedChildTypes(types); } continue; } throw new SnNotSupportedException(); } } } }