Beispiel #1
0
 internal static IEdmTypeReference ResolveAndValidateNonPrimitiveTargetType(EdmTypeKind expectedTypeKind, IEdmTypeReference expectedTypeReference, EdmTypeKind payloadTypeKind, IEdmType payloadType, string payloadTypeName, IEdmModel model, ODataMessageReaderSettings messageReaderSettings, ODataVersion version, out SerializationTypeNameAnnotation serializationTypeNameAnnotation)
 {
     bool flag = (messageReaderSettings.ReaderBehavior.TypeResolver != null) && (payloadType != null);
     if (!flag)
     {
         ValidateTypeSupported(expectedTypeReference, version);
         if (model.IsUserModel() && ((expectedTypeReference == null) || !messageReaderSettings.DisableStrictMetadataValidation))
         {
             VerifyPayloadTypeDefined(payloadTypeName, payloadType);
         }
     }
     else
     {
         ValidateTypeSupported((payloadType == null) ? null : payloadType.ToTypeReference(true), version);
     }
     if ((payloadTypeKind != EdmTypeKind.None) && (!messageReaderSettings.DisableStrictMetadataValidation || (expectedTypeReference == null)))
     {
         ValidationUtils.ValidateTypeKind(payloadTypeKind, expectedTypeKind, payloadTypeName);
     }
     serializationTypeNameAnnotation = null;
     if (!model.IsUserModel())
     {
         return null;
     }
     if ((expectedTypeReference == null) || flag)
     {
         return ResolveAndValidateTargetTypeWithNoExpectedType(expectedTypeKind, payloadType, payloadTypeName, out serializationTypeNameAnnotation);
     }
     if (messageReaderSettings.DisableStrictMetadataValidation)
     {
         return ResolveAndValidateTargetTypeStrictValidationDisabled(expectedTypeKind, expectedTypeReference, payloadType, payloadTypeName, out serializationTypeNameAnnotation);
     }
     return ResolveAndValidateTargetTypeStrictValidationEnabled(expectedTypeKind, expectedTypeReference, payloadType, payloadTypeName, out serializationTypeNameAnnotation);
 }
        internal string GetEntryTypeNameForWriting(ODataEntry entry)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(entry != null, "entry != null");

            SerializationTypeNameAnnotation typeNameAnnotation = entry.GetAnnotation <SerializationTypeNameAnnotation>();

            if (typeNameAnnotation != null)
            {
                return(typeNameAnnotation.TypeName);
            }

            return(entry.TypeName);
        }
        internal string GetValueTypeNameForWriting(
            object value,
            IEdmTypeReference typeReferenceFromValue,
            SerializationTypeNameAnnotation typeNameAnnotation,
            CollectionWithoutExpectedTypeValidator collectionValidator,
            out string collectionItemTypeName)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(value != null, "value != null");

            collectionItemTypeName = null;

            // if no type name is specified we will use the type name inferred from metadata
            string typeName = GetTypeNameFromValue(value);

            if (typeName == null && typeReferenceFromValue != null)
            {
                typeName = typeReferenceFromValue.ODataFullName();
            }

            if (typeName != null)
            {
                // If the type is the same as the one specified by the parent collection, omit the type name, since it's not needed.
                if (collectionValidator != null && string.CompareOrdinal(collectionValidator.ItemTypeNameFromCollection, typeName) == 0)
                {
                    typeName = null;
                }

                // If value is a collection value, get the item type name.
                if (typeName != null && value is ODataCollectionValue)
                {
                    collectionItemTypeName = ValidationUtils.ValidateCollectionTypeName(typeName);
                }
            }

            if (typeNameAnnotation != null)
            {
                // If the value of TypeName is null, we'll flow it through here, thereby instructing the caller to write no type name.
                typeName = typeNameAnnotation.TypeName;
            }

            return(typeName);
        }
        private ODataCollectionValue ReadCollectionValue(IEdmCollectionTypeReference collectionTypeReference, string payloadTypeName, SerializationTypeNameAnnotation serializationTypeNameAnnotation)
        {
            this.IncreaseRecursionDepth();
            ODataCollectionValue value2 = new ODataCollectionValue {
                TypeName = (collectionTypeReference == null) ? payloadTypeName : collectionTypeReference.ODataFullName()
            };
            if (serializationTypeNameAnnotation != null)
            {
                value2.SetAnnotation<SerializationTypeNameAnnotation>(serializationTypeNameAnnotation);
            }
            base.XmlReader.MoveToElement();
            List<object> sourceEnumerable = new List<object>();
            if (!base.XmlReader.IsEmptyElement)
            {
                base.XmlReader.ReadStartElement();
                IEdmTypeReference expectedTypeReference = (collectionTypeReference == null) ? null : collectionTypeReference.ElementType();
                DuplicatePropertyNamesChecker duplicatePropertyNamesChecker = base.CreateDuplicatePropertyNamesChecker();
                CollectionWithoutExpectedTypeValidator collectionValidator = null;
                if (collectionTypeReference == null)
                {
                    string itemTypeNameFromCollection = (payloadTypeName == null) ? null : EdmLibraryExtensions.GetCollectionItemTypeName(payloadTypeName);
                    collectionValidator = new CollectionWithoutExpectedTypeValidator(itemTypeNameFromCollection);
                }
                do
                {
                    switch (base.XmlReader.NodeType)
                    {
                        case XmlNodeType.Element:
                            if (base.XmlReader.NamespaceEquals(base.XmlReader.ODataNamespace))
                            {
                                if (!base.XmlReader.LocalNameEquals(this.ODataCollectionItemElementName))
                                {
                                    throw new ODataException(Microsoft.Data.OData.Strings.ODataAtomPropertyAndValueDeserializer_InvalidCollectionElement(base.XmlReader.LocalName, base.XmlReader.ODataNamespace));
                                }
                                object item = this.ReadNonEntityValueImplementation(expectedTypeReference, duplicatePropertyNamesChecker, collectionValidator, true, false);
                                base.XmlReader.Read();
                                ValidationUtils.ValidateCollectionItem(item, false);
                                sourceEnumerable.Add(item);
                            }
                            else
                            {
                                base.XmlReader.Skip();
                            }
                            break;

                        case XmlNodeType.EndElement:
                            break;

                        default:
                            base.XmlReader.Skip();
                            break;
                    }
                }
                while (base.XmlReader.NodeType != XmlNodeType.EndElement);
            }
            value2.Items = new ReadOnlyEnumerable(sourceEnumerable);
            this.DecreaseRecursionDepth();
            return value2;
        }
Beispiel #5
0
 internal static IEdmTypeReference ResolvePayloadTypeNameAndComputeTargetType(EdmTypeKind expectedTypeKind, IEdmType defaultPrimitivePayloadType, IEdmTypeReference expectedTypeReference, string payloadTypeName, IEdmModel model, ODataMessageReaderSettings messageReaderSettings, ODataVersion version, Func<EdmTypeKind> typeKindFromPayloadFunc, out EdmTypeKind targetTypeKind, out SerializationTypeNameAnnotation serializationTypeNameAnnotation)
 {
     EdmTypeKind kind;
     IEdmTypeReference reference;
     serializationTypeNameAnnotation = null;
     IEdmType payloadType = ResolvePayloadTypeName(model, expectedTypeReference, payloadTypeName, EdmTypeKind.Complex, messageReaderSettings.ReaderBehavior, version, out kind);
     targetTypeKind = ComputeTargetTypeKind(expectedTypeReference, expectedTypeKind == EdmTypeKind.Entity, payloadTypeName, kind, messageReaderSettings, typeKindFromPayloadFunc);
     if (targetTypeKind == EdmTypeKind.Primitive)
     {
         reference = ResolveAndValidatePrimitiveTargetType(expectedTypeReference, kind, payloadType, payloadTypeName, defaultPrimitivePayloadType, model, messageReaderSettings, version);
     }
     else
     {
         reference = ResolveAndValidateNonPrimitiveTargetType(targetTypeKind, expectedTypeReference, kind, payloadType, payloadTypeName, model, messageReaderSettings, version, out serializationTypeNameAnnotation);
     }
     if ((expectedTypeKind != EdmTypeKind.None) && (reference != null))
     {
         ValidationUtils.ValidateTypeKind(targetTypeKind, expectedTypeKind, payloadTypeName);
     }
     return reference;
 }
 private ODataCollectionValue ReadCollectionValueImplementation(IEdmCollectionTypeReference collectionValueTypeReference, string payloadTypeName, SerializationTypeNameAnnotation serializationTypeNameAnnotation)
 {
     ODataVersionChecker.CheckCollectionValue(base.Version);
     this.IncreaseRecursionDepth();
     base.JsonReader.ReadStartObject();
     ODataCollectionValue value2 = new ODataCollectionValue {
         TypeName = (collectionValueTypeReference != null) ? collectionValueTypeReference.ODataFullName() : payloadTypeName
     };
     if (serializationTypeNameAnnotation != null)
     {
         value2.SetAnnotation<SerializationTypeNameAnnotation>(serializationTypeNameAnnotation);
     }
     List<object> sourceEnumerable = null;
     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_MultiplePropertiesInCollectionWrapper("__metadata"));
             }
             flag = true;
             base.JsonReader.SkipValue();
         }
         else
         {
             if (string.CompareOrdinal("results", strB) == 0)
             {
                 if (sourceEnumerable != null)
                 {
                     throw new ODataException(Microsoft.Data.OData.Strings.ODataJsonPropertyAndValueDeserializer_MultiplePropertiesInCollectionWrapper("results"));
                 }
                 sourceEnumerable = new List<object>();
                 base.JsonReader.ReadStartArray();
                 DuplicatePropertyNamesChecker duplicatePropertyNamesChecker = base.CreateDuplicatePropertyNamesChecker();
                 IEdmTypeReference expectedTypeReference = null;
                 if (collectionValueTypeReference != null)
                 {
                     expectedTypeReference = collectionValueTypeReference.CollectionDefinition().ElementType;
                 }
                 CollectionWithoutExpectedTypeValidator collectionValidator = null;
                 while (base.JsonReader.NodeType != JsonNodeType.EndArray)
                 {
                     object item = this.ReadNonEntityValueImplementation(expectedTypeReference, duplicatePropertyNamesChecker, collectionValidator, true);
                     ValidationUtils.ValidateCollectionItem(item, false);
                     sourceEnumerable.Add(item);
                 }
                 base.JsonReader.ReadEndArray();
                 continue;
             }
             base.JsonReader.SkipValue();
         }
     }
     base.JsonReader.ReadEndObject();
     if (sourceEnumerable == null)
     {
         throw new ODataException(Microsoft.Data.OData.Strings.ODataJsonPropertyAndValueDeserializer_CollectionWithoutResults);
     }
     value2.Items = new ReadOnlyEnumerable(sourceEnumerable);
     this.DecreaseRecursionDepth();
     return value2;
 }
        private object ReadNonEntityValueImplementation(IEdmTypeReference expectedTypeReference, DuplicatePropertyNamesChecker duplicatePropertyNamesChecker, CollectionWithoutExpectedTypeValidator collectionValidator, bool validateNullValue, bool epmPresent)
        {
            string itemTypeNameFromCollection;
            bool flag;
            SerializationTypeNameAnnotation annotation;
            EdmTypeKind kind2;
            this.ReadNonEntityValueAttributes(out itemTypeNameFromCollection, out flag);
            if (flag)
            {
                return this.ReadNullValue(expectedTypeReference, validateNullValue);
            }
            bool flag2 = false;
            if ((collectionValidator != null) && (itemTypeNameFromCollection == null))
            {
                itemTypeNameFromCollection = collectionValidator.ItemTypeNameFromCollection;
                flag2 = collectionValidator.ItemTypeKindFromCollection != EdmTypeKind.None;
            }
            IEdmTypeReference type = ReaderValidationUtils.ResolvePayloadTypeNameAndComputeTargetType(EdmTypeKind.None, edmStringType, expectedTypeReference, itemTypeNameFromCollection, base.Model, base.MessageReaderSettings, base.Version, new Func<EdmTypeKind>(this.GetNonEntityValueKind), out kind2, out annotation);
            if (flag2)
            {
                annotation = new SerializationTypeNameAnnotation {
                    TypeName = null
                };
            }
            if (collectionValidator != null)
            {
                collectionValidator.ValidateCollectionItem(itemTypeNameFromCollection, kind2);
            }
            switch (kind2)
            {
                case EdmTypeKind.Primitive:
                    return this.ReadPrimitiveValue(type.AsPrimitive());

                case EdmTypeKind.Complex:
                    return this.ReadComplexValue((type == null) ? null : type.AsComplex(), itemTypeNameFromCollection, annotation, duplicatePropertyNamesChecker, epmPresent);

                case EdmTypeKind.Collection:
                {
                    IEdmCollectionTypeReference collectionTypeReference = ValidationUtils.ValidateCollectionType(type);
                    return this.ReadCollectionValue(collectionTypeReference, itemTypeNameFromCollection, annotation);
                }
            }
            throw new ODataException(Microsoft.Data.OData.Strings.General_InternalError(InternalErrorCodes.ODataAtomPropertyAndValueDeserializer_ReadNonEntityValue));
        }
Beispiel #8
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>
        /// Reads a collection value.
        /// </summary>
        /// <param name="collectionValueTypeReference">The collection 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>
        /// <returns>The value of the collection.</returns>
        /// <remarks>
        /// Pre-Condition:  Fails if the current node is not a JsonNodeType.StartObject
        /// Post-Condition: almost anything - the node after the collection value (after the EndObject)
        /// </remarks>
        private ODataCollectionValue ReadCollectionValueImplementation(
            IEdmCollectionTypeReference collectionValueTypeReference, 
            string payloadTypeName,
            SerializationTypeNameAnnotation serializationTypeNameAnnotation)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(
                collectionValueTypeReference == null || collectionValueTypeReference.IsNonEntityODataCollectionTypeKind(),
                "If the metadata is specified it must denote a Collection for this method to work.");
            this.JsonReader.AssertNotBuffering();

            ODataVersionChecker.CheckCollectionValue(this.Version);

            this.IncreaseRecursionDepth();

            // Read over the start object
            this.JsonReader.ReadStartObject();

            ODataCollectionValue collectionValue = new ODataCollectionValue();
            collectionValue.TypeName = collectionValueTypeReference != null ? collectionValueTypeReference.ODataFullName() : payloadTypeName;
            if (serializationTypeNameAnnotation != null)
            {
                collectionValue.SetAnnotation(serializationTypeNameAnnotation);
            }

            List<object> items = null;
            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(o.Strings.ODataJsonPropertyAndValueDeserializer_MultiplePropertiesInCollectionWrapper(JsonConstants.ODataMetadataName));
                    }

                    metadataPropertyFound = true;

                    // Note that we don't need to read the type name again, as we've already read it above in FindTypeNameInPayload.
                    // There's nothing else of interest in the __metadata for collections.
                    this.JsonReader.SkipValue();
                }
                else if (string.CompareOrdinal(JsonConstants.ODataResultsName, propertyName) == 0)
                {
                    // results property
                    if (items != null)
                    {
                        throw new ODataException(o.Strings.ODataJsonPropertyAndValueDeserializer_MultiplePropertiesInCollectionWrapper(JsonConstants.ODataResultsName));
                    }

                    items = new List<object>();

                    this.JsonReader.ReadStartArray();

                    DuplicatePropertyNamesChecker duplicatePropertyNamesChecker = this.CreateDuplicatePropertyNamesChecker();
                    IEdmTypeReference itemType = null;
                    if (collectionValueTypeReference != null)
                    {
                        itemType = collectionValueTypeReference.CollectionDefinition().ElementType;
                    }

                    // NOTE: we do not support reading JSON without metadata right now so we always have an expected item type;
                    //       The collection validator is always null.
                    CollectionWithoutExpectedTypeValidator collectionValidator = null;

                    while (this.JsonReader.NodeType != JsonNodeType.EndArray)
                    {
                        object itemValue = this.ReadNonEntityValueImplementation(
                            itemType,
                            duplicatePropertyNamesChecker,
                            collectionValidator,
                            /*validateNullValue*/ true);

                        // Validate the item (for example that it's not null)
                        ValidationUtils.ValidateCollectionItem(itemValue, false /* isStreamable */);

                        // Note that the ReadNonEntityValue already validated that the actual type of the value matches
                        // the expected type (the itemType).
                        items.Add(itemValue);
                    }

                    Debug.Assert(this.JsonReader.NodeType == JsonNodeType.EndArray, "The results value must end with an end array.");
                    this.JsonReader.ReadEndArray();
                }
                else
                {
                    // Skip over any other property in the collection object
                    this.JsonReader.SkipValue();
                }
            }

            Debug.Assert(this.JsonReader.NodeType == JsonNodeType.EndObject, "After all properties of Collection wrapper are read the EndObject node is expected.");
            this.JsonReader.ReadEndObject();

            if (items == null)
            {
                // We didn't find any results property. All collections must have the results property.
                throw new ODataException(o.Strings.ODataJsonPropertyAndValueDeserializer_CollectionWithoutResults);
            }

            collectionValue.Items = new ReadOnlyEnumerable(items);

            this.JsonReader.AssertNotBuffering();
            this.DecreaseRecursionDepth();

            return collectionValue;
        }
        private static IEdmTypeReference ResolveAndValidateTargetTypeWithNoExpectedType(EdmTypeKind expectedTypeKind, IEdmType payloadType, string payloadTypeName, out SerializationTypeNameAnnotation serializationTypeNameAnnotation)
        {
            serializationTypeNameAnnotation = null;
            if (payloadType == null)
            {
                if (expectedTypeKind == EdmTypeKind.Entity)
                {
                    throw new ODataException(Microsoft.Data.OData.Strings.ReaderValidationUtils_EntryWithoutType);
                }
                throw new ODataException(Microsoft.Data.OData.Strings.ReaderValidationUtils_ValueWithoutType);
            }
            IEdmTypeReference targetTypeReference = payloadType.ToTypeReference(true);

            serializationTypeNameAnnotation = CreateSerializationTypeNameAnnotation(payloadTypeName, targetTypeReference);
            return(targetTypeReference);
        }
        internal static IEdmTypeReference ResolveAndValidateNonPrimitiveTargetType(EdmTypeKind expectedTypeKind, IEdmTypeReference expectedTypeReference, EdmTypeKind payloadTypeKind, IEdmType payloadType, string payloadTypeName, IEdmModel model, ODataMessageReaderSettings messageReaderSettings, ODataVersion version, out SerializationTypeNameAnnotation serializationTypeNameAnnotation)
        {
            bool flag = (messageReaderSettings.ReaderBehavior.TypeResolver != null) && (payloadType != null);

            if (!flag)
            {
                ValidateTypeSupported(expectedTypeReference, version);
                if (model.IsUserModel() && ((expectedTypeReference == null) || !messageReaderSettings.DisableStrictMetadataValidation))
                {
                    VerifyPayloadTypeDefined(payloadTypeName, payloadType);
                }
            }
            else
            {
                ValidateTypeSupported((payloadType == null) ? null : payloadType.ToTypeReference(true), version);
            }
            if ((payloadTypeKind != EdmTypeKind.None) && (!messageReaderSettings.DisableStrictMetadataValidation || (expectedTypeReference == null)))
            {
                ValidationUtils.ValidateTypeKind(payloadTypeKind, expectedTypeKind, payloadTypeName);
            }
            serializationTypeNameAnnotation = null;
            if (!model.IsUserModel())
            {
                return(null);
            }
            if ((expectedTypeReference == null) || flag)
            {
                return(ResolveAndValidateTargetTypeWithNoExpectedType(expectedTypeKind, payloadType, payloadTypeName, out serializationTypeNameAnnotation));
            }
            if (messageReaderSettings.DisableStrictMetadataValidation)
            {
                return(ResolveAndValidateTargetTypeStrictValidationDisabled(expectedTypeKind, expectedTypeReference, payloadType, payloadTypeName, out serializationTypeNameAnnotation));
            }
            return(ResolveAndValidateTargetTypeStrictValidationEnabled(expectedTypeKind, expectedTypeReference, payloadType, payloadTypeName, out serializationTypeNameAnnotation));
        }
Beispiel #12
0
 private static IEdmTypeReference ResolveAndValidateTargetTypeWithNoExpectedType(EdmTypeKind expectedTypeKind, IEdmType payloadType, string payloadTypeName, out SerializationTypeNameAnnotation serializationTypeNameAnnotation)
 {
     serializationTypeNameAnnotation = null;
     if (payloadType == null)
     {
         if (expectedTypeKind == EdmTypeKind.Entity)
         {
             throw new ODataException(Microsoft.Data.OData.Strings.ReaderValidationUtils_EntryWithoutType);
         }
         throw new ODataException(Microsoft.Data.OData.Strings.ReaderValidationUtils_ValueWithoutType);
     }
     IEdmTypeReference targetTypeReference = payloadType.ToTypeReference(true);
     serializationTypeNameAnnotation = CreateSerializationTypeNameAnnotation(payloadTypeName, targetTypeReference);
     return targetTypeReference;
 }
        private static IEdmTypeReference ResolveAndValidateTargetTypeStrictValidationDisabled(EdmTypeKind expectedTypeKind, IEdmTypeReference expectedTypeReference, IEdmType payloadType, string payloadTypeName, out SerializationTypeNameAnnotation serializationTypeNameAnnotation)
        {
            switch (expectedTypeKind)
            {
            case EdmTypeKind.Entity:
            {
                if (((payloadType == null) || (expectedTypeKind != payloadType.TypeKind)) || !expectedTypeReference.AsEntity().EntityDefinition().IsAssignableFrom(((IEdmEntityType)payloadType)))
                {
                    break;
                }
                IEdmTypeReference targetTypeReference = payloadType.ToTypeReference(true);
                serializationTypeNameAnnotation = CreateSerializationTypeNameAnnotation(payloadTypeName, targetTypeReference);
                return(targetTypeReference);
            }

            case EdmTypeKind.Complex:
                if ((payloadType != null) && (expectedTypeKind == payloadType.TypeKind))
                {
                    VerifyComplexType(expectedTypeReference, payloadType, false);
                }
                break;

            case EdmTypeKind.Collection:
                if ((payloadType != null) && (expectedTypeKind == payloadType.TypeKind))
                {
                    VerifyCollectionComplexItemType(expectedTypeReference, payloadType);
                }
                break;

            default:
                throw new ODataException(Microsoft.Data.OData.Strings.General_InternalError(InternalErrorCodes.ReaderValidationUtils_ResolveAndValidateTypeName_Strict_TypeKind));
            }
            serializationTypeNameAnnotation = CreateSerializationTypeNameAnnotation(payloadTypeName, expectedTypeReference);
            return(expectedTypeReference);
        }
Beispiel #14
0
        private static IEdmTypeReference ResolveAndValidateTargetTypeStrictValidationEnabled(EdmTypeKind expectedTypeKind, IEdmTypeReference expectedTypeReference, IEdmType payloadType, string payloadTypeName, out SerializationTypeNameAnnotation serializationTypeNameAnnotation)
        {
            switch (expectedTypeKind)
            {
                case EdmTypeKind.Entity:
                {
                    if (payloadType == null)
                    {
                        break;
                    }
                    IEdmTypeReference targetTypeReference = payloadType.ToTypeReference(true);
                    ValidationUtils.ValidateEntityTypeIsAssignable((IEdmEntityTypeReference) expectedTypeReference, (IEdmEntityTypeReference) targetTypeReference);
                    serializationTypeNameAnnotation = CreateSerializationTypeNameAnnotation(payloadTypeName, targetTypeReference);
                    return targetTypeReference;
                }
                case EdmTypeKind.Complex:
                    if (payloadType != null)
                    {
                        VerifyComplexType(expectedTypeReference, payloadType, true);
                    }
                    break;

                case EdmTypeKind.Collection:
                    if ((payloadType != null) && (string.CompareOrdinal(payloadType.ODataFullName(), expectedTypeReference.ODataFullName()) != 0))
                    {
                        VerifyCollectionComplexItemType(expectedTypeReference, payloadType);
                        throw new ODataException(Microsoft.Data.OData.Strings.ValidationUtils_IncompatibleType(payloadType.ODataFullName(), expectedTypeReference.ODataFullName()));
                    }
                    break;

                default:
                    throw new ODataException(Microsoft.Data.OData.Strings.General_InternalError(InternalErrorCodes.ReaderValidationUtils_ResolveAndValidateTypeName_Strict_TypeKind));
            }
            serializationTypeNameAnnotation = CreateSerializationTypeNameAnnotation(payloadTypeName, expectedTypeReference);
            return expectedTypeReference;
        }
Beispiel #15
0
        private static IEdmTypeReference ResolveAndValidateTargetTypeStrictValidationDisabled(EdmTypeKind expectedTypeKind, IEdmTypeReference expectedTypeReference, IEdmType payloadType, string payloadTypeName, out SerializationTypeNameAnnotation serializationTypeNameAnnotation)
        {
            switch (expectedTypeKind)
            {
                case EdmTypeKind.Entity:
                {
                    if (((payloadType == null) || (expectedTypeKind != payloadType.TypeKind)) || !expectedTypeReference.AsEntity().EntityDefinition().IsAssignableFrom(((IEdmEntityType) payloadType)))
                    {
                        break;
                    }
                    IEdmTypeReference targetTypeReference = payloadType.ToTypeReference(true);
                    serializationTypeNameAnnotation = CreateSerializationTypeNameAnnotation(payloadTypeName, targetTypeReference);
                    return targetTypeReference;
                }
                case EdmTypeKind.Complex:
                    if ((payloadType != null) && (expectedTypeKind == payloadType.TypeKind))
                    {
                        VerifyComplexType(expectedTypeReference, payloadType, false);
                    }
                    break;

                case EdmTypeKind.Collection:
                    if ((payloadType != null) && (expectedTypeKind == payloadType.TypeKind))
                    {
                        VerifyCollectionComplexItemType(expectedTypeReference, payloadType);
                    }
                    break;

                default:
                    throw new ODataException(Microsoft.Data.OData.Strings.General_InternalError(InternalErrorCodes.ReaderValidationUtils_ResolveAndValidateTypeName_Strict_TypeKind));
            }
            serializationTypeNameAnnotation = CreateSerializationTypeNameAnnotation(payloadTypeName, expectedTypeReference);
            return expectedTypeReference;
        }
        /// <summary>
        /// Read a collection from the reader.
        /// </summary>
        /// <param name="collectionTypeReference">The type of the collection to read (or null if no type is available).</param>
        /// <param name="payloadTypeName">The name of the collection type specified in the payload.</param>
        /// <param name="serializationTypeNameAnnotation">The serialization type name for the collection value (possibly null).</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.Element    - the element was empty.
        ///                  XmlNodeType.EndElement - the element had some value.
        ///                  
        /// Note that this method will not read null values, those should be handled by the caller already.
        /// </remarks>
        private ODataCollectionValue ReadCollectionValue(
            IEdmCollectionTypeReference collectionTypeReference, 
            string payloadTypeName,
            SerializationTypeNameAnnotation serializationTypeNameAnnotation)
        {
            this.AssertXmlCondition(XmlNodeType.Element, XmlNodeType.Attribute);
            Debug.Assert(
                collectionTypeReference == null || collectionTypeReference.IsNonEntityODataCollectionTypeKind(),
                "If the metadata is specified it must denote a collection for this method to work.");

            this.IncreaseRecursionDepth();

            ODataCollectionValue collectionValue = new ODataCollectionValue();

            // If we have a metadata type for the collection, use that type name
            // otherwise use the type name from the payload (if there was any).
            collectionValue.TypeName = collectionTypeReference == null ? payloadTypeName : collectionTypeReference.ODataFullName();
            if (serializationTypeNameAnnotation != null)
            {
                collectionValue.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();

            List<object> items = new List<object>();

            // Empty collections are valid - they have no items
            if (!this.XmlReader.IsEmptyElement)
            {
                // Read over the collection element to its first child node (or end-element)
                this.XmlReader.ReadStartElement();

                IEdmTypeReference itemTypeReference = collectionTypeReference == null ? null : collectionTypeReference.ElementType();

                DuplicatePropertyNamesChecker duplicatePropertyNamesChecker = this.CreateDuplicatePropertyNamesChecker();
                CollectionWithoutExpectedTypeValidator collectionValidator = null;
                if (collectionTypeReference == null)
                {
                    // Parse the type name from the payload (if any), extract the item type name and construct a collection validator
                    string itemTypeName = payloadTypeName == null ? null : EdmLibraryExtensions.GetCollectionItemTypeName(payloadTypeName);
                    collectionValidator = new CollectionWithoutExpectedTypeValidator(itemTypeName);
                }

                do
                {
                    switch (this.XmlReader.NodeType)
                    {
                        case XmlNodeType.Element:
                            if (this.XmlReader.NamespaceEquals(this.XmlReader.ODataNamespace))
                            {
                                if (!this.XmlReader.LocalNameEquals(this.ODataCollectionItemElementName))
                                {
                                    throw new ODataException(o.Strings.ODataAtomPropertyAndValueDeserializer_InvalidCollectionElement(this.XmlReader.LocalName, this.XmlReader.ODataNamespace));
                                }

                                // We don't support EPM for collections so it is fine to say that EPM is not present
                                object itemValue = this.ReadNonEntityValueImplementation(
                                    itemTypeReference, 
                                    duplicatePropertyNamesChecker, 
                                    collectionValidator,
                                    /*validateNullValue*/ true,
                                    /*epmPresent*/ false);

                                // read over the end tag of the element or the start tag if the element was empty.
                                this.XmlReader.Read();

                                // Validate the item (for example that it's not null)
                                ValidationUtils.ValidateCollectionItem(itemValue, false /* isStreamable */);

                                // Note that the ReadNonEntityValue already validated that the actual type of the value matches
                                // the expected type (the itemType).
                                items.Add(itemValue);
                            }
                            else
                            {
                                this.XmlReader.Skip();
                            }

                            break;

                        case XmlNodeType.EndElement:
                            // End of the collection.
                            break;

                        default:
                            // Non-element so for example a text node, just ignore
                            this.XmlReader.Skip();
                            break;
                    }
                }
                while (this.XmlReader.NodeType != XmlNodeType.EndElement);
            }

            collectionValue.Items = new ReadOnlyEnumerable(items);

            this.AssertXmlCondition(true, XmlNodeType.EndElement);
            Debug.Assert(collectionValue != null, "The method should never return null since it doesn't handle null values.");

            this.DecreaseRecursionDepth();

            return collectionValue;
        }
        /// <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;
        }
        /// <summary>
        /// Reads the primitive, complex or collection value.
        /// </summary>
        /// <param name="expectedTypeReference">The expected type reference of the value.</param>
        /// <param name="duplicatePropertyNamesChecker">The duplicate property names checker to use (cached), or null if new one should be created.</param>
        /// <param name="collectionValidator">The collection validator instance if no expected item type has been specified; otherwise null.</param>
        /// <param name="validateNullValue">true to validate a null value; otherwise false.</param>
        /// <param name="epmPresent">Whether any EPM mappings exist.</param>
        /// <returns>The value read (null, primitive CLR value, ODataComplexValue or ODataCollectionValue).</returns>
        /// <remarks>
        /// Pre-Condition:   XmlNodeType.Element    - The XML element containing the value to read (also the attributes will be read from it)
        /// Post-Condition:  XmlNodeType.EndElement - The end tag of the element.
        ///                  XmlNodeType.Element    - The empty element node.
        /// </remarks>
        private object ReadNonEntityValueImplementation(
            IEdmTypeReference expectedTypeReference, 
            DuplicatePropertyNamesChecker duplicatePropertyNamesChecker, 
            CollectionWithoutExpectedTypeValidator collectionValidator,
            bool validateNullValue,
            bool epmPresent)
        {
            this.AssertXmlCondition(XmlNodeType.Element);
            Debug.Assert(
                expectedTypeReference == null || !expectedTypeReference.IsODataEntityTypeKind(),
                "Only primitive, complex or collection types can be read by this method.");
            Debug.Assert(
                expectedTypeReference == null || collectionValidator == null,
                "If an expected value type reference is specified, no collection validator must be provided.");
            this.XmlReader.AssertNotBuffering();

            // Read the attributes looking for m:type and m:null
            string payloadTypeName;
            bool isNull;
            this.ReadNonEntityValueAttributes(out payloadTypeName, out isNull);

            object result;
            if (isNull)
            {
                result = this.ReadNullValue(expectedTypeReference, validateNullValue);
            }
            else
            {
                // If we could derive the item type name from the collection's type name and no type name was specified in the payload
                // fill it in now.
                EdmTypeKind payloadTypeKind;
                bool derivedItemTypeNameFromCollectionTypeName = false;
                if (collectionValidator != null && payloadTypeName == null)
                {
                    payloadTypeName = collectionValidator.ItemTypeNameFromCollection;
                    payloadTypeKind = collectionValidator.ItemTypeKindFromCollection;
                    derivedItemTypeNameFromCollectionTypeName = payloadTypeKind != EdmTypeKind.None;
                }

                // Resolve the payload type name and compute the target type kind and target type reference.
                SerializationTypeNameAnnotation serializationTypeNameAnnotation;
                EdmTypeKind targetTypeKind;
                IEdmTypeReference targetTypeReference = ReaderValidationUtils.ResolvePayloadTypeNameAndComputeTargetType(
                    EdmTypeKind.None,
                    /*defaultPrimitivePayloadType*/ edmStringType,
                    expectedTypeReference,
                    payloadTypeName,
                    this.Model,
                    this.MessageReaderSettings,
                    this.Version,
                    this.GetNonEntityValueKind,
                    out targetTypeKind,
                    out serializationTypeNameAnnotation);

                if (derivedItemTypeNameFromCollectionTypeName)
                {
                    Debug.Assert(
                        serializationTypeNameAnnotation == null,
                        "If we derived the item type name from the collection type name we must not have created a serialization type name annotation.");
                    serializationTypeNameAnnotation = new SerializationTypeNameAnnotation { TypeName = null };
                }

                // If we have no expected type make sure the collection items are of the same kind and specify the same name.
                if (collectionValidator != null)
                {
                    Debug.Assert(expectedTypeReference == null, "If a collection validator is specified there must not be an expected value type reference.");
                    collectionValidator.ValidateCollectionItem(payloadTypeName, targetTypeKind);
                }

                switch (targetTypeKind)
                {
                    case EdmTypeKind.Primitive:
                        Debug.Assert(targetTypeReference != null && targetTypeReference.IsODataPrimitiveTypeKind(), "Expected an OData primitive type.");
                        result = this.ReadPrimitiveValue(targetTypeReference.AsPrimitive());
                        break;

                    case EdmTypeKind.Complex:
                        Debug.Assert(targetTypeReference == null || targetTypeReference.IsComplex(), "Expected a complex type.");
                        result = this.ReadComplexValue(
                            targetTypeReference == null ? null : targetTypeReference.AsComplex(),
                            payloadTypeName,
                            serializationTypeNameAnnotation,
                            duplicatePropertyNamesChecker,
                            epmPresent);
                        break;

                    case EdmTypeKind.Collection:
                        IEdmCollectionTypeReference collectionTypeReference = ValidationUtils.ValidateCollectionType(targetTypeReference);
                        result = this.ReadCollectionValue(
                            collectionTypeReference, 
                            payloadTypeName,
                            serializationTypeNameAnnotation);
                        break;

                    default:
                        throw new ODataException(o.Strings.General_InternalError(InternalErrorCodes.ODataAtomPropertyAndValueDeserializer_ReadNonEntityValue));
                }
            }

            this.AssertXmlCondition(true, XmlNodeType.EndElement);
            this.XmlReader.AssertNotBuffering();
            return result;
        }
        private static IEdmTypeReference ResolveAndValidateTargetTypeStrictValidationEnabled(EdmTypeKind expectedTypeKind, IEdmTypeReference expectedTypeReference, IEdmType payloadType, string payloadTypeName, out SerializationTypeNameAnnotation serializationTypeNameAnnotation)
        {
            switch (expectedTypeKind)
            {
            case EdmTypeKind.Entity:
            {
                if (payloadType == null)
                {
                    break;
                }
                IEdmTypeReference targetTypeReference = payloadType.ToTypeReference(true);
                ValidationUtils.ValidateEntityTypeIsAssignable((IEdmEntityTypeReference)expectedTypeReference, (IEdmEntityTypeReference)targetTypeReference);
                serializationTypeNameAnnotation = CreateSerializationTypeNameAnnotation(payloadTypeName, targetTypeReference);
                return(targetTypeReference);
            }

            case EdmTypeKind.Complex:
                if (payloadType != null)
                {
                    VerifyComplexType(expectedTypeReference, payloadType, true);
                }
                break;

            case EdmTypeKind.Collection:
                if ((payloadType != null) && (string.CompareOrdinal(payloadType.ODataFullName(), expectedTypeReference.ODataFullName()) != 0))
                {
                    VerifyCollectionComplexItemType(expectedTypeReference, payloadType);
                    throw new ODataException(Microsoft.Data.OData.Strings.ValidationUtils_IncompatibleType(payloadType.ODataFullName(), expectedTypeReference.ODataFullName()));
                }
                break;

            default:
                throw new ODataException(Microsoft.Data.OData.Strings.General_InternalError(InternalErrorCodes.ReaderValidationUtils_ResolveAndValidateTypeName_Strict_TypeKind));
            }
            serializationTypeNameAnnotation = CreateSerializationTypeNameAnnotation(payloadTypeName, expectedTypeReference);
            return(expectedTypeReference);
        }
        /// <summary>
        /// Resolves and validates the payload type against the expected type and returns the target type.
        /// </summary>
        /// <param name="expectedTypeKind">The expected type kind for the value.</param>
        /// <param name="defaultPrimitivePayloadType">The default payload type if none is specified in the payload;
        /// for ATOM this is Edm.String, for JSON it is null since there is no payload type name for primitive types in the payload.</param>
        /// <param name="expectedTypeReference">The expected type reference, or null if no expected type is available.</param>
        /// <param name="payloadTypeName">The payload type name, or null if no payload type was specified.</param>
        /// <param name="model">The model to use.</param>
        /// <param name="messageReaderSettings">The message reader settings to use.</param>
        /// <param name="version">The version of the payload being read.</param>
        /// <param name="typeKindFromPayloadFunc">A func to compute the type kind from the payload shape if it could not be determined from the expected type or the payload type.</param>
        /// <param name="targetTypeKind">The target type kind to be used to read the payload.</param>
        /// <param name="serializationTypeNameAnnotation">Potentially non-null instance of an annotation to put on the value reported from the reader.</param>
        /// <returns>
        /// The target type reference to use for parsing the value.
        /// If there is no user specified model, this will return null.
        /// If there is a user specified model, this method never returns null.
        /// </returns>
        /// <remarks>
        /// This method cannot be used for primitive type resolution. Primitive type resolution is format dependent and format specific methods should be used instead.
        /// </remarks>
        internal static IEdmTypeReference ResolvePayloadTypeNameAndComputeTargetType(
            EdmTypeKind expectedTypeKind,
            IEdmType defaultPrimitivePayloadType,
            IEdmTypeReference expectedTypeReference,
            string payloadTypeName,
            IEdmModel model,
            ODataMessageReaderSettings messageReaderSettings,
            ODataVersion version,
            Func<EdmTypeKind> typeKindFromPayloadFunc,
            out EdmTypeKind targetTypeKind,
            out SerializationTypeNameAnnotation serializationTypeNameAnnotation)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(typeKindFromPayloadFunc != null, "typeKindFromPayloadFunc != null");

            serializationTypeNameAnnotation = null;

            // Resolve the type name and get the payload type kind; that is the type kind of the payload
            // type if available or the expected type kind if no payload type could be resolved. Since
            // we always detect primitive and collection types the expected type for unrecognized payload
            // types is EdmTypeKind.Complex.
            EdmTypeKind payloadTypeKind;
            IEdmType payloadType = ResolvePayloadTypeName(
                model,
                expectedTypeReference,
                payloadTypeName,
                EdmTypeKind.Complex,
                messageReaderSettings.ReaderBehavior,
                version,
                out payloadTypeKind);

            // Compute the target type kind based on the expected type, the payload type kind
            // and a function to detect the target type kind from the shape of the payload.
            targetTypeKind = ComputeTargetTypeKind(
                expectedTypeReference, 
                /*forEntityValue*/ expectedTypeKind == EdmTypeKind.Entity,
                payloadTypeName, 
                payloadTypeKind, 
                messageReaderSettings, 
                typeKindFromPayloadFunc);

            // Resolve potential conflicts between payload and expected types and apply all the various behavior changing flags from settings
            IEdmTypeReference targetTypeReference;
            if (targetTypeKind == EdmTypeKind.Primitive)
            {
                targetTypeReference = ReaderValidationUtils.ResolveAndValidatePrimitiveTargetType(
                    expectedTypeReference,
                    payloadTypeKind,
                    payloadType,
                    payloadTypeName,
                    defaultPrimitivePayloadType,
                    model,
                    messageReaderSettings,
                    version);
            }
            else
            {
                targetTypeReference = ReaderValidationUtils.ResolveAndValidateNonPrimitiveTargetType(
                    targetTypeKind,
                    expectedTypeReference,
                    payloadTypeKind,
                    payloadType,
                    payloadTypeName,
                    model,
                    messageReaderSettings,
                    version,
                    out serializationTypeNameAnnotation);
            }

            if (expectedTypeKind != EdmTypeKind.None && targetTypeReference != null)
            {
                ValidationUtils.ValidateTypeKind(targetTypeKind, expectedTypeKind, payloadTypeName);
            }

            return targetTypeReference;
        }
        internal static IEdmTypeReference ResolvePayloadTypeNameAndComputeTargetType(EdmTypeKind expectedTypeKind, IEdmType defaultPrimitivePayloadType, IEdmTypeReference expectedTypeReference, string payloadTypeName, IEdmModel model, ODataMessageReaderSettings messageReaderSettings, ODataVersion version, Func <EdmTypeKind> typeKindFromPayloadFunc, out EdmTypeKind targetTypeKind, out SerializationTypeNameAnnotation serializationTypeNameAnnotation)
        {
            EdmTypeKind       kind;
            IEdmTypeReference reference;

            serializationTypeNameAnnotation = null;
            IEdmType payloadType = ResolvePayloadTypeName(model, expectedTypeReference, payloadTypeName, EdmTypeKind.Complex, messageReaderSettings.ReaderBehavior, version, out kind);

            targetTypeKind = ComputeTargetTypeKind(expectedTypeReference, expectedTypeKind == EdmTypeKind.Entity, payloadTypeName, kind, messageReaderSettings, typeKindFromPayloadFunc);
            if (targetTypeKind == EdmTypeKind.Primitive)
            {
                reference = ResolveAndValidatePrimitiveTargetType(expectedTypeReference, kind, payloadType, payloadTypeName, defaultPrimitivePayloadType, model, messageReaderSettings, version);
            }
            else
            {
                reference = ResolveAndValidateNonPrimitiveTargetType(targetTypeKind, expectedTypeReference, kind, payloadType, payloadTypeName, model, messageReaderSettings, version, out serializationTypeNameAnnotation);
            }
            if ((expectedTypeKind != EdmTypeKind.None) && (reference != null))
            {
                ValidationUtils.ValidateTypeKind(targetTypeKind, expectedTypeKind, payloadTypeName);
            }
            return(reference);
        }
        /// <summary>
        /// Resolves the payload type versus the expected type and validates that such combination is allowed.
        /// </summary>
        /// <param name="expectedTypeKind">The expected type kind for the value.</param>
        /// <param name="expectedTypeReference">The expected type reference, or null if no expected type is available.</param>
        /// <param name="payloadTypeKind">The payload type kind, this may be the one from the type itself, or one detected without resolving the type.</param>
        /// <param name="payloadType">The payload type, or null if the payload type was not specified, or it didn't resolve against the model.</param>
        /// <param name="payloadTypeName">The payload type name, or null if no payload type was specified.</param>
        /// <param name="model">The model to use.</param>
        /// <param name="messageReaderSettings">The message reader settings to use.</param>
        /// <param name="version">The version of the payload being read.</param>
        /// <param name="serializationTypeNameAnnotation">Potentially non-null instance of an annotation to put on the value reported from the reader.</param>
        /// <returns>
        /// The target type reference to use for parsing the value.
        /// If there is no user specified model, this will return null.
        /// If there is a user specified model, this method never returns null.
        /// </returns>
        /// <remarks>
        /// This method cannot be used for primitive type resolution. Primitive type resolution is format dependent and format specific methods should be used instead.
        /// </remarks>
        internal static IEdmTypeReference ResolveAndValidateNonPrimitiveTargetType(
            EdmTypeKind expectedTypeKind,
            IEdmTypeReference expectedTypeReference,
            EdmTypeKind payloadTypeKind,
            IEdmType payloadType,
            string payloadTypeName,
            IEdmModel model,
            ODataMessageReaderSettings messageReaderSettings,
            ODataVersion version,
            out SerializationTypeNameAnnotation serializationTypeNameAnnotation)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(messageReaderSettings != null, "messageReaderSettings != null");
            Debug.Assert(
                expectedTypeKind == EdmTypeKind.Complex || expectedTypeKind == EdmTypeKind.Entity ||
                expectedTypeKind == EdmTypeKind.Collection,
                "The expected type kind must be one of Complex, Entity or Collection.");
            Debug.Assert(
                payloadTypeKind == EdmTypeKind.Complex || payloadTypeKind == EdmTypeKind.Entity ||
                payloadTypeKind == EdmTypeKind.Collection || payloadTypeKind == EdmTypeKind.None ||
                payloadTypeKind == EdmTypeKind.Primitive,
                "The payload type kind must be one of None, Primitive, Complex, Entity or Collection.");
            Debug.Assert(
                expectedTypeReference == null || expectedTypeReference.TypeKind() == expectedTypeKind,
                "The expected type kind must match the expected type reference if that is available.");
            Debug.Assert(
                payloadType == null || payloadType.TypeKind == payloadTypeKind,
                "The payload type kind must match the payload type if that is available.");
            Debug.Assert(payloadType == null || payloadTypeName != null, "If we have a payload type, we must have its name as well.");

            bool useExpectedTypeOnlyForTypeResolution = messageReaderSettings.ReaderBehavior.TypeResolver != null && payloadType != null;
            if (!useExpectedTypeOnlyForTypeResolution)
            {
                ValidateTypeSupported(expectedTypeReference, version);

                // We should validate that the payload type resolved before anything else to produce reasonable error messages
                // Otherwise we might report errors which are somewhat confusing (like "Type '' is Complex but Collection was expected.").
                if (model.IsUserModel() && (expectedTypeReference == null || !messageReaderSettings.DisableStrictMetadataValidation))
                {
                    // When using a type resolver (i.e., useExpectedTypeOnlyForTypeResolution == true) then we don't have to
                    // call this method because the contract with the type resolver is to always resolve the type name and thus
                    // we will always get a defined type.
                    VerifyPayloadTypeDefined(payloadTypeName, payloadType);
                }
            }
            else
            {
                // Payload types are always nullable.
                ValidateTypeSupported(payloadType == null ? null : payloadType.ToTypeReference(/*nullable*/ true), version);
            }

            if (payloadTypeKind != EdmTypeKind.None && (!messageReaderSettings.DisableStrictMetadataValidation || expectedTypeReference == null))
            {
                // Make sure that the type kinds match.
                ValidationUtils.ValidateTypeKind(payloadTypeKind, expectedTypeKind, payloadTypeName);
            }

            serializationTypeNameAnnotation = null;

            if (!model.IsUserModel())
            {
                // If there's no model, it means we should not have the expected type either, and that there's no type to use,
                // no metadata validation to perform.
                Debug.Assert(expectedTypeReference == null, "If we don't have a model, we must not have expected type either.");
                return null;
            }

            if (expectedTypeReference == null || useExpectedTypeOnlyForTypeResolution)
            {
                return ResolveAndValidateTargetTypeWithNoExpectedType(
                    expectedTypeKind,
                    payloadType,
                    payloadTypeName,
                    out serializationTypeNameAnnotation);
            }

            if (messageReaderSettings.DisableStrictMetadataValidation)
            {
                return ResolveAndValidateTargetTypeStrictValidationDisabled(
                    expectedTypeKind,
                    expectedTypeReference,
                    payloadType,
                    payloadTypeName,
                    out serializationTypeNameAnnotation);
            }

            return ResolveAndValidateTargetTypeStrictValidationEnabled(
                expectedTypeKind,
                expectedTypeReference,
                payloadType,
                payloadTypeName,
                out serializationTypeNameAnnotation);
        }
Beispiel #23
0
 private ODataCollectionValue CreateODataCollection(Type collectionItemType, string propertyName, object value, List<object> visitedComplexTypeObjects)
 {
     PrimitiveType type;
     string edmType;
     Func<object, object> valueConverter = null;
     Func<object, ODataComplexValue> func2 = null;
     WebUtil.ValidateCollection(collectionItemType, value, propertyName);
     bool flag = PrimitiveType.TryGetPrimitiveType(collectionItemType, out type);
     ODataCollectionValue value2 = new ODataCollectionValue();
     IEnumerable enumerable = (IEnumerable) value;
     if (flag)
     {
         edmType = ClientConvert.GetEdmType(Nullable.GetUnderlyingType(collectionItemType) ?? collectionItemType);
         if (valueConverter == null)
         {
             valueConverter = delegate (object val) {
                 WebUtil.ValidateCollectionItem(val);
                 WebUtil.ValidatePrimitiveCollectionItem(val, propertyName, collectionItemType);
                 return GetPrimitiveValue(val, collectionItemType);
             };
         }
         value2.Items = Util.GetEnumerable<object>(enumerable, valueConverter);
     }
     else
     {
         edmType = this.requestInfo.ResolveNameFromType(collectionItemType);
         if (func2 == null)
         {
             func2 = delegate (object val) {
                 WebUtil.ValidateCollectionItem(val);
                 WebUtil.ValidateComplexCollectionItem(val, propertyName, collectionItemType);
                 return this.CreateODataComplexValue(collectionItemType, val, propertyName, true, visitedComplexTypeObjects);
             };
         }
         value2.Items = Util.GetEnumerable<ODataComplexValue>(enumerable, func2);
     }
     string str2 = (edmType == null) ? null : string.Format(CultureInfo.InvariantCulture, "Collection({0})", new object[] { edmType });
     SerializationTypeNameAnnotation annotation = new SerializationTypeNameAnnotation {
         TypeName = str2
     };
     value2.SetAnnotation<SerializationTypeNameAnnotation>(annotation);
     return value2;
 }
        /// <summary>
        /// Resolves the payload type if there's no expected type.
        /// </summary>
        /// <param name="expectedTypeKind">The expected type kind for the value.</param>
        /// <param name="payloadType">The payload type, or null if the payload type was not specified, or it didn't resolve against the model.</param>
        /// <param name="payloadTypeName">The payload type name, or null if no payload type was specified.</param>
        /// <param name="serializationTypeNameAnnotation">Potentially non-null instance of an annotation to put on the value reported from the reader.</param>
        /// <returns>The target type reference to use for parsing the value.</returns>
        private static IEdmTypeReference ResolveAndValidateTargetTypeWithNoExpectedType(
            EdmTypeKind expectedTypeKind,
            IEdmType payloadType,
            string payloadTypeName,
            out SerializationTypeNameAnnotation serializationTypeNameAnnotation)
        {
            Debug.Assert(payloadTypeName == null || payloadType != null, "The payload type must have resolved before we get here.");
            serializationTypeNameAnnotation = null;

            // No expected type (for example an open property, but other scenarios are possible)
            // We need some type to go on. We do have a model, so we must perform metadata validation and for that we need a type.
            if (payloadType == null)
            {
                if (expectedTypeKind == EdmTypeKind.Entity)
                {
                    throw new ODataException(Strings.ReaderValidationUtils_EntryWithoutType);
                }

                throw new ODataException(Strings.ReaderValidationUtils_ValueWithoutType);
            }

            // Payload types are always nullable.
            IEdmTypeReference payloadTypeReference = payloadType.ToTypeReference(/*nullable*/ true);
            serializationTypeNameAnnotation = CreateSerializationTypeNameAnnotation(payloadTypeName, payloadTypeReference);

            // Use the payload type (since we don't have any other).
            return payloadTypeReference;
        }
Beispiel #25
0
 internal void WriteEntry(EntityDescriptor entityDescriptor, IEnumerable<LinkDescriptor> relatedLinks, ODataRequestMessageWrapper requestMessage)
 {
     ClientEdmModel model = ClientEdmModel.GetModel(this.requestInfo.MaxProtocolVersion);
     ClientTypeAnnotation clientTypeAnnotation = model.GetClientTypeAnnotation(model.GetOrCreateEdmType(entityDescriptor.Entity.GetType()));
     using (ODataMessageWriter writer = CreateMessageWriter(requestMessage, this.requestInfo))
     {
         ODataWriter odataWriter = writer.CreateODataEntryWriter();
         ODataEntry entry = new ODataEntry();
         if (this.requestInfo.HasWritingEventHandlers)
         {
             entry.SetAnnotation<WritingEntityInfo>(new WritingEntityInfo(entityDescriptor.Entity, this.requestInfo));
         }
         string serverTypeName = this.requestInfo.GetServerTypeName(entityDescriptor);
         if (clientTypeAnnotation.ElementTypeName != serverTypeName)
         {
             SerializationTypeNameAnnotation annotation = new SerializationTypeNameAnnotation {
                 TypeName = serverTypeName
             };
             entry.SetAnnotation<SerializationTypeNameAnnotation>(annotation);
         }
         entry.TypeName = clientTypeAnnotation.ElementTypeName;
         if (EntityStates.Modified == entityDescriptor.State)
         {
             entry.Id = entityDescriptor.GetLatestIdentity();
         }
         if (entityDescriptor.IsMediaLinkEntry || clientTypeAnnotation.IsMediaLinkEntry)
         {
             entry.MediaResource = new ODataStreamReferenceValue();
         }
         odataWriter.WriteStart(entry);
         if (EntityStates.Added == entityDescriptor.State)
         {
             this.WriteNavigationLink(entityDescriptor, relatedLinks, odataWriter);
         }
         entry.Properties = this.PopulateProperties(clientTypeAnnotation, entityDescriptor.Entity, null);
         odataWriter.WriteEnd();
     }
 }
        /// <summary>
        /// Resolves the payload type versus the expected type and validates that such combination is allowed when the strict validation is disabled.
        /// </summary>
        /// <param name="expectedTypeKind">The expected type kind for the value.</param>
        /// <param name="expectedTypeReference">The expected type reference, or null if no expected type is available.</param>
        /// <param name="payloadType">The payload type, or null if the payload type was not specified, or it didn't resolve against the model.</param>
        /// <param name="payloadTypeName">The payload type name, or null if no payload type was specified.</param>
        /// <param name="serializationTypeNameAnnotation">Potentially non-null instance of an annotation to put on the value reported from the reader.</param>
        /// <returns>The target type reference to use for parsing the value.</returns>
        private static IEdmTypeReference ResolveAndValidateTargetTypeStrictValidationDisabled(
            EdmTypeKind expectedTypeKind,
            IEdmTypeReference expectedTypeReference,
            IEdmType payloadType,
            string payloadTypeName,
            out SerializationTypeNameAnnotation serializationTypeNameAnnotation)
        {
            // Lax validation logic
            switch (expectedTypeKind)
            {
                case EdmTypeKind.Complex:
                    // if the expectedTypeKind is different from the payloadType.TypeKind the types are not related 
                    // in any way. In that case we will just use the expected type because we are in lax mode. 
                    if (payloadType != null && expectedTypeKind == payloadType.TypeKind)
                    {
                        // Just verify that it's not a derived complex type, in all other cases simply use the expected type.
                        VerifyComplexType(expectedTypeReference, payloadType, /* failIfNotRelated */ false);
                    }

                    break;
                case EdmTypeKind.Entity:
                    // if the expectedTypeKind is different from the payloadType.TypeKind the types are not related 
                    // in any way. In that case we will just use the expected type because we are in lax mode. 
                    if (payloadType != null && expectedTypeKind == payloadType.TypeKind)
                    {
                        // If the type is assignable (equal or derived) we will use the payload type, since we want to allow derived entities
                        if (EdmLibraryExtensions.IsAssignableFrom(expectedTypeReference.AsEntity().EntityDefinition(), (IEdmEntityType)payloadType))
                        {
                            IEdmTypeReference payloadTypeReference = payloadType.ToTypeReference(/*nullable*/ true);
                            serializationTypeNameAnnotation = CreateSerializationTypeNameAnnotation(payloadTypeName, payloadTypeReference);
                            return payloadTypeReference;
                        }
                    }

                    break;
                case EdmTypeKind.Collection:
                    // if the expectedTypeKind is different from the payloadType.TypeKind the types are not related 
                    // in any way. In that case we will just use the expected type because we are in lax mode. 
                    if (payloadType != null && expectedTypeKind == payloadType.TypeKind)
                    {
                        VerifyCollectionComplexItemType(expectedTypeReference, payloadType);
                    }

                    break;
                default:
                    throw new ODataException(Strings.General_InternalError(InternalErrorCodes.ReaderValidationUtils_ResolveAndValidateTypeName_Strict_TypeKind));
            }

            serializationTypeNameAnnotation = CreateSerializationTypeNameAnnotation(payloadTypeName, expectedTypeReference);

            // Either there's no payload type, in which case use the expected one, or the payload one and the expected one are equal.
            return expectedTypeReference;
        }
        /// <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(o.Strings.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)
                        {
                            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);

                            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;
        }
        /// <summary>
        /// Resolves the payload type versus the expected type and validates that such combination is allowed when strict validation is enabled.
        /// </summary>
        /// <param name="expectedTypeKind">The expected type kind for the value.</param>
        /// <param name="expectedTypeReference">The expected type reference, or null if no expected type is available.</param>
        /// <param name="payloadType">The payload type, or null if the payload type was not specified, or it didn't resolve against the model.</param>
        /// <param name="payloadTypeName">The payload type name, or null if no payload type was specified.</param>
        /// <param name="serializationTypeNameAnnotation">Potentially non-null instance of an annotation to put on the value reported from the reader.</param>
        /// <returns>The target type reference to use for parsing the value.</returns>
        private static IEdmTypeReference ResolveAndValidateTargetTypeStrictValidationEnabled(
            EdmTypeKind expectedTypeKind,
            IEdmTypeReference expectedTypeReference,
            IEdmType payloadType,
            string payloadTypeName,
            out SerializationTypeNameAnnotation serializationTypeNameAnnotation)
        {
            Debug.Assert(payloadTypeName == null || payloadType != null, "The payload type must have resolved before we get here.");

            // Strict validation logic
            switch (expectedTypeKind)
            {
                case EdmTypeKind.Complex:
                    if (payloadType != null)
                    {
                        VerifyComplexType(expectedTypeReference, payloadType, /* failIfNotRelated */ true);
                    }

                    break;
                case EdmTypeKind.Entity:
                    if (payloadType != null)
                    {
                        // The payload type must be assignable to the expected type.
                        IEdmTypeReference payloadTypeReference = payloadType.ToTypeReference(/*nullable*/ true);
                        ValidationUtils.ValidateEntityTypeIsAssignable((IEdmEntityTypeReference)expectedTypeReference, (IEdmEntityTypeReference)payloadTypeReference);
                        serializationTypeNameAnnotation = CreateSerializationTypeNameAnnotation(payloadTypeName, payloadTypeReference);

                        // Use the payload type
                        return payloadTypeReference;
                    }

                    break;
                case EdmTypeKind.Collection:
                    // The type must be exactly equal - note that we intentionally ignore nullability of the items here, since the payload type
                    // can't specify that.
                    if (payloadType != null && string.CompareOrdinal(payloadType.ODataFullName(), expectedTypeReference.ODataFullName()) != 0)
                    {
                        VerifyCollectionComplexItemType(expectedTypeReference, payloadType);

                        throw new ODataException(Strings.ValidationUtils_IncompatibleType(payloadType.ODataFullName(), expectedTypeReference.ODataFullName()));
                    }

                    break;
                default:
                    throw new ODataException(Strings.General_InternalError(InternalErrorCodes.ReaderValidationUtils_ResolveAndValidateTypeName_Strict_TypeKind));
            }

            serializationTypeNameAnnotation = CreateSerializationTypeNameAnnotation(payloadTypeName, expectedTypeReference);

            // Either there's no payload type, in which case use the expected one, or the payload one and the expected one are equal.
            return expectedTypeReference;
        }
 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;
 }
 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;
 }