Exemple #1
0
        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
                });
            }
        }
Exemple #3
0
        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);
        }
Exemple #5
0
        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"));
        }
Exemple #6
0
        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));
        }
Exemple #7
0
        /// <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");
        }
Exemple #9
0
        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;
        }
Exemple #11
0
        /// <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"));
 }
Exemple #15
0
        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");
 }