/// <summary> /// Gets the type name from the given <paramref name="value"/>. /// </summary> /// <param name="value">The value to get the type name from. This can be an ODataPrimitiveValue, an ODataComplexValue, an ODataCollectionValue or a Clr primitive object.</param> /// <returns>The type name for the given <paramref name="value"/>.</returns> protected static string GetTypeNameFromValue(object value) { Debug.Assert(value != null, "value != null"); ODataPrimitiveValue primitiveValue = value as ODataPrimitiveValue; if (primitiveValue != null) { return(EdmLibraryExtensions.GetPrimitiveTypeReference(primitiveValue.Value.GetType()).ODataFullName()); } ODataComplexValue complexValue = value as ODataComplexValue; if (complexValue != null) { return(complexValue.TypeName); } ODataCollectionValue collectionValue = value as ODataCollectionValue; if (collectionValue != null) { return(collectionValue.TypeName); } IEdmPrimitiveTypeReference primitiveTypeReference = EdmLibraryExtensions.GetPrimitiveTypeReference(value.GetType()); if (primitiveTypeReference == null) { throw new ODataException(Strings.ValidationUtils_UnsupportedPrimitiveType(value.GetType().FullName)); } return(primitiveTypeReference.ODataFullName()); }
/// <summary> /// Gets the type name from the given <paramref name="value"/>. /// </summary> /// <param name="value">The value to get the type name from. This can be an ODataPrimitiveValue, an ODataComplexValue, an ODataCollectionValue or a Clr primitive object.</param> /// <returns>The type name for the given <paramref name="value"/>.</returns> protected static string GetTypeNameFromValue(object value) { Debug.Assert(value != null, "value != null"); ODataPrimitiveValue primitiveValue = value as ODataPrimitiveValue; if (primitiveValue != null) { // primitiveValueTypeReference == null means: the EDM type of the primitive value cannot be determined. // This could possibly be due to value being an unsigned int. // In this case, simply return null because: // - If the property is regular property, the type is not needed since service model knows its exact type. // - If the property is dynamic property, ODL does not support dynamic property containing unsigned int value // since we don't know its underlying type as well as how to serialize it. IEdmPrimitiveTypeReference primitiveValueTypeReference = EdmLibraryExtensions.GetPrimitiveTypeReference(primitiveValue.Value.GetType()); return(primitiveValueTypeReference == null ? null : primitiveValueTypeReference.ODataFullName()); } ODataComplexValue complexValue = value as ODataComplexValue; if (complexValue != null) { return(complexValue.TypeName); } ODataEnumValue enumValue = value as ODataEnumValue; if (enumValue != null) { return(enumValue.TypeName); } ODataCollectionValue collectionValue = value as ODataCollectionValue; if (collectionValue != null) { return(EdmLibraryExtensions.GetCollectionTypeFullName(collectionValue.TypeName)); } IEdmPrimitiveTypeReference primitiveTypeReference = EdmLibraryExtensions.GetPrimitiveTypeReference(value.GetType()); if (primitiveTypeReference == null) { throw new ODataException(Strings.ValidationUtils_UnsupportedPrimitiveType(value.GetType().FullName)); } return(primitiveTypeReference.ODataFullName()); }
/// <summary> /// Reads an annotation's value from the annotation value notation specified on the current element. /// </summary> /// <param name="expectedTypeReference">The expected type reference of the vocabulary term from the metadata.</param> /// <param name="attributeValueNotationTypeReference">The type reference indicated by the name of the attribute used in attribute value notation. /// For example, if the attribute was called "string", this will be a reference to the string type.</param> /// <param name="attributeValueNotationAttributeName">The name of the attribute used by attribute avalue notation.</param> /// <param name="attributeValueNotationAttributeValue">The value of the attribute used by attribute value notation.</param> /// <param name="typeAttributeValue">The value of the "m:type" attribute on the annotation element.</param> /// <param name="positionedOnEmptyElement">true if the annotation element is empty, false otherwise.</param> /// <param name="model">The edm model instance.</param> /// <param name="messageReaderSettings">The message reader settings instance.</param> /// <param name="version">The payload version to read.</param> /// <returns>The primitive value represented on this element via attribute value notation.</returns> private static ODataPrimitiveValue GetValueFromAttributeValueNotation( IEdmTypeReference expectedTypeReference, IEdmPrimitiveTypeReference attributeValueNotationTypeReference, string attributeValueNotationAttributeName, string attributeValueNotationAttributeValue, string typeAttributeValue, bool positionedOnEmptyElement, IEdmModel model, ODataMessageReaderSettings messageReaderSettings, ODataVersion version) { Debug.Assert(attributeValueNotationTypeReference != null, "attributeValueNotationTypeReference != null"); if (!positionedOnEmptyElement) { // If there is content in the body of the element, throw since it's ambiguous whether we should use the value from the attribute or the element content. throw new ODataException(ODataErrorStrings.AtomInstanceAnnotation_AttributeValueNotationUsedOnNonEmptyElement(attributeValueNotationAttributeName)); } // If both m:type is present and attribute value notation is being used, they must match. // For example, if m:type is "Edm.Int32", but the "string" attribute is also present, we should throw. if (typeAttributeValue != null && !string.Equals(attributeValueNotationTypeReference.Definition.ODataFullName(), typeAttributeValue, StringComparison.Ordinal)) { throw new ODataException(ODataErrorStrings.AtomInstanceAnnotation_AttributeValueNotationUsedWithIncompatibleType(typeAttributeValue, attributeValueNotationAttributeName)); } IEdmTypeReference targetTypeReference = ReaderValidationUtils.ResolveAndValidatePrimitiveTargetType( expectedTypeReference, EdmTypeKind.Primitive, attributeValueNotationTypeReference.Definition, attributeValueNotationTypeReference.ODataFullName(), attributeValueNotationTypeReference.Definition, model, messageReaderSettings, version); return(new ODataPrimitiveValue(AtomValueUtils.ConvertStringToPrimitive(attributeValueNotationAttributeValue, targetTypeReference.AsPrimitive()))); }
/// <summary> /// Converts the given JSON int value to the expected type as per OData conversion rules for JSON values. /// </summary> /// <param name="intValue">Int32 value to the converted.</param> /// <param name="targetType">Target type to which the int value needs to be converted.</param> /// <param name="primitiveTypeReference">Type reference to which the value needs to be converted.</param> /// <returns>Object which is in sync with the property type.</returns> private static object ConvertInt32Value(int intValue, Type targetType, IEdmPrimitiveTypeReference primitiveTypeReference) { if (targetType == typeof(Int16)) { return Convert.ToInt16(intValue); } if (targetType == typeof(Byte)) { return Convert.ToByte(intValue); } if (targetType == typeof(SByte)) { return Convert.ToSByte(intValue); } if (targetType == typeof(Single)) { return Convert.ToSingle(intValue); } if (targetType == typeof(Double)) { return Convert.ToDouble(intValue); } if (targetType == typeof(Decimal)) { return Convert.ToDecimal(intValue); } if (targetType == typeof(Int64)) { return Convert.ToInt64(intValue); } if (targetType != typeof(Int32)) { throw new ODataException(ODataErrorStrings.ODataJsonReaderUtils_CannotConvertInt32(primitiveTypeReference.ODataFullName())); } return intValue; }
/// <summary> /// Creates an exception used when primitive type conversion fails. /// </summary> /// <param name="targetTypeReference">The target type reference to which the conversion failed.</param> /// <param name="innerException">Possible inner exception with more information about the failure.</param> /// <param name="stringValue">The string representation for the value.</param> /// <returns>The exception object to throw.</returns> internal static ODataException GetPrimitiveTypeConversionException(IEdmPrimitiveTypeReference targetTypeReference, Exception innerException, string stringValue) { Debug.Assert(targetTypeReference != null, "targetTypeReference != null"); return new ODataException(Strings.ReaderValidationUtils_CannotConvertPrimitiveValue(stringValue, targetTypeReference.ODataFullName()), innerException); }
internal static object VerifyAndCoerceUriPrimitiveLiteral(object primitiveValue, IEdmModel model, IEdmTypeReference expectedTypeReference, ODataVersion version) { ExceptionUtils.CheckArgumentNotNull<object>(primitiveValue, "primitiveValue"); ExceptionUtils.CheckArgumentNotNull<IEdmModel>(model, "model"); ExceptionUtils.CheckArgumentNotNull<IEdmTypeReference>(expectedTypeReference, "expectedTypeReference"); ODataUriNullValue value2 = primitiveValue as ODataUriNullValue; if (value2 != null) { if (!expectedTypeReference.IsNullable) { throw new ODataException(Microsoft.Data.OData.Strings.ODataUriUtils_ConvertFromUriLiteralNullOnNonNullableType(expectedTypeReference.ODataFullName())); } IEdmType type = ValidationUtils.ValidateValueTypeName(model, value2.TypeName, expectedTypeReference.Definition.TypeKind); if (type.IsSpatial()) { ODataVersionChecker.CheckSpatialValue(version); } if (!TypePromotionUtils.CanConvertTo(type.ToTypeReference(), expectedTypeReference)) { throw new ODataException(Microsoft.Data.OData.Strings.ODataUriUtils_ConvertFromUriLiteralNullTypeVerificationFailure(expectedTypeReference.ODataFullName(), value2.TypeName)); } value2.TypeName = expectedTypeReference.ODataFullName(); return value2; } IEdmPrimitiveTypeReference reference = expectedTypeReference.AsPrimitiveOrNull(); if (reference == null) { throw new ODataException(Microsoft.Data.OData.Strings.ODataUriUtils_ConvertFromUriLiteralTypeVerificationFailure(expectedTypeReference.ODataFullName(), primitiveValue)); } object obj2 = CoerceNumericType(primitiveValue, reference.PrimitiveDefinition()); if (obj2 != null) { return obj2; } Type c = primitiveValue.GetType(); if (!TypeUtils.GetNonNullableType(EdmLibraryExtensions.GetPrimitiveClrType(reference)).IsAssignableFrom(c)) { throw new ODataException(Microsoft.Data.OData.Strings.ODataUriUtils_ConvertFromUriLiteralTypeVerificationFailure(reference.ODataFullName(), primitiveValue)); } return primitiveValue; }
/// <summary> /// Verifies that the given <paramref name="primitiveValue"/> is or can be coerced to <paramref name="expectedTypeReference"/>, and coerces it if necessary. /// </summary> /// <param name="primitiveValue">An EDM primitive value to verify.</param> /// <param name="model">Model to verify against.</param> /// <param name="expectedTypeReference">Expected type reference.</param> /// <param name="version">The version to use for reading.</param> /// <returns>Coerced version of the <paramref name="primitiveValue"/>.</returns> internal static object VerifyAndCoerceUriPrimitiveLiteral(object primitiveValue, IEdmModel model, IEdmTypeReference expectedTypeReference, ODataVersion version) { DebugUtils.CheckNoExternalCallers(); ExceptionUtils.CheckArgumentNotNull(primitiveValue, "primitiveValue"); ExceptionUtils.CheckArgumentNotNull(model, "model"); ExceptionUtils.CheckArgumentNotNull(expectedTypeReference, "expectedTypeReference"); // First deal with null literal ODataUriNullValue nullValue = primitiveValue as ODataUriNullValue; if (nullValue != null) { if (!expectedTypeReference.IsNullable) { throw new ODataException(o.Strings.ODataUriUtils_ConvertFromUriLiteralNullOnNonNullableType(expectedTypeReference.ODataFullName())); } IEdmType actualResolvedType = ValidationUtils.ValidateValueTypeName(model, nullValue.TypeName, expectedTypeReference.Definition.TypeKind); Debug.Assert(actualResolvedType != null, "This is a primitive-only codepath so actualResolvedType != null."); if (actualResolvedType.IsSpatial()) { ODataVersionChecker.CheckSpatialValue(version); } if (TypePromotionUtils.CanConvertTo(actualResolvedType.ToTypeReference(), expectedTypeReference)) { nullValue.TypeName = expectedTypeReference.ODataFullName(); return(nullValue); } throw new ODataException(o.Strings.ODataUriUtils_ConvertFromUriLiteralNullTypeVerificationFailure(expectedTypeReference.ODataFullName(), nullValue.TypeName)); } // Only other positive case is a numeric primitive that needs to be coerced IEdmPrimitiveTypeReference expectedPrimitiveTypeReference = expectedTypeReference.AsPrimitiveOrNull(); if (expectedPrimitiveTypeReference == null) { throw new ODataException(o.Strings.ODataUriUtils_ConvertFromUriLiteralTypeVerificationFailure(expectedTypeReference.ODataFullName(), primitiveValue)); } object coercedResult = CoerceNumericType(primitiveValue, expectedPrimitiveTypeReference.PrimitiveDefinition()); if (coercedResult != null) { return(coercedResult); } Type actualType = primitiveValue.GetType(); Type targetType = TypeUtils.GetNonNullableType(EdmLibraryExtensions.GetPrimitiveClrType(expectedPrimitiveTypeReference)); // If target type is assignable from actual type, we're OK if (targetType.IsAssignableFrom(actualType)) { return(primitiveValue); } throw new ODataException(o.Strings.ODataUriUtils_ConvertFromUriLiteralTypeVerificationFailure(expectedPrimitiveTypeReference.ODataFullName(), primitiveValue)); }
/// <summary> /// Converts the given payload value to the type defined in a type definition. /// </summary> /// <param name="value">The given payload value.</param> /// <param name="edmTypeReference">The expected type reference from model.</param> /// <returns>The converted value of the type.</returns> public virtual object ConvertFromPayloadValue(object value, IEdmTypeReference edmTypeReference) { IEdmPrimitiveTypeReference primitiveTypeReference = edmTypeReference as IEdmPrimitiveTypeReference; Debug.Assert(primitiveTypeReference != null, "primitiveTypeReference != null"); try { Type targetType = EdmLibraryExtensions.GetPrimitiveClrType(primitiveTypeReference.PrimitiveDefinition(), false); string stringValue = value as string; if (stringValue != null) { return(ConvertStringValue(stringValue, targetType)); } else if (value is Int32) { return(ConvertInt32Value((int)value, targetType, primitiveTypeReference)); } else if (value is Decimal) { Decimal decimalValue = (Decimal)value; if (targetType == typeof(Int64)) { return(Convert.ToInt64(decimalValue)); } if (targetType == typeof(Double)) { return(Convert.ToDouble(decimalValue)); } if (targetType == typeof(Single)) { return(Convert.ToSingle(decimalValue)); } if (targetType != typeof(Decimal)) { throw new ODataException(ODataErrorStrings.ODataJsonReaderUtils_CannotConvertDecimal(primitiveTypeReference.ODataFullName())); } } else if (value is Double) { Double doubleValue = (Double)value; if (targetType == typeof(Single)) { return(Convert.ToSingle(doubleValue)); } if (targetType != typeof(Double)) { throw new ODataException(ODataErrorStrings.ODataJsonReaderUtils_CannotConvertDouble(primitiveTypeReference.ODataFullName())); } } else if (value is bool) { if (targetType != typeof(bool)) { throw new ODataException(ODataErrorStrings.ODataJsonReaderUtils_CannotConvertBoolean(primitiveTypeReference.ODataFullName())); } } else if (value is DateTime) { if (targetType != typeof(DateTime)) { throw new ODataException(ODataErrorStrings.ODataJsonReaderUtils_CannotConvertDateTime(primitiveTypeReference.ODataFullName())); } } else if (value is DateTimeOffset) { if (targetType != typeof(DateTimeOffset)) { throw new ODataException(ODataErrorStrings.ODataJsonReaderUtils_CannotConvertDateTimeOffset(primitiveTypeReference.ODataFullName())); } } } catch (Exception e) { if (!ExceptionUtils.IsCatchableExceptionType(e)) { throw; } throw ReaderValidationUtils.GetPrimitiveTypeConversionException(primitiveTypeReference, e, value.ToString()); } // otherwise just return the value without doing any conversion return(value); }
internal static object ConvertValue( object value, IEdmPrimitiveTypeReference primitiveTypeReference, ODataMessageReaderSettings messageReaderSettings, ODataVersion version, bool validateNullValue, string propertyName) { Debug.Assert(primitiveTypeReference != null, "primitiveTypeReference != null"); if (value == null) { // Only primitive type references are validated. Core model is sufficient. ReaderValidationUtils.ValidateNullValue( EdmCoreModel.Instance, primitiveTypeReference, messageReaderSettings, validateNullValue, version, propertyName); return(null); } try { Type targetType = EdmLibraryExtensions.GetPrimitiveClrType(primitiveTypeReference.PrimitiveDefinition(), false); string stringValue = value as string; if (stringValue != null) { return(ConvertStringValue(stringValue, targetType)); } else if (value is Int32) { return(ConvertInt32Value((int)value, targetType, primitiveTypeReference)); } else if (value is Decimal) { Decimal decimalValue = (Decimal)value; if (targetType == typeof(Int64)) { return(Convert.ToInt64(decimalValue)); } if (targetType == typeof(Double)) { return(Convert.ToDouble(decimalValue)); } if (targetType == typeof(Single)) { return(Convert.ToSingle(decimalValue)); } if (targetType != typeof(Decimal)) { throw new ODataException(ODataErrorStrings.ODataJsonReaderUtils_CannotConvertDecimal(primitiveTypeReference.ODataFullName())); } } else if (value is Double) { Double doubleValue = (Double)value; if (targetType == typeof(Single)) { return(Convert.ToSingle(doubleValue)); } if (targetType != typeof(Double)) { throw new ODataException(ODataErrorStrings.ODataJsonReaderUtils_CannotConvertDouble(primitiveTypeReference.ODataFullName())); } } else if (value is bool) { if (targetType != typeof(bool)) { throw new ODataException(ODataErrorStrings.ODataJsonReaderUtils_CannotConvertBoolean(primitiveTypeReference.ODataFullName())); } } else if (value is DateTime) { if (targetType != typeof(DateTime)) { throw new ODataException(ODataErrorStrings.ODataJsonReaderUtils_CannotConvertDateTime(primitiveTypeReference.ODataFullName())); } } else if (value is DateTimeOffset) { if (targetType != typeof(DateTimeOffset)) { throw new ODataException(ODataErrorStrings.ODataJsonReaderUtils_CannotConvertDateTimeOffset(primitiveTypeReference.ODataFullName())); } } } catch (Exception e) { if (!ExceptionUtils.IsCatchableExceptionType(e)) { throw; } throw ReaderValidationUtils.GetPrimitiveTypeConversionException(primitiveTypeReference, e, value.ToString()); } // otherwise just return the value without doing any conversion return(value); }
/// <summary> /// Converts the given JSON int value to the expected type as per OData conversion rules for JSON values. /// </summary> /// <param name="intValue">Int32 value to the converted.</param> /// <param name="targetType">Target type to which the int value needs to be converted.</param> /// <param name="primitiveTypeReference">Type reference to which the value needs to be converted.</param> /// <param name="usesV1ProviderBehavior">true if the conversion should use the V1 provider behavior, false if the default behavior should be used.</param> /// <returns>Object which is in sync with the property type (modulo the V1 exception of converting numbers to non-compatible target types).</returns> private static object ConvertInt32Value(int intValue, Type targetType, IEdmPrimitiveTypeReference primitiveTypeReference, bool usesV1ProviderBehavior) { if (targetType == typeof(Int16)) { return(Convert.ToInt16(intValue)); } if (targetType == typeof(Byte)) { return(Convert.ToByte(intValue)); } if (targetType == typeof(SByte)) { return(Convert.ToSByte(intValue)); } if (targetType == typeof(Single)) { return(Convert.ToSingle(intValue)); } if (targetType == typeof(Double)) { return(Convert.ToDouble(intValue)); } if (targetType == typeof(Decimal) || targetType == typeof(Int64)) { throw new ODataException(o.Strings.ODataJsonReaderUtils_CannotConvertInt64OrDecimal); } if (!IsV1PrimitiveType(targetType) || (targetType != typeof(Int32) && !usesV1ProviderBehavior)) { throw new ODataException(o.Strings.ODataJsonReaderUtils_CannotConvertInt32(primitiveTypeReference.ODataFullName())); } return(intValue); }
/// <summary> /// Reads a primitive value. /// </summary> /// <param name="insideJsonObjectValue">true if the reader is positioned on the first property of the value which is a JSON Object /// (or the second property if the first one was odata.type).</param> /// <param name="expectedValueTypeReference">The expected type reference of the value, or null if none is available.</param> /// <param name="validateNullValue">true to validate null values; otherwise false.</param> /// <param name="propertyName">The name of the property whose value is being read, if applicable (used for error reporting).</param> /// <returns>The value of the primitive value.</returns> /// <remarks> /// Pre-Condition: insideJsonObjectValue == false -> none - Fails if the current node is not a JsonNodeType.PrimitiveValue /// insideJsonObjectValue == true -> JsonNodeType.Property or JsonNodeType.EndObject - the first property of the value object, /// or the second property if first was odata.type, or the end-object. /// Post-Condition: almost anything - the node after the primitive value. /// </remarks> private object ReadPrimitiveValue(bool insideJsonObjectValue, IEdmPrimitiveTypeReference expectedValueTypeReference, bool validateNullValue, string propertyName) { object result; if (expectedValueTypeReference != null && expectedValueTypeReference.IsSpatial()) { result = ODataJsonReaderCoreUtils.ReadSpatialValue( this.JsonReader, insideJsonObjectValue, this.JsonLightInputContext, expectedValueTypeReference, validateNullValue, this.recursionDepth, propertyName); } else { if (insideJsonObjectValue) { // We manually throw JSON exception here to get a nicer error message (we expect primitive value and got object). // Otherwise the ReadPrimitiveValue would fail with something like "expected primitive value but found property/end object" which is rather confusing. throw new ODataException(ODataErrorStrings.JsonReaderExtensions_UnexpectedNodeDetectedWithPropertyName(JsonNodeType.PrimitiveValue, JsonNodeType.StartObject, propertyName)); } result = this.JsonReader.ReadPrimitiveValue(); if (expectedValueTypeReference != null) { if ((expectedValueTypeReference.IsDecimal() || expectedValueTypeReference.IsInt64()) && result != null) { if ((result is string) ^ this.JsonReader.IsIeee754Compatible) { throw new ODataException(ODataErrorStrings.ODataJsonReaderUtils_ConflictBetweenInputFormatAndParameter(expectedValueTypeReference.ODataFullName())); } } result = ODataJsonLightReaderUtils.ConvertValue( result, expectedValueTypeReference, this.MessageReaderSettings, validateNullValue, propertyName, this.Model.GetPayloadValueConverter()); } else { if (result is Decimal) { // convert decimal back to double to follow legacy logic when target type is not specified and IEEE754Compatible=false. // we may lose precision for some range of int64 and decimal. return Convert.ToDouble((Decimal)result); } } } return result; }
/// <summary> /// Verifies that the given <paramref name="primitiveValue"/> is or can be coerced to <paramref name="expectedTypeReference"/>, and coerces it if necessary. /// </summary> /// <param name="primitiveValue">An EDM primitive value to verify.</param> /// <param name="model">Model to verify against.</param> /// <param name="expectedTypeReference">Expected type reference.</param> /// <returns>Coerced version of the <paramref name="primitiveValue"/>.</returns> internal static object VerifyAndCoerceUriPrimitiveLiteral(object primitiveValue, IEdmModel model, IEdmTypeReference expectedTypeReference) { ExceptionUtils.CheckArgumentNotNull(primitiveValue, "primitiveValue"); ExceptionUtils.CheckArgumentNotNull(model, "model"); ExceptionUtils.CheckArgumentNotNull(expectedTypeReference, "expectedTypeReference"); // First deal with null literal ODataNullValue nullValue = primitiveValue as ODataNullValue; if (nullValue != null) { if (!expectedTypeReference.IsNullable) { throw new ODataException(ODataErrorStrings.ODataUriUtils_ConvertFromUriLiteralNullOnNonNullableType(expectedTypeReference.ODataFullName())); } return(nullValue); } // Only other positive case is a numeric primitive that needs to be coerced IEdmPrimitiveTypeReference expectedPrimitiveTypeReference = expectedTypeReference.AsPrimitiveOrNull(); if (expectedPrimitiveTypeReference == null) { throw new ODataException(ODataErrorStrings.ODataUriUtils_ConvertFromUriLiteralTypeVerificationFailure(expectedTypeReference.ODataFullName(), primitiveValue)); } object coercedResult = CoerceNumericType(primitiveValue, expectedPrimitiveTypeReference.PrimitiveDefinition()); if (coercedResult != null) { return(coercedResult); } // if expectedTypeReference is set, need to coerce cast coercedResult = CoerceTemporalType(primitiveValue, expectedPrimitiveTypeReference.PrimitiveDefinition()); if (coercedResult != null) { return(coercedResult); } Type actualType = primitiveValue.GetType(); Type targetType = TypeUtils.GetNonNullableType(EdmLibraryExtensions.GetPrimitiveClrType(expectedPrimitiveTypeReference)); // If target type is assignable from actual type, we're OK if (targetType.IsAssignableFrom(actualType)) { return(primitiveValue); } throw new ODataException(ODataErrorStrings.ODataUriUtils_ConvertFromUriLiteralTypeVerificationFailure(expectedPrimitiveTypeReference.ODataFullName(), primitiveValue)); }
internal static ODataException GetPrimitiveTypeConversionException(IEdmPrimitiveTypeReference targetTypeReference, Exception innerException) { return(new ODataException(Microsoft.Data.OData.Strings.ReaderValidationUtils_CannotConvertPrimitiveValue(targetTypeReference.ODataFullName()), innerException)); }
/// <summary> /// Reads an annotation's value from the annotation value notation specified on the current element. /// </summary> /// <param name="expectedTypeReference">The expected type reference of the vocabulary term from the metadata.</param> /// <param name="attributeValueNotationTypeReference">The type reference indicated by the name of the attribute used in attribute value notation. /// For example, if the attribute was called "string", this will be a reference to the string type.</param> /// <param name="attributeValueNotationAttributeName">The name of the attribute used by attribute avalue notation.</param> /// <param name="attributeValueNotationAttributeValue">The value of the attribute used by attribute value notation.</param> /// <param name="typeAttributeValue">The value of the "m:type" attribute on the annotation element.</param> /// <param name="positionedOnEmptyElement">true if the annotation element is empty, false otherwise.</param> /// <param name="model">The edm model instance.</param> /// <param name="messageReaderSettings">The message reader settings instance.</param> /// <returns>The primitive value represented on this element via attribute value notation.</returns> private static ODataPrimitiveValue GetValueFromAttributeValueNotation( IEdmTypeReference expectedTypeReference, IEdmPrimitiveTypeReference attributeValueNotationTypeReference, string attributeValueNotationAttributeName, string attributeValueNotationAttributeValue, string typeAttributeValue, bool positionedOnEmptyElement, IEdmModel model, ODataMessageReaderSettings messageReaderSettings) { Debug.Assert(attributeValueNotationTypeReference != null, "attributeValueNotationTypeReference != null"); if (!positionedOnEmptyElement) { // If there is content in the body of the element, throw since it's ambiguous whether we should use the value from the attribute or the element content. throw new ODataException(ODataErrorStrings.AtomInstanceAnnotation_AttributeValueNotationUsedOnNonEmptyElement(attributeValueNotationAttributeName)); } // If both m:type is present and attribute value notation is being used, they must match. // For example, if m:type is "Edm.Int32", but the "string" attribute is also present, we should throw. if (typeAttributeValue != null && !string.Equals(attributeValueNotationTypeReference.Definition.ODataFullName(), typeAttributeValue, StringComparison.Ordinal)) { throw new ODataException(ODataErrorStrings.AtomInstanceAnnotation_AttributeValueNotationUsedWithIncompatibleType(typeAttributeValue, attributeValueNotationAttributeName)); } IEdmTypeReference targetTypeReference = ReaderValidationUtils.ResolveAndValidatePrimitiveTargetType( expectedTypeReference, EdmTypeKind.Primitive, attributeValueNotationTypeReference.Definition, attributeValueNotationTypeReference.ODataFullName(), attributeValueNotationTypeReference.Definition, model, messageReaderSettings); return new ODataPrimitiveValue(AtomValueUtils.ConvertStringToPrimitive(attributeValueNotationAttributeValue, targetTypeReference.AsPrimitive())); }
internal static ODataException GetPrimitiveTypeConversionException(IEdmPrimitiveTypeReference targetTypeReference, Exception innerException) { return new ODataException(Microsoft.Data.OData.Strings.ReaderValidationUtils_CannotConvertPrimitiveValue(targetTypeReference.ODataFullName()), innerException); }
/// <summary> /// Converts the given JSON value to the expected type as per OData conversion rules for JSON values. /// </summary> /// <param name="value">Value to the converted.</param> /// <param name="primitiveTypeReference">Type reference to which the value needs to be converted.</param> /// <param name="messageReaderSettings">The message reader settings used for reading.</param> /// <param name="version">The version of the OData protocol used for reading.</param> /// <param name="validateNullValue">true to validate null values; otherwise false.</param> /// <returns>Object which is in sync with the property type (modulo the V1 exception of converting numbers to non-compatible target types).</returns> internal static object ConvertValue( object value, IEdmPrimitiveTypeReference primitiveTypeReference, ODataMessageReaderSettings messageReaderSettings, ODataVersion version, bool validateNullValue) { DebugUtils.CheckNoExternalCallers(); Debug.Assert(primitiveTypeReference != null, "primitiveTypeReference != null"); //// NOTE: this method was copied from WCF DS (and changed to take a type reference instead of a CLR target type) if (value == null) { // Only primitive type references are validated. Core model is sufficient. ReaderValidationUtils.ValidateNullValue(EdmCoreModel.Instance, primitiveTypeReference, messageReaderSettings, validateNullValue, version); return(null); } try { Type targetType = EdmLibraryExtensions.GetPrimitiveClrType(primitiveTypeReference.PrimitiveDefinition(), false); ODataReaderBehavior readerBehavior = messageReaderSettings.ReaderBehavior; string stringValue = value as string; if (stringValue != null) { return(ConvertStringValue(stringValue, targetType, version)); } else if (value is Int32) { return(ConvertInt32Value((int)value, targetType, primitiveTypeReference, readerBehavior == null ? false : readerBehavior.UseV1ProviderBehavior)); } else if (value is Double) { Double doubleValue = (Double)value; if (targetType == typeof(Single)) { return(Convert.ToSingle(doubleValue)); } if (!IsV1PrimitiveType(targetType) || (targetType != typeof(Double) && (readerBehavior == null || !readerBehavior.UseV1ProviderBehavior))) { throw new ODataException(o.Strings.ODataJsonReaderUtils_CannotConvertDouble(primitiveTypeReference.ODataFullName())); } } else if (value is bool) { if (targetType != typeof(bool) && (readerBehavior == null || readerBehavior.FormatBehaviorKind != ODataBehaviorKind.WcfDataServicesServer)) { throw new ODataException(o.Strings.ODataJsonReaderUtils_CannotConvertBoolean(primitiveTypeReference.ODataFullName())); } } else if (value is DateTime) { if (targetType != typeof(DateTime) && (readerBehavior == null || readerBehavior.FormatBehaviorKind != ODataBehaviorKind.WcfDataServicesServer)) { throw new ODataException(o.Strings.ODataJsonReaderUtils_CannotConvertDateTime(primitiveTypeReference.ODataFullName())); } } else if (value is DateTimeOffset) { // Currently, we do not support any conversion for DateTimeOffset date type. Hence failing if the target // type is not DateTimeOffset. if (targetType != typeof(DateTimeOffset)) { throw new ODataException(o.Strings.ODataJsonReaderUtils_CannotConvertDateTimeOffset(primitiveTypeReference.ODataFullName())); } } } catch (Exception e) { if (!ExceptionUtils.IsCatchableExceptionType(e)) { throw; } throw ReaderValidationUtils.GetPrimitiveTypeConversionException(primitiveTypeReference, e); } // otherwise just return the value without doing any conversion return(value); }
private static object ConvertInt32Value(int intValue, Type targetType, IEdmPrimitiveTypeReference primitiveTypeReference, bool usesV1ProviderBehavior) { if (targetType == typeof(short)) { return(Convert.ToInt16(intValue)); } if (targetType == typeof(byte)) { return(Convert.ToByte(intValue)); } if (targetType == typeof(sbyte)) { return(Convert.ToSByte(intValue)); } if (targetType == typeof(float)) { return(Convert.ToSingle(intValue)); } if (targetType == typeof(double)) { return(Convert.ToDouble(intValue)); } if ((targetType == typeof(decimal)) || (targetType == typeof(long))) { throw new ODataException(Microsoft.Data.OData.Strings.ODataJsonReaderUtils_CannotConvertInt64OrDecimal); } if (!IsV1PrimitiveType(targetType) || ((targetType != typeof(int)) && !usesV1ProviderBehavior)) { throw new ODataException(Microsoft.Data.OData.Strings.ODataJsonReaderUtils_CannotConvertInt32(primitiveTypeReference.ODataFullName())); } return(intValue); }
/// <summary> /// Converts the given JSON int value to the expected type as per OData conversion rules for JSON values. /// </summary> /// <param name="intValue">Int32 value to the converted.</param> /// <param name="targetType">Target type to which the int value needs to be converted.</param> /// <param name="primitiveTypeReference">Type reference to which the value needs to be converted.</param> /// <returns>Object which is in sync with the property type.</returns> private static object ConvertInt32Value(int intValue, Type targetType, IEdmPrimitiveTypeReference primitiveTypeReference) { if (targetType == typeof(Int16)) { return(Convert.ToInt16(intValue)); } if (targetType == typeof(Byte)) { return(Convert.ToByte(intValue)); } if (targetType == typeof(SByte)) { return(Convert.ToSByte(intValue)); } if (targetType == typeof(Single)) { return(Convert.ToSingle(intValue)); } if (targetType == typeof(Double)) { return(Convert.ToDouble(intValue)); } if (targetType == typeof(Decimal)) { return(Convert.ToDecimal(intValue)); } if (targetType == typeof(Int64)) { return(Convert.ToInt64(intValue)); } if (targetType != typeof(Int32)) { throw new ODataException(ODataErrorStrings.ODataJsonReaderUtils_CannotConvertInt32(primitiveTypeReference.ODataFullName())); } return(intValue); }
internal static object ConvertValue(object value, IEdmPrimitiveTypeReference primitiveTypeReference, ODataMessageReaderSettings messageReaderSettings, ODataVersion version, bool validateNullValue) { if (value == null) { ReaderValidationUtils.ValidateNullValue(EdmCoreModel.Instance, primitiveTypeReference, messageReaderSettings, validateNullValue, version); return(null); } try { Type primitiveClrType = EdmLibraryExtensions.GetPrimitiveClrType(primitiveTypeReference.PrimitiveDefinition(), false); ODataReaderBehavior readerBehavior = messageReaderSettings.ReaderBehavior; string stringValue = value as string; if (stringValue != null) { return(ConvertStringValue(stringValue, primitiveClrType, version)); } if (value is int) { return(ConvertInt32Value((int)value, primitiveClrType, primitiveTypeReference, (readerBehavior != null) && readerBehavior.UseV1ProviderBehavior)); } if (value is double) { double num = (double)value; if (primitiveClrType == typeof(float)) { return(Convert.ToSingle(num)); } if (!IsV1PrimitiveType(primitiveClrType) || ((primitiveClrType != typeof(double)) && ((readerBehavior == null) || !readerBehavior.UseV1ProviderBehavior))) { throw new ODataException(Microsoft.Data.OData.Strings.ODataJsonReaderUtils_CannotConvertDouble(primitiveTypeReference.ODataFullName())); } return(value); } if (value is bool) { if ((primitiveClrType != typeof(bool)) && ((readerBehavior == null) || (readerBehavior.FormatBehaviorKind != ODataBehaviorKind.WcfDataServicesServer))) { throw new ODataException(Microsoft.Data.OData.Strings.ODataJsonReaderUtils_CannotConvertBoolean(primitiveTypeReference.ODataFullName())); } return(value); } if (value is DateTime) { if ((primitiveClrType != typeof(DateTime)) && ((readerBehavior == null) || (readerBehavior.FormatBehaviorKind != ODataBehaviorKind.WcfDataServicesServer))) { throw new ODataException(Microsoft.Data.OData.Strings.ODataJsonReaderUtils_CannotConvertDateTime(primitiveTypeReference.ODataFullName())); } return(value); } if ((value is DateTimeOffset) && (primitiveClrType != typeof(DateTimeOffset))) { throw new ODataException(Microsoft.Data.OData.Strings.ODataJsonReaderUtils_CannotConvertDateTimeOffset(primitiveTypeReference.ODataFullName())); } } catch (Exception exception) { if (!ExceptionUtils.IsCatchableExceptionType(exception)) { throw; } throw ReaderValidationUtils.GetPrimitiveTypeConversionException(primitiveTypeReference, exception); } return(value); }
/// <summary> /// Gets the type name based on the given odata value. /// </summary> /// <param name="value">The value.</param> /// <param name="model">The model used to handle unsigned int conversions.</param> /// <returns>The type name for the context URI.</returns> private static string GetTypeNameForValue(ODataValue value, IEdmModel model) { if (value == null) { return(null); } // special identifier for null values. if (value.IsNullValue) { return(ODataConstants.ContextUriFragmentNull); } var typeAnnotation = value.GetAnnotation <SerializationTypeNameAnnotation>(); if (typeAnnotation != null && !string.IsNullOrEmpty(typeAnnotation.TypeName)) { return(typeAnnotation.TypeName); } var complexValue = value as ODataComplexValue; if (complexValue != null) { return(complexValue.TypeName); } var collectionValue = value as ODataCollectionValue; if (collectionValue != null) { return(EdmLibraryExtensions.GetCollectionTypeFullName(collectionValue.TypeName)); } var enumValue = value as ODataEnumValue; if (enumValue != null) { return(enumValue.TypeName); } ODataPrimitiveValue primitive = value as ODataPrimitiveValue; if (primitive == null) { Debug.Assert(value is ODataStreamReferenceValue, "value is ODataStreamReferenceValue"); throw new ODataException(Strings.ODataContextUriBuilder_StreamValueMustBePropertiesOfODataEntry); } // Try convert to underlying type if the primitive value is unsigned int. IEdmTypeDefinitionReference typeDefinitionReference = model.ResolveUIntTypeDefinition(primitive.Value); if (typeDefinitionReference != null) { return(typeDefinitionReference.ODataFullName()); } IEdmPrimitiveTypeReference primitiveValueTypeReference = EdmLibraryExtensions.GetPrimitiveTypeReference(primitive.Value.GetType()); return(primitiveValueTypeReference == null ? null : primitiveValueTypeReference.ODataFullName()); }
/// <summary> /// Converts the given datetime value into the allowed target types. /// </summary> /// <param name="datetimeValue">DateTime value as read by the JsonReader.</param> /// <param name="targetType">Target type to which the datetime value needs to be converted.</param> /// <param name="primitiveTypeReference">Type reference to which the value needs to be converted.</param> /// <param name="readerBehavior">ODataReaderBehavior instance.</param> /// <returns>Object which is in sync with the target type.</returns> private static object ConvertDateTimeValue(DateTime datetimeValue, Type targetType, IEdmPrimitiveTypeReference primitiveTypeReference, ODataReaderBehavior readerBehavior) { if (targetType == typeof(DateTimeOffset)) { // If the kind of DateTime is local or UTC, that means we know the timezone information. Hence we should allow // conversion to DateTimeOffset - there is no dataloss or ambiguity in that conversion. if (datetimeValue.Kind == DateTimeKind.Local || datetimeValue.Kind == DateTimeKind.Utc) { return(new DateTimeOffset(datetimeValue)); } } if (targetType != typeof(DateTime) && (readerBehavior == null || readerBehavior.FormatBehaviorKind != ODataBehaviorKind.WcfDataServicesServer)) { throw new ODataException(ODataErrorStrings.ODataJsonReaderUtils_CannotConvertDateTime(primitiveTypeReference.ODataFullName())); } return(datetimeValue); }