private void GenerateDataTypes(string nameSpace, string folderPath) { var defs = ApplicationContext.Current.Services.DataTypeService.GetAllDataTypeDefinitions(); if (_typeDefs == null) { _typeDefs = this.GetType().Assembly.GetTypes().Where(x => x.GetCustomAttribute <BuiltInDataTypeAttribute>() != null && !x.IsGenericTypeDefinition).ToDictionary(x => x.GetInitialisedAttribute <DataTypeAttribute>(), x => x.Name); } List <DataTypeDescription> types = new List <DataTypeDescription>(); foreach (var def in defs) { if (!_typeDefs.Any(x => x.Key.Name == def.Name)) //not a known built-in type { var dataType = new DataTypeDescription(); dataType.PreValues = ApplicationContext.Current.Services.DataTypeService .GetPreValuesCollectionByDataTypeId(def.Id) .PreValuesAsDictionary .Where(x => x.Value != null && x.Value.Value != null) .Select(x => new PreValueDescription() { Alias = x.Key, Value = x.Value.Value.Replace("\"", "\"\"") }) .ToList(); if (_typeDefs.Any(x => x.Key.PropertyEditorAlias == def.PropertyEditorAlias)) //can base on a known built-in type { var builtIn = _typeDefs.First(x => x.Key.PropertyEditorAlias == def.PropertyEditorAlias); dataType.CustomType = false; dataType.InheritanceBase = builtIn.Key.DecoratedType.Name; dataType.DataTypeClassName = TypeGeneratorUtils.GetDataTypeClassName(def.Id, null); dataType.DataTypeInstanceName = def.Name; dataType.PropertyEditorAlias = def.PropertyEditorAlias; dataType.DbType = Enum.GetName(typeof(DataTypeDatabaseType), def.DatabaseType); } else { dataType.CustomType = true; switch (def.DatabaseType) { case DataTypeDatabaseType.Date: dataType.InheritanceBase = "IUmbracoDateDataType"; dataType.SerializedTypeName = "DateTime"; break; case DataTypeDatabaseType.Integer: dataType.InheritanceBase = "IUmbracoIntegerDataType"; dataType.SerializedTypeName = "int"; break; case DataTypeDatabaseType.Ntext: dataType.InheritanceBase = "IUmbracoNtextDataType"; dataType.SerializedTypeName = "string"; break; case DataTypeDatabaseType.Nvarchar: dataType.InheritanceBase = "IUmbracoNvarcharDataType"; dataType.SerializedTypeName = "string"; break; } dataType.DataTypeClassName = TypeGeneratorUtils.GetDataTypeClassName(def.Id, null); dataType.DataTypeInstanceName = def.Name; dataType.PropertyEditorAlias = def.PropertyEditorAlias; dataType.DbType = Enum.GetName(typeof(DataTypeDatabaseType), def.DatabaseType); } types.Add(dataType); } } GenerateClassFiles(nameSpace, folderPath, types); }
/// <summary> /// add datatype validation messages to modelstate to enhance validation messages for type conversion error /// </summary> /// <param name="bindingContext"></param> /// <param name="propertyDescriptor"></param> private static void AddDataTypeConversionMessages(ModelBindingContext bindingContext, PropertyDescriptor propertyDescriptor) { // need to skip properties that aren't part of the request, else we might hit a StackOverflowException string fullPropertyKey = CreateSubPropertyName(bindingContext.ModelName, propertyDescriptor.Name); if (!bindingContext.ValueProvider.ContainsPrefix(fullPropertyKey)) { return; } ModelState modelState = bindingContext.ModelState[fullPropertyKey]; if (modelState == null) { return; } foreach ( ModelError error in modelState.Errors.Where(err => !String.IsNullOrEmpty(err.ErrorMessage) && err.Exception == null). ToList()) { if (error.ErrorMessage.Contains("@DataType")) { Type numericType; if (DataTypeDescription.ContainsKey(propertyDescriptor.PropertyType)) { numericType = propertyDescriptor.PropertyType; } else { numericType = Nullable.GetUnderlyingType(propertyDescriptor.PropertyType); } var newMessage = error.ErrorMessage.Replace("@DataType", DataTypeDescription[numericType]); modelState.Errors.Remove(error); modelState.Errors.Add(newMessage); } } if ((propertyDescriptor.PropertyType == typeof(decimal) || propertyDescriptor.PropertyType == typeof(decimal?)) && bindingContext.PropertyMetadata[propertyDescriptor.Name].IsRequired) { var precision = ClientDataTypeModelValidatorProvider.DefaultDecimalPrecision; var scale = ClientDataTypeModelValidatorProvider.DefaultDecimalScale; var attr = propertyDescriptor.Attributes.OfType <DecimalFormatAttribute>().FirstOrDefault(); if (attr != null) { precision = attr.Precision; scale = attr.Scale; } var rex = new Regex("^(\\d{1," + (precision - scale) + "})(\\.\\d{1," + scale + "})?$"); if (!rex.IsMatch(modelState.Value.AttemptedValue)) { var errorMessage = ClientDataTypeModelValidatorProvider.NumericModelValidator.MakeErrorString( ValidationMessages.NumericModelValidator_DecimalFormatError, bindingContext.PropertyMetadata[propertyDescriptor.Name].GetDisplayName(), precision - scale, scale); modelState.Errors.Add(errorMessage); } } }