private string SetProperty(string target, PropertyInfo property, string value) { if (!ViewModelJsonConverter.IsComplexType(property.PropertyType)) { return(target + "." + property.Name + "(" + value + ")"); } else { return($"dotvvm.serialization.deserialize({ value }, { target }.{ property.Name })"); } }
public static bool IsComplexType(this JsExpression expr) { if (expr.TryGetAnnotation <ViewModelInfoAnnotation>(out var vmInfo)) { return(ViewModelJsonConverter.IsComplexType(vmInfo.Type)); } if (expr is JsAssignmentExpression assignment && assignment.Operator == null) { return(IsComplexType(assignment.Right)); } if (expr is JsBinaryExpression binary && (binary.Operator == BinaryOperatorType.ConditionalAnd || binary.Operator == BinaryOperatorType.ConditionalOr)) { return(IsComplexType(binary.Left) && IsComplexType(binary.Right)); } if (expr is JsConditionalExpression conditional) { return(IsComplexType(conditional.TrueExpression) && IsComplexType(conditional.FalseExpression)); } if (expr is JsLiteral literal) { return(literal.Value != null && ViewModelJsonConverter.IsComplexType(literal.Value.GetType())); } return(false); }
/// <summary> /// Validates the view model. /// </summary> private IEnumerable <ViewModelValidationError> ValidateViewModel(object viewModel, string pathPrefix, HashSet <object> alreadyValidated) { if (alreadyValidated.Contains(viewModel)) { yield break; } if (viewModel == null) { yield break; } var viewModelType = viewModel.GetType(); if (ViewModelJsonConverter.IsPrimitiveType(viewModelType) || ViewModelJsonConverter.IsNullableType(viewModelType)) { yield break; } alreadyValidated.Add(viewModel); if (ViewModelJsonConverter.IsEnumerable(viewModelType)) { if (pathPrefix.Length == 0) { pathPrefix = "$data"; } else { pathPrefix += "()"; } // collections var index = 0; foreach (var item in (IEnumerable)viewModel) { foreach (var error in ValidateViewModel(item, pathPrefix + "[" + index + "]()", alreadyValidated)) { yield return(error); } index++; } yield break; } // validate all properties on the object var map = viewModelSerializationMapper.GetMap(viewModel.GetType()); foreach (var property in map.Properties.Where(p => p.TransferToServer)) { var value = property.PropertyInfo.GetValue(viewModel); var path = CombinePath(pathPrefix, property.Name); // validate the property if (property.ValidationRules.Any()) { var context = new ValidationContext(viewModel, validationItems) { MemberName = property.Name }; foreach (var rule in property.ValidationRules) { var propertyResult = rule.SourceValidationAttribute?.GetValidationResult(value, context); if (propertyResult != ValidationResult.Success) { yield return(new ViewModelValidationError() { PropertyPath = path, ErrorMessage = rule.ErrorMessage }); } } } // inspect objects if (value != null) { if (ViewModelJsonConverter.IsComplexType(property.Type)) { // complex objects foreach (var error in ValidateViewModel(value, path, alreadyValidated)) { yield return(error); } } } } if (viewModel is IValidatableObject) { foreach (var error in ((IValidatableObject)viewModel).Validate( new ValidationContext(viewModel, validationItems))) { var paths = new List <string>(); if (error.MemberNames != null) { foreach (var memberName in error.MemberNames) { paths.Add(CombinePath(pathPrefix, memberName)); } } if (!paths.Any()) { paths.Add(pathPrefix); } foreach (var memberPath in paths) { yield return(new ViewModelValidationError() { PropertyPath = memberPath, ErrorMessage = error.ErrorMessage }); } } } }