private ODataComplexValue ReadComplexValue(IEdmComplexTypeReference complexTypeReference, string payloadTypeName, SerializationTypeNameAnnotation serializationTypeNameAnnotation, DuplicatePropertyNamesChecker duplicatePropertyNamesChecker, bool epmPresent) { this.IncreaseRecursionDepth(); ODataComplexValue value2 = new ODataComplexValue(); IEdmComplexType type = (complexTypeReference == null) ? null : ((IEdmComplexType)complexTypeReference.Definition); value2.TypeName = (type == null) ? payloadTypeName : type.ODataFullName(); if (serializationTypeNameAnnotation != null) { value2.SetAnnotation <SerializationTypeNameAnnotation>(serializationTypeNameAnnotation); } base.XmlReader.MoveToElement(); if (duplicatePropertyNamesChecker == null) { duplicatePropertyNamesChecker = base.CreateDuplicatePropertyNamesChecker(); } else { duplicatePropertyNamesChecker.Clear(); } List <ODataProperty> properties = new List <ODataProperty>(); this.ReadPropertiesImplementation(type, properties, duplicatePropertyNamesChecker, epmPresent); value2.Properties = new ReadOnlyEnumerable <ODataProperty>(properties); this.DecreaseRecursionDepth(); return(value2); }
internal static void AddTypeNameAnnotationAsNeeded(ODataComplexValue value, ODataMetadataLevel metadataLevel) { // ODataLib normally has the caller decide whether or not to serialize properties by leaving properties // null when values should not be serialized. The TypeName property is different and should always be // provided to ODataLib to enable model validation. A separate annotation is used to decide whether or not // to serialize the type name (a null value prevents serialization). // Note that this annotation should not be used for Atom or JSON verbose formats, as it will interfere with // the correct default behavior for those formats. Contract.Assert(value != null); // Only add an annotation if we want to override ODataLib's default type name serialization behavior. if (ShouldAddTypeNameAnnotation(metadataLevel)) { string typeName; // Provide the type name to serialize (or null to force it not to serialize). if (ShouldSuppressTypeNameSerialization(metadataLevel)) { typeName = null; } else { typeName = value.TypeName; } value.SetAnnotation <SerializationTypeNameAnnotation>(new SerializationTypeNameAnnotation { TypeName = typeName }); } }
private ODataComplexValue CreateODataComplexValue(Type complexType, object value, string propertyName, bool isCollectionItem, List <object> visitedComplexTypeObjects) { ClientTypeAnnotation clientTypeAnnotation = ClientEdmModel.GetModel(this.requestInfo.MaxProtocolVersion).GetClientTypeAnnotation(complexType); if (visitedComplexTypeObjects == null) { visitedComplexTypeObjects = new List <object>(); } else if (visitedComplexTypeObjects.Contains(value)) { if (propertyName != null) { throw System.Data.Services.Client.Error.InvalidOperation(System.Data.Services.Client.Strings.Serializer_LoopsNotAllowedInComplexTypes(propertyName)); } throw System.Data.Services.Client.Error.InvalidOperation(System.Data.Services.Client.Strings.Serializer_LoopsNotAllowedInNonPropertyComplexTypes(clientTypeAnnotation.ElementTypeName)); } if (value == null) { return(null); } visitedComplexTypeObjects.Add(value); ODataComplexValue value2 = new ODataComplexValue(); if (!isCollectionItem) { SerializationTypeNameAnnotation annotation = new SerializationTypeNameAnnotation { TypeName = this.requestInfo.GetServerTypeName(clientTypeAnnotation) }; value2.SetAnnotation <SerializationTypeNameAnnotation>(annotation); } value2.Properties = this.PopulateProperties(clientTypeAnnotation, value, visitedComplexTypeObjects); visitedComplexTypeObjects.Remove(value); return(value2); }
/// <summary> /// Creates and returns an ODataComplexValue from the given value. /// </summary> /// <param name="complexType">The value type.</param> /// <param name="value">The complex value.</param> /// <param name="propertyName">If the value is a property, then it represents the name of the property. Can be null, for non-property.</param> /// <param name="isCollectionItem">True, if the value is an item in a collection, false otherwise.</param> /// <param name="visitedComplexTypeObjects">Set of instances of complex types encountered in the hierarchy. Used to detect cycles.</param> /// <returns>An ODataComplexValue representing the given value.</returns> internal ODataComplexValue CreateODataComplexValue(Type complexType, object value, string propertyName, bool isCollectionItem, HashSet <object> visitedComplexTypeObjects) { Debug.Assert(complexType != null, "complexType != null"); Debug.Assert(value != null || !isCollectionItem, "Collection items must not be null"); ClientEdmModel model = this.requestInfo.Model; ClientTypeAnnotation complexTypeAnnotation = model.GetClientTypeAnnotation(complexType); Debug.Assert(complexTypeAnnotation != null, "complexTypeAnnotation != null"); Debug.Assert(!complexTypeAnnotation.IsEntityType, "Unexpected entity"); // Handle null values for complex types by putting m:null="true" if (value == null) { Debug.Assert(!isCollectionItem, "Null collection items are not supported. Should have already been checked."); return(null); } if (visitedComplexTypeObjects == null) { visitedComplexTypeObjects = new HashSet <object>(ReferenceEqualityComparer <object> .Instance); } else if (visitedComplexTypeObjects.Contains(value)) { if (propertyName != null) { throw Error.InvalidOperation(Strings.Serializer_LoopsNotAllowedInComplexTypes(propertyName)); } else { Debug.Assert(complexTypeAnnotation.ElementTypeName != null, "complexTypeAnnotation.ElementTypeName != null"); throw Error.InvalidOperation(Strings.Serializer_LoopsNotAllowedInNonPropertyComplexTypes(complexTypeAnnotation.ElementTypeName)); } } visitedComplexTypeObjects.Add(value); ODataComplexValue odataComplexValue = new ODataComplexValue(); // When TypeName is set, it causes validation to occur when ODataLib writes out the collection. Part of the validation ensures that all items // in the collection are exactly the same type, no derived types are allowed. In the released WCF Data Services 5.0 implementation, we don't set // TypeName here, so that validation does not occur, therefore we will set this value only for JSON Light, so we don't break existing code. if (!this.requestInfo.Format.UsingAtom) { odataComplexValue.TypeName = complexTypeAnnotation.ElementTypeName; } // If this complex type is a collection item don't put type name on each item if (!isCollectionItem) { odataComplexValue.SetAnnotation(new SerializationTypeNameAnnotation { TypeName = this.requestInfo.GetServerTypeName(complexTypeAnnotation) }); } odataComplexValue.Properties = this.PopulateProperties(value, complexTypeAnnotation.PropertiesToSerialize(), visitedComplexTypeObjects); visitedComplexTypeObjects.Remove(value); return(odataComplexValue); }
public void BuildPropertyContextUriForComplexPropertyValueWithNonNullAnnotation() { ODataComplexValue value = new ODataComplexValue { TypeName = "FQNS.FromObject" }; value.SetAnnotation(new SerializationTypeNameAnnotation { TypeName = "FQNS.FromAnnotation" }); var contextUri = this.CreatePropertyContextUri(value); contextUri.OriginalString.Should().Be(BuildExpectedContextUri("#FQNS.FromAnnotation")); }
internal static IEdmValue CreateStructuredEdmValue(ODataComplexValue complexValue, IEdmComplexTypeReference complexType) { if (complexType != null) { object typeAnnotation = ReflectionUtils.CreateInstance( odataTypeAnnotationType, new Type[] { typeof(IEdmComplexTypeReference) }, complexType); complexValue.SetAnnotation(typeAnnotation); } return((IEdmValue)ReflectionUtils.CreateInstance( odataEdmStructuredValueType, new Type[] { typeof(ODataComplexValue) }, complexValue)); }
/// <summary> /// Read a complex value from the reader. /// </summary> /// <param name="complexTypeReference">The type reference of the value to read (or null if no type is available).</param> /// <param name="payloadTypeName">The name of the type specified in the payload.</param> /// <param name="serializationTypeNameAnnotation">The serialization type name for the complex value (possibly null).</param> /// <param name="duplicatePropertyNamesChecker">The duplicate property names checker to use (cached), or null if new one should be created.</param> /// <param name="epmPresent">Whether any EPM mappings exist.</param> /// <returns>The value read from the payload.</returns> /// <remarks> /// Pre-Condition: XmlNodeType.Element - the element to read the value for. /// XmlNodeType.Attribute - an attribute on the element to read the value for. /// Post-Condition: XmlNodeType.EndElement - the element has been read. /// /// Note that this method will not read null values, those should be handled by the caller already. /// </remarks> private ODataComplexValue ReadComplexValue( IEdmComplexTypeReference complexTypeReference, string payloadTypeName, SerializationTypeNameAnnotation serializationTypeNameAnnotation, DuplicatePropertyNamesChecker duplicatePropertyNamesChecker, bool epmPresent) { this.AssertXmlCondition(XmlNodeType.Element, XmlNodeType.Attribute); this.IncreaseRecursionDepth(); ODataComplexValue complexValue = new ODataComplexValue(); IEdmComplexType complexType = complexTypeReference == null ? null : (IEdmComplexType)complexTypeReference.Definition; // If we have a metadata type for the complex value, use that type name // otherwise use the type name from the payload (if there was any). complexValue.TypeName = complexType == null ? payloadTypeName : complexType.ODataFullName(); if (serializationTypeNameAnnotation != null) { complexValue.SetAnnotation(serializationTypeNameAnnotation); } // Move to the element (so that if we were on an attribute we can test the element for being empty) this.XmlReader.MoveToElement(); if (duplicatePropertyNamesChecker == null) { duplicatePropertyNamesChecker = this.CreateDuplicatePropertyNamesChecker(); } else { duplicatePropertyNamesChecker.Clear(); } List <ODataProperty> properties = new List <ODataProperty>(); this.ReadPropertiesImplementation(complexType, properties, duplicatePropertyNamesChecker, epmPresent); complexValue.Properties = new ReadOnlyEnumerable <ODataProperty>(properties); this.AssertXmlCondition(true, XmlNodeType.EndElement); Debug.Assert(complexValue != null, "The method should never return null since it doesn't handle null values."); this.DecreaseRecursionDepth(); return(complexValue); }
public void TypeNameShouldComeFromSerializationTypeNameAnnotationForComplexValue() { var stna = new SerializationTypeNameAnnotation() { TypeName = "FromSTNA" }; var value = new ODataComplexValue() { TypeName = "Model.Bla" }; value.SetAnnotation(stna); this.typeNameOracle.GetValueTypeNameForWriting(value, new EdmComplexTypeReference(new EdmComplexType("Model", "Bla"), true), new EdmComplexTypeReference(new EdmComplexType("Model", "Bla"), false), /* isOpenProperty*/ false).Should().Be("FromSTNA"); }
public void ValueWithTypeNameAnnotationShouldReturnTypeNameFromAnnotation() { var complexValue = new ODataComplexValue() { TypeName = ComplexTypeName }; complexValue.SetAnnotation(new SerializationTypeNameAnnotation { TypeName = "TypeNameFromSTNA" }); this.testSubject.GetValueTypeNameForWriting( complexValue, complexTypeReference, complexTypeReference, /*isOpen*/ false) .Should().Be("TypeNameFromSTNA"); }
/// <summary> /// Read a complex value from the reader. /// </summary> /// <param name="complexTypeReference">The type reference of the value to read (or null if no type is available).</param> /// <param name="payloadTypeName">The name of the type specified in the payload.</param> /// <param name="serializationTypeNameAnnotation">The serialization type name for the complex value (possibly null).</param> /// <param name="duplicatePropertyNamesChecker">The duplicate property names checker to use (cached), or null if new one should be created.</param> /// <returns>The value read from the payload.</returns> /// <remarks> /// Pre-Condition: XmlNodeType.Element - the element to read the value for. /// XmlNodeType.Attribute - an attribute on the element to read the value for. /// Post-Condition: XmlNodeType.EndElement - the element has been read. /// /// Note that this method will not read null values, those should be handled by the caller already. /// </remarks> private ODataComplexValue ReadComplexValue( IEdmComplexTypeReference complexTypeReference, string payloadTypeName, SerializationTypeNameAnnotation serializationTypeNameAnnotation, DuplicatePropertyNamesChecker duplicatePropertyNamesChecker) { this.AssertXmlCondition(XmlNodeType.Element, XmlNodeType.Attribute); this.IncreaseRecursionDepth(); ODataComplexValue complexValue = new ODataComplexValue(); IEdmComplexType complexType = complexTypeReference == null ? null : (IEdmComplexType)complexTypeReference.Definition; // If we have a metadata type for the complex value, use that type name // otherwise use the type name from the payload (if there was any). complexValue.TypeName = complexType == null ? payloadTypeName : complexType.ODataFullName(); if (serializationTypeNameAnnotation != null) { complexValue.SetAnnotation(serializationTypeNameAnnotation); } // Move to the element (so that if we were on an attribute we can test the element for being empty) this.XmlReader.MoveToElement(); if (duplicatePropertyNamesChecker == null) { duplicatePropertyNamesChecker = this.CreateDuplicatePropertyNamesChecker(); } else { duplicatePropertyNamesChecker.Clear(); } ReadOnlyEnumerable<ODataProperty> properties = new ReadOnlyEnumerable<ODataProperty>(); this.ReadPropertiesImplementation(complexType, properties, duplicatePropertyNamesChecker); complexValue.Properties = properties; this.AssertXmlCondition(true, XmlNodeType.EndElement); Debug.Assert(complexValue != null, "The method should never return null since it doesn't handle null values."); this.DecreaseRecursionDepth(); return complexValue; }
/// <summary> /// Reads a complex value. /// </summary> /// <param name="complexValueTypeReference">The expected type reference of the value.</param> /// <param name="payloadTypeName">The type name read from the payload.</param> /// <param name="serializationTypeNameAnnotation">The serialization type name for the collection value (possibly null).</param> /// <param name="duplicatePropertyNamesChecker">The duplicate property names checker to use - if null the method should create a new one if necessary.</param> /// <returns>The value of the complex value.</returns> /// <remarks> /// Pre-Condition: Fails if the current node is not a JsonNodeType.StartObject or JsonNodeType.PrimitiveValue (with null value) /// Post-Condition: almost anything - the node after the complex value (after the EndObject) /// </remarks> private ODataComplexValue ReadComplexValueImplementation( IEdmComplexTypeReference complexValueTypeReference, string payloadTypeName, SerializationTypeNameAnnotation serializationTypeNameAnnotation, DuplicatePropertyNamesChecker duplicatePropertyNamesChecker) { this.JsonReader.AssertNotBuffering(); this.IncreaseRecursionDepth(); // Read over the start object this.JsonReader.ReadStartObject(); ODataComplexValue complexValue = new ODataComplexValue(); complexValue.TypeName = complexValueTypeReference != null?complexValueTypeReference.ODataFullName() : payloadTypeName; if (serializationTypeNameAnnotation != null) { complexValue.SetAnnotation(serializationTypeNameAnnotation); } if (duplicatePropertyNamesChecker == null) { duplicatePropertyNamesChecker = this.CreateDuplicatePropertyNamesChecker(); } else { duplicatePropertyNamesChecker.Clear(); } List <ODataProperty> properties = new List <ODataProperty>(); bool metadataPropertyFound = false; while (this.JsonReader.NodeType == JsonNodeType.Property) { string propertyName = this.JsonReader.ReadPropertyName(); if (string.CompareOrdinal(JsonConstants.ODataMetadataName, propertyName) == 0) { // __metadata property. if (metadataPropertyFound) { throw new ODataException(ODataErrorStrings.ODataJsonPropertyAndValueDeserializer_MultipleMetadataPropertiesInComplexValue); } metadataPropertyFound = true; this.JsonReader.SkipValue(); } else { if (!ValidationUtils.IsValidPropertyName(propertyName)) { // We ignore properties with an invalid name since these are extension points for the future. this.JsonReader.SkipValue(); } else { // Any other property is data ODataProperty property = new ODataProperty(); property.Name = propertyName; // Lookup the property in metadata IEdmProperty edmProperty = null; bool ignoreProperty = false; if (complexValueTypeReference != null) { edmProperty = ReaderValidationUtils.ValidateValuePropertyDefined(propertyName, complexValueTypeReference.ComplexDefinition(), this.MessageReaderSettings, out ignoreProperty); } if (ignoreProperty) { // in case of ignoreProperty = true which means to ignore undeclared property. this.JsonReader.SkipValue(); } else { ODataNullValueBehaviorKind nullValueReadBehaviorKind = this.ReadingResponse || edmProperty == null ? ODataNullValueBehaviorKind.Default : this.Model.NullValueReadBehaviorKind(edmProperty); // Read the property value object propertyValue = this.ReadNonEntityValueImplementation( edmProperty == null ? null : edmProperty.Type, /*duplicatePropertyNamesChecker*/ null, /*collectionValidator*/ null, nullValueReadBehaviorKind == ODataNullValueBehaviorKind.Default, propertyName); if (nullValueReadBehaviorKind != ODataNullValueBehaviorKind.IgnoreValue || propertyValue != null) { duplicatePropertyNamesChecker.CheckForDuplicatePropertyNames(property); property.Value = propertyValue; properties.Add(property); } } } } } Debug.Assert(this.JsonReader.NodeType == JsonNodeType.EndObject, "After all the properties of a complex value are read the EndObject node is expected."); this.JsonReader.ReadEndObject(); complexValue.Properties = new ReadOnlyEnumerable <ODataProperty>(properties); this.JsonReader.AssertNotBuffering(); this.DecreaseRecursionDepth(); return(complexValue); }
public void ValueWithTypeNameAnnotationShouldReturnTypeNameFromAnnotation() { var complexValue = new ODataComplexValue() { TypeName = ComplexTypeName }; complexValue.SetAnnotation(new SerializationTypeNameAnnotation { TypeName = "TypeNameFromSTNA" }); this.testSubject.GetValueTypeNameForWriting( complexValue, complexTypeReference, complexTypeReference, /*isOpen*/ false) .Should().Be("TypeNameFromSTNA"); }
/// <summary> /// Reads a complex value. /// </summary> /// <param name="complexValueTypeReference">The expected type reference of the value.</param> /// <param name="payloadTypeName">The type name read from the payload.</param> /// <param name="serializationTypeNameAnnotation">The serialization type name for the collection value (possibly null).</param> /// <param name="duplicatePropertyNamesChecker">The duplicate property names checker to use - this is always initialized as necessary, do not clear.</param> /// <returns>The value of the complex value.</returns> /// <remarks> /// Pre-Condition: JsonNodeType.Property - the first property of the complex value object, or the second one if the first one was odata.type. /// JsonNodeType.EndObject - the end object of the complex value object. /// Post-Condition: almost anything - the node after the complex value (after the EndObject) /// </remarks> private ODataComplexValue ReadComplexValue( IEdmComplexTypeReference complexValueTypeReference, string payloadTypeName, SerializationTypeNameAnnotation serializationTypeNameAnnotation, DuplicatePropertyNamesChecker duplicatePropertyNamesChecker) { this.AssertJsonCondition(JsonNodeType.Property, JsonNodeType.EndObject); Debug.Assert(duplicatePropertyNamesChecker != null, "duplicatePropertyNamesChecker != null"); this.IncreaseRecursionDepth(); ODataComplexValue complexValue = new ODataComplexValue(); complexValue.TypeName = complexValueTypeReference != null ? complexValueTypeReference.FullName() : payloadTypeName; if (serializationTypeNameAnnotation != null) { complexValue.SetAnnotation(serializationTypeNameAnnotation); } if (complexValueTypeReference != null) { complexValue.SetAnnotation(new ODataTypeAnnotation(complexValueTypeReference)); } List<ODataProperty> properties = new List<ODataProperty>(); while (this.JsonReader.NodeType == JsonNodeType.Property) { this.ReadPropertyCustomAnnotationValue = this.ReadCustomInstanceAnnotationValue; this.ProcessProperty( duplicatePropertyNamesChecker, this.ReadTypePropertyAnnotationValue, (propertyParsingResult, propertyName) => { switch (propertyParsingResult) { case PropertyParsingResult.ODataInstanceAnnotation: if (string.CompareOrdinal(ODataAnnotationNames.ODataType, propertyName) == 0) { throw new ODataException(ODataErrorStrings.ODataJsonLightPropertyAndValueDeserializer_ComplexTypeAnnotationNotFirst); } else { throw new ODataException(ODataErrorStrings.ODataJsonLightPropertyAndValueDeserializer_UnexpectedAnnotationProperties(propertyName)); } case PropertyParsingResult.CustomInstanceAnnotation: ODataAnnotationNames.ValidateIsCustomAnnotationName(propertyName); Debug.Assert( !this.MessageReaderSettings.ShouldSkipAnnotation(propertyName), "!this.MessageReaderSettings.ShouldReadAndValidateAnnotation(annotationName) -- otherwise we should have already skipped the custom annotation and won't see it here."); var customInstanceAnnotationValue = this.ReadCustomInstanceAnnotationValue(duplicatePropertyNamesChecker, propertyName); complexValue.InstanceAnnotations.Add(new ODataInstanceAnnotation(propertyName, customInstanceAnnotationValue.ToODataValue())); break; case PropertyParsingResult.PropertyWithoutValue: throw new ODataException(ODataErrorStrings.ODataJsonLightPropertyAndValueDeserializer_ComplexValuePropertyAnnotationWithoutProperty(propertyName)); case PropertyParsingResult.PropertyWithValue: // Any other property is data ODataProperty property = new ODataProperty(); property.Name = propertyName; // Lookup the property in metadata IEdmProperty edmProperty = null; bool ignoreProperty = false; if (complexValueTypeReference != null) { edmProperty = ReaderValidationUtils.ValidateValuePropertyDefined(propertyName, complexValueTypeReference.ComplexDefinition(), this.MessageReaderSettings, out ignoreProperty); } if (ignoreProperty && (this.JsonReader.NodeType == JsonNodeType.StartObject || this.JsonReader.NodeType == JsonNodeType.StartArray)) { this.JsonReader.SkipValue(); } else { // EdmLib bridge marks all key properties as non-nullable, but Astoria allows them to be nullable. // If the property has an annotation to ignore null values, we need to omit the property in requests. ODataNullValueBehaviorKind nullValueReadBehaviorKind = this.ReadingResponse || edmProperty == null ? ODataNullValueBehaviorKind.Default : this.Model.NullValueReadBehaviorKind(edmProperty); // Read the property value object propertyValue = this.ReadNonEntityValueImplementation( ValidateDataPropertyTypeNameAnnotation(duplicatePropertyNamesChecker, propertyName), edmProperty == null ? null : edmProperty.Type, /*duplicatePropertyNamesChecker*/ null, /*collectionValidator*/ null, nullValueReadBehaviorKind == ODataNullValueBehaviorKind.Default, /*isTopLevelPropertyValue*/ false, /*insideComplexValue*/ false, propertyName, edmProperty == null); if (nullValueReadBehaviorKind != ODataNullValueBehaviorKind.IgnoreValue || propertyValue != null) { duplicatePropertyNamesChecker.CheckForDuplicatePropertyNames(property); property.Value = propertyValue; var propertyAnnotations = duplicatePropertyNamesChecker.GetCustomPropertyAnnotations(propertyName); if (propertyAnnotations != null) { foreach (var annotation in propertyAnnotations) { if (annotation.Value != null) { // annotation.Value == null indicates that this annotation should be skipped. property.InstanceAnnotations.Add(new ODataInstanceAnnotation(annotation.Key, annotation.Value.ToODataValue())); } } } properties.Add(property); } } break; case PropertyParsingResult.EndOfObject: break; case PropertyParsingResult.MetadataReferenceProperty: throw new ODataException(ODataErrorStrings.ODataJsonLightPropertyAndValueDeserializer_UnexpectedMetadataReferenceProperty(propertyName)); } }); } Debug.Assert(this.JsonReader.NodeType == JsonNodeType.EndObject, "After all the properties of a complex value are read the EndObject node is expected."); this.JsonReader.ReadEndObject(); complexValue.Properties = new ReadOnlyEnumerable<ODataProperty>(properties); this.DecreaseRecursionDepth(); return complexValue; }
public void BuildPropertyContextUriForComplexPropertyValueWithNonNullAnnotation() { ODataComplexValue value = new ODataComplexValue { TypeName = "FQNS.FromObject" }; value.SetAnnotation(new SerializationTypeNameAnnotation { TypeName = "FQNS.FromAnnotation" }); var contextUri = this.CreatePropertyContextUri(value); contextUri.OriginalString.Should().Be(BuildExpectedContextUri("#FQNS.FromAnnotation")); }
private ODataComplexValue ReadComplexValueImplementation(IEdmComplexTypeReference complexValueTypeReference, string payloadTypeName, SerializationTypeNameAnnotation serializationTypeNameAnnotation, DuplicatePropertyNamesChecker duplicatePropertyNamesChecker) { this.IncreaseRecursionDepth(); base.JsonReader.ReadStartObject(); ODataComplexValue value2 = new ODataComplexValue { TypeName = (complexValueTypeReference != null) ? complexValueTypeReference.ODataFullName() : payloadTypeName }; if (serializationTypeNameAnnotation != null) { value2.SetAnnotation <SerializationTypeNameAnnotation>(serializationTypeNameAnnotation); } if (duplicatePropertyNamesChecker == null) { duplicatePropertyNamesChecker = base.CreateDuplicatePropertyNamesChecker(); } else { duplicatePropertyNamesChecker.Clear(); } List <ODataProperty> sourceList = new List <ODataProperty>(); bool flag = false; while (base.JsonReader.NodeType == JsonNodeType.Property) { string strB = base.JsonReader.ReadPropertyName(); if (string.CompareOrdinal("__metadata", strB) == 0) { if (flag) { throw new ODataException(Microsoft.Data.OData.Strings.ODataJsonPropertyAndValueDeserializer_MultipleMetadataPropertiesInComplexValue); } flag = true; base.JsonReader.SkipValue(); } else if (!ValidationUtils.IsValidPropertyName(strB)) { base.JsonReader.SkipValue(); } else { ODataProperty property = new ODataProperty { Name = strB }; IEdmProperty property2 = null; bool ignoreProperty = false; if (complexValueTypeReference != null) { property2 = ReaderValidationUtils.ValidateValuePropertyDefined(strB, complexValueTypeReference.ComplexDefinition(), base.MessageReaderSettings, out ignoreProperty); } if (ignoreProperty) { base.JsonReader.SkipValue(); continue; } ODataNullValueBehaviorKind kind = (base.ReadingResponse || (property2 == null)) ? ODataNullValueBehaviorKind.Default : base.Model.NullValueReadBehaviorKind(property2); object obj2 = this.ReadNonEntityValueImplementation((property2 == null) ? null : property2.Type, null, null, kind == ODataNullValueBehaviorKind.Default); if ((kind != ODataNullValueBehaviorKind.IgnoreValue) || (obj2 != null)) { duplicatePropertyNamesChecker.CheckForDuplicatePropertyNames(property); property.Value = obj2; sourceList.Add(property); } } } base.JsonReader.ReadEndObject(); value2.Properties = new ReadOnlyEnumerable <ODataProperty>(sourceList); this.DecreaseRecursionDepth(); return(value2); }
public void TypeNameShouldComeFromSerializationTypeNameAnnotationForComplexValue() { var stna = new SerializationTypeNameAnnotation() {TypeName = "FromSTNA"}; var value = new ODataComplexValue() {TypeName = "Model.Bla"}; value.SetAnnotation(stna); this.typeNameOracle.GetValueTypeNameForWriting(value, new EdmComplexTypeReference(new EdmComplexType("Model", "Bla"), true), new EdmComplexTypeReference(new EdmComplexType("Model", "Bla"), false), /* isOpenProperty*/ false).Should().Be("FromSTNA"); }