예제 #1
0
 /// <summary>
 /// Writes the type name on the wire.
 /// </summary>
 /// <param name="propertyName">Name of the property.</param>
 /// <param name="typeNameToWrite">Type name of the property.</param>
 /// <param name="isTopLevel">true when writing a top-level property; false for nested properties.</param>
 private void WritePropertyTypeName(string propertyName, string typeNameToWrite, bool isTopLevel)
 {
     if (typeNameToWrite != null)
     {
         // We write the type name as an instance annotation (named "odata.type") for top-level properties, but as a property annotation (e.g., "*****@*****.**") if not top level.
         if (isTopLevel)
         {
             ODataJsonLightWriterUtils.WriteODataTypeInstanceAnnotation(this.JsonWriter, typeNameToWrite);
         }
         else
         {
             ODataJsonLightWriterUtils.WriteODataTypePropertyAnnotation(this.JsonWriter, propertyName, typeNameToWrite);
         }
     }
 }
        /// <summary>
        /// Writes the metadata properties for an entry which can only occur at the start.
        /// </summary>
        /// <param name="entryState">The entry state for which to write the metadata properties.</param>
        internal void WriteEntryStartMetadataProperties(IODataJsonLightWriterEntryState entryState)
        {
            Debug.Assert(entryState != null, "entryState != null");

            ODataEntry entry = entryState.Entry;

            // Write the "@odata.type": "typename"
            string typeName = this.JsonLightOutputContext.TypeNameOracle.GetEntryTypeNameForWriting(entryState.GetOrCreateTypeContext(this.Model, this.WritingResponse).ExpectedEntityTypeName, entry);

            if (typeName != null)
            {
                if (typeName.StartsWith("ODataAggregation.DynamicTypes."))
                {
                    ODataJsonLightWriterUtils.WriteODataIdAnnotation(this.JsonWriter, @"""""");
                }
                else
                {
                    ODataJsonLightWriterUtils.WriteODataTypeInstanceAnnotation(this.JsonWriter, typeName);
                }
            }

            // Write the "@odata.id": "Entity Id"
            Uri id;

            if (entry.MetadataBuilder.TryGetIdForSerialization(out id))
            {
                this.JsonWriter.WriteInstanceAnnotationName(ODataAnnotationNames.ODataId);
                if (id != null && !entry.HasNonComputedId)
                {
                    id = this.MetadataDocumentBaseUri.MakeRelativeUri(id);
                }

                this.JsonWriter.WriteValue(id == null ? null : this.UriToString(id));
            }

            // Write the "@odata.etag": "ETag value"
            string etag = entry.ETag;

            if (etag != null)
            {
                this.JsonWriter.WriteInstanceAnnotationName(ODataAnnotationNames.ODataETag);
                this.JsonWriter.WriteValue(etag);
            }
        }
예제 #3
0
        public void WriteCollectionValue(ODataCollectionValue collectionValue, IEdmTypeReference metadataTypeReference, bool isTopLevelProperty, bool isInUri, bool isOpenPropertyType)
        {
            Debug.Assert(collectionValue != null, "collectionValue != null");
            Debug.Assert(!isTopLevelProperty || !isInUri, "Cannot be a top level property and in a uri");

            this.IncreaseRecursionDepth();

            // If the CollectionValue has type information write out the metadata and the type in it.
            string typeName = collectionValue.TypeName;

            if (isTopLevelProperty)
            {
                Debug.Assert(metadataTypeReference == null, "Never expect a metadata type for top-level properties.");
                if (typeName == null)
                {
                    throw new ODataException(ODataErrorStrings.ODataJsonLightValueSerializer_MissingTypeNameOnCollection);
                }
            }
            else
            {
                // In requests, we allow the metadata type reference to be null if the type name is specified in the OM
                if (metadataTypeReference == null && !this.WritingResponse && typeName == null && this.Model.IsUserModel())
                {
                    throw new ODataException(ODataErrorStrings.ODataJsonLightPropertyAndValueSerializer_NoExpectedTypeOrTypeNameSpecifiedForCollectionValueInRequest);
                }
            }

            // resolve the type name to the type; if no type name is specified we will use the
            // type inferred from metadata
            IEdmCollectionTypeReference collectionTypeReference = (IEdmCollectionTypeReference)TypeNameOracle.ResolveAndValidateTypeNameForValue(this.Model, metadataTypeReference, collectionValue, isOpenPropertyType);

            typeName = this.JsonLightOutputContext.TypeNameOracle.GetValueTypeNameForWriting(collectionValue, metadataTypeReference, collectionTypeReference, isOpenPropertyType);
            bool useValueProperty = isInUri && !string.IsNullOrEmpty(typeName);

            if (useValueProperty)
            {
                // "{"
                this.JsonWriter.StartObjectScope();
                ODataJsonLightWriterUtils.WriteODataTypeInstanceAnnotation(this.JsonWriter, typeName);
                this.JsonWriter.WriteValuePropertyName();
            }

            // [
            // This represents the array of items in the CollectionValue
            this.JsonWriter.StartArrayScope();

            // Iterate through the CollectionValue items and write them out (treat null Items as an empty enumeration)
            IEnumerable items = collectionValue.Items;

            if (items != null)
            {
                IEdmTypeReference expectedItemTypeReference = collectionTypeReference == null ? null : collectionTypeReference.ElementType();

                DuplicatePropertyNamesChecker duplicatePropertyNamesChecker = null;
                foreach (object item in items)
                {
                    ValidationUtils.ValidateCollectionItem(item, expectedItemTypeReference.IsNullable());

                    ODataComplexValue itemAsComplexValue = item as ODataComplexValue;
                    if (itemAsComplexValue != null)
                    {
                        if (duplicatePropertyNamesChecker == null)
                        {
                            duplicatePropertyNamesChecker = this.CreateDuplicatePropertyNamesChecker();
                        }

                        this.WriteComplexValue(
                            itemAsComplexValue,
                            expectedItemTypeReference,
                            false /*isTopLevel*/,
                            false /*isOpenPropertyType*/,
                            duplicatePropertyNamesChecker);

                        duplicatePropertyNamesChecker.Clear();
                    }
                    else
                    {
                        Debug.Assert(!(item is ODataCollectionValue), "!(item is ODataCollectionValue)");
                        Debug.Assert(!(item is ODataStreamReferenceValue), "!(item is ODataStreamReferenceValue)");

                        // by design: collection element's type name is not written for enum or non-spatial primitive value even in case of full metadata.
                        // because enum and non-spatial primitive types don't have inheritance, the type of each element is the same as the item type of the collection, whose type name for spatial types in full metadata mode.
                        ODataEnumValue enumValue = item as ODataEnumValue;
                        if (enumValue != null)
                        {
                            this.WriteEnumValue(enumValue, expectedItemTypeReference);
                        }
                        else
                        {
                            if (item != null)
                            {
                                this.WritePrimitiveValue(item, expectedItemTypeReference);
                            }
                            else
                            {
                                this.WriteNullValue();
                            }
                        }
                    }
                }
            }

            // End the array scope which holds the items
            this.JsonWriter.EndArrayScope();

            if (useValueProperty)
            {
                this.JsonWriter.EndObjectScope();
            }

            this.DecreaseRecursionDepth();
        }
예제 #4
0
        public void WriteComplexValue(
            ODataComplexValue complexValue,
            IEdmTypeReference metadataTypeReference,
            bool isTopLevel,
            bool isOpenPropertyType,
            DuplicatePropertyNamesChecker duplicatePropertyNamesChecker)
        {
            Debug.Assert(complexValue != null, "complexValue != null");

            this.IncreaseRecursionDepth();

            // Start the object scope which will represent the entire complex instance;
            // for top-level complex properties we already wrote the object scope (and the context URI when needed).
            if (!isTopLevel)
            {
                this.JsonWriter.StartObjectScope();
            }

            string typeName = complexValue.TypeName;

            if (isTopLevel)
            {
                Debug.Assert(metadataTypeReference == null, "Never expect a metadata type for top-level properties.");
                if (typeName == null)
                {
                    throw new ODataException(ODataErrorStrings.ODataJsonLightValueSerializer_MissingTypeNameOnComplex);
                }
            }
            else
            {
                // In requests, we allow the property type reference to be null if the type name is specified in the OM
                if (metadataTypeReference == null && !this.WritingResponse && typeName == null && this.Model.IsUserModel())
                {
                    throw new ODataException(ODataErrorStrings.ODataJsonLightPropertyAndValueSerializer_NoExpectedTypeOrTypeNameSpecifiedForComplexValueRequest);
                }
            }

            // Resolve the type name to the type; if no type name is specified we will use the
            // type inferred from metadata.
            IEdmComplexTypeReference complexValueTypeReference = (IEdmComplexTypeReference)TypeNameOracle.ResolveAndValidateTypeNameForValue(this.Model, metadataTypeReference, complexValue, isOpenPropertyType);

            Debug.Assert(
                metadataTypeReference == null || complexValueTypeReference == null || EdmLibraryExtensions.IsAssignableFrom(metadataTypeReference, complexValueTypeReference),
                "Complex property types must be the same as or inherit from the ones from metadata (unless open).");

            typeName = this.JsonLightOutputContext.TypeNameOracle.GetValueTypeNameForWriting(complexValue, metadataTypeReference, complexValueTypeReference, isOpenPropertyType);
            if (typeName != null)
            {
                ODataJsonLightWriterUtils.WriteODataTypeInstanceAnnotation(this.JsonWriter, typeName);
            }

            // Write the properties of the complex value as usual. Note we do not allow complex types to contain named stream properties.
            this.PropertySerializer.WriteProperties(
                complexValueTypeReference == null ? null : complexValueTypeReference.ComplexDefinition(),
                complexValue.Properties,
                true /* isComplexValue */,
                duplicatePropertyNamesChecker,
                null /*projectedProperties */);

            // End the object scope which represents the complex instance;
            // for top-level complex properties we already wrote the end object scope.
            if (!isTopLevel)
            {
                this.JsonWriter.EndObjectScope();
            }

            this.DecreaseRecursionDepth();
        }