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);
 }
Beispiel #3
0
        /// <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
                        });
                    }
                }
            }
        }