/// <summary>
        /// Read a service document.
        /// This method reads the service document from the input and returns
        /// an <see cref="ODataServiceDocument"/> that represents the read service document.
        /// </summary>
        /// <returns>A task which returns an <see cref="ODataServiceDocument"/> representing the read service document.</returns>
        /// <remarks>
        /// Pre-Condition:  JsonNodeType.None:        assumes that the JSON reader has not been used yet.
        /// Post-Condition: JsonNodeType.EndOfInput
        /// </remarks>
        internal Task <ODataServiceDocument> ReadServiceDocumentAsync()
        {
            Debug.Assert(this.JsonReader.NodeType == JsonNodeType.None, "Pre-Condition: expected JsonNodeType.None, the reader must not have been used yet.");
            this.JsonReader.AssertNotBuffering();

            // We use this to store annotations and check for duplicate annotation names, but we don't really store properties in it.
            PropertyAndAnnotationCollector propertyAndAnnotationCollector = this.CreatePropertyAndAnnotationCollector();

            // Position the reader on the first node
            return(this.ReadPayloadStartAsync(
                       ODataPayloadKind.ServiceDocument,
                       propertyAndAnnotationCollector,
                       /*isReadingNestedPayload*/ false,
                       /*allowEmptyPayload*/ false)

                   .FollowOnSuccessWith(t =>
            {
                ODataServiceDocument serviceDocument = this.ReadServiceDocumentImplementation(propertyAndAnnotationCollector);

                // Read the end of the response.
                this.ReadPayloadEnd(/*isReadingNestedPayload*/ false);

                Debug.Assert(this.JsonReader.NodeType == JsonNodeType.EndOfInput, "Post-Condition: expected JsonNodeType.EndOfInput");
                this.JsonReader.AssertNotBuffering();

                return serviceDocument;
            }));
        }
Beispiel #2
0
        public async Task ReadCollectionStartAsync_ThrowsExceptionForTopLevelPropertyAnnotationWithoutProperty()
        {
            var propertyAndAnnotationCollector = new PropertyAndAnnotationCollector(true);
            var expectedItemTypeReference      = EdmCoreModel.Instance.GetString(false);

            var payload = "{\"@odata.context\":\"http://tempuri.org/$metadata#Collection(Edm.String)\"," +
                          "\"[email protected]\":\"foobar\"}";

            var exception = await Assert.ThrowsAsync <ODataException>(
                () => SetupJsonLightCollectionDeserializerAndRunTestAsync(
                    payload,
                    async(jsonLightCollectionDeserializer) =>
            {
                await jsonLightCollectionDeserializer.ReadPayloadStartAsync(
                    ODataPayloadKind.Collection,
                    propertyAndAnnotationCollector,
                    isReadingNestedPayload: false,
                    allowEmptyPayload: false);

                var collectionStart = await jsonLightCollectionDeserializer.ReadCollectionStartAsync(
                    propertyAndAnnotationCollector,
                    isReadingNestedPayload: false,
                    expectedItemTypeReference: expectedItemTypeReference);
            }));

            Assert.Equal(
                ODataErrorStrings.ODataJsonLightPropertyAndValueDeserializer_TopLevelPropertyAnnotationWithoutProperty("value"),
                exception.Message);
        }
Beispiel #3
0
        public async Task ReadCollectionStartAsync_ThrowsExceptionForMetadataReferenceProperty()
        {
            var propertyAndAnnotationCollector = new PropertyAndAnnotationCollector(true);
            var expectedItemTypeReference      = EdmCoreModel.Instance.GetString(false);

            var payload = "{\"@odata.context\":\"http://tempuri.org/$metadata#Collection(Edm.String)\"," +
                          "\"#NS.Func\":{\"title\":\"Func\",\"target\":\"http://tempuri.org/Func\"}," +
                          "\"value\":[\"Tea\",\"Coffee\"]}";

            var exception = await Assert.ThrowsAsync <ODataException>(
                () => SetupJsonLightCollectionDeserializerAndRunTestAsync(
                    payload,
                    async(jsonLightCollectionDeserializer) =>
            {
                await jsonLightCollectionDeserializer.ReadPayloadStartAsync(
                    ODataPayloadKind.Collection,
                    propertyAndAnnotationCollector,
                    isReadingNestedPayload: false,
                    allowEmptyPayload: false);

                var collectionStart = await jsonLightCollectionDeserializer.ReadCollectionStartAsync(
                    propertyAndAnnotationCollector,
                    isReadingNestedPayload: false,
                    expectedItemTypeReference: expectedItemTypeReference);
            }));

            Assert.Equal(
                ODataErrorStrings.ODataJsonLightPropertyAndValueDeserializer_UnexpectedMetadataReferenceProperty("#NS.Func"),
                exception.Message);
        }
Beispiel #4
0
        /// <summary>
        /// Read a set of top-level entity reference links.
        /// </summary>
        /// <param name="propertyAndAnnotationCollector">The duplicate property names checker to use for the top-level scope.</param>
        /// <returns>An <see cref="ODataEntityReferenceLinks"/> representing the read links.</returns>
        private ODataEntityReferenceLinks ReadEntityReferenceLinksImplementation(PropertyAndAnnotationCollector propertyAndAnnotationCollector)
        {
            Debug.Assert(propertyAndAnnotationCollector != null, "propertyAndAnnotationCollector != null");

            ODataEntityReferenceLinks entityReferenceLinks = new ODataEntityReferenceLinks();

            this.ReadEntityReferenceLinksAnnotations(entityReferenceLinks, propertyAndAnnotationCollector, /*forLinksStart*/ true);

            // Read the start of the content array of the links
            this.JsonReader.ReadStartArray();

            List <ODataEntityReferenceLink> links = new List <ODataEntityReferenceLink>();
            PropertyAndAnnotationCollector  linkPropertyAndAnnotationCollector = this.JsonLightInputContext.CreatePropertyAndAnnotationCollector();

            while (this.JsonReader.NodeType != JsonNodeType.EndArray)
            {
                // read another link
                ODataEntityReferenceLink entityReferenceLink = this.ReadSingleEntityReferenceLink(linkPropertyAndAnnotationCollector, /*topLevel*/ false);
                links.Add(entityReferenceLink);
                linkPropertyAndAnnotationCollector.Reset();
            }

            this.JsonReader.ReadEndArray();

            this.ReadEntityReferenceLinksAnnotations(entityReferenceLinks, propertyAndAnnotationCollector, /*forLinksStart*/ false);

            this.JsonReader.ReadEndObject();

            entityReferenceLinks.Links = new ReadOnlyEnumerable <ODataEntityReferenceLink>(links);
            return(entityReferenceLinks);
        }
Beispiel #5
0
        /// <summary>
        /// Parses JSON object property starting with the current position of the JSON reader.
        /// </summary>
        /// <param name="propertyAndAnnotationCollector">The duplicate property names checker to use, it will also store the property annotations found.</param>
        /// <param name="readPropertyAnnotationValue">Function called to read property annotation value.</param>
        /// <param name="handleProperty">Function callback to handle the result of parsing property.</param>
        internal void ProcessProperty(
            PropertyAndAnnotationCollector propertyAndAnnotationCollector,
            Func <string, object> readPropertyAnnotationValue,
            Action <PropertyParsingResult, string> handleProperty)
        {
            Debug.Assert(propertyAndAnnotationCollector != null, "propertyAndAnnotationCollector != null");
            Debug.Assert(readPropertyAnnotationValue != null, "readPropertyAnnotationValue != null");
            Debug.Assert(handleProperty != null, "handleProperty != null");
            this.AssertJsonCondition(JsonNodeType.Property);

            string propertyName;
            PropertyParsingResult propertyParsingResult = this.ParseProperty(
                propertyAndAnnotationCollector, readPropertyAnnotationValue, out propertyName);

            while (propertyParsingResult == PropertyParsingResult.CustomInstanceAnnotation && this.ShouldSkipCustomInstanceAnnotation(propertyName))
            {
                // Read over the property name
                this.JsonReader.Read();

                // Skip over the instance annotation value and don't report it to the OM.
                this.JsonReader.SkipValue();
                propertyParsingResult = this.ParseProperty(
                    propertyAndAnnotationCollector, readPropertyAnnotationValue, out propertyName);
            }

            handleProperty(propertyParsingResult, propertyName);
            if (propertyParsingResult != PropertyParsingResult.EndOfObject &&
                propertyParsingResult != PropertyParsingResult.CustomInstanceAnnotation)
            {
                propertyAndAnnotationCollector.MarkPropertyAsProcessed(propertyName);
            }
        }
Beispiel #6
0
        /// <summary>
        /// Read a top-level error.
        /// </summary>
        /// <returns>A task which returns an <see cref="ODataError"/> representing the read error.</returns>
        /// <remarks>
        /// Pre-Condition:  JsonNodeType.None       - The reader must not have been used yet.
        /// Post-Condition: JsonNodeType.EndOfInput
        /// </remarks>
        internal Task <ODataError> ReadTopLevelErrorAsync()
        {
            Debug.Assert(this.JsonReader.NodeType == JsonNodeType.None, "Pre-Condition: expected JsonNodeType.None, the reader must not have been used yet.");
            Debug.Assert(!this.JsonReader.DisableInStreamErrorDetection, "!JsonReader.DisableInStreamErrorDetection");
            this.JsonReader.AssertNotBuffering();

            // prevent the buffering JSON reader from detecting in-stream errors - we read the error ourselves
            // to throw proper exceptions
            this.JsonReader.DisableInStreamErrorDetection = true;

            // We use this to store annotations and check for duplicate annotation names, but we don't really store properties in it.
            PropertyAndAnnotationCollector propertyAndAnnotationCollector = this.CreatePropertyAndAnnotationCollector();

            // Position the reader on the first node
            return(this.ReadPayloadStartAsync(
                       ODataPayloadKind.Error,
                       propertyAndAnnotationCollector,
                       /*isReadingNestedPayload*/ false,
                       /*allowEmptyPayload*/ false)

                   .FollowOnSuccessWith(t =>
            {
                ODataError result = this.ReadTopLevelErrorImplementation();

                Debug.Assert(this.JsonReader.NodeType == JsonNodeType.EndOfInput, "Post-Condition: JsonNodeType.EndOfInput");
                this.JsonReader.AssertNotBuffering();

                return result;
            })

                   .FollowAlwaysWith(t =>
            {
                this.JsonReader.DisableInStreamErrorDetection = false;
            }));
        }
Beispiel #7
0
        /// <summary>
        /// Read a set of top-level entity reference links.
        /// </summary>
        /// <returns>A task which returns an <see cref="ODataEntityReferenceLinks"/> representing the read links.</returns>
        internal async Task <ODataEntityReferenceLinks> ReadEntityReferenceLinksAsync()
        {
            Debug.Assert(this.JsonReader.NodeType == JsonNodeType.None, "Pre-Condition: expected JsonNodeType.None, the reader must not have been used yet.");
            this.JsonReader.AssertNotBuffering();

            // We use this to store annotations and check for duplicate annotation names, but we don't really store properties in it.
            PropertyAndAnnotationCollector propertyAndAnnotationCollector = this.CreatePropertyAndAnnotationCollector();

            await this.ReadPayloadStartAsync(
                ODataPayloadKind.EntityReferenceLinks,
                propertyAndAnnotationCollector,
                isReadingNestedPayload : false,
                allowEmptyPayload : false).ConfigureAwait(false);

            ODataEntityReferenceLinks entityReferenceLinks = await this.ReadEntityReferenceLinksImplementationAsync(
                propertyAndAnnotationCollector).ConfigureAwait(false);

            await this.ReadPayloadEndAsync(isReadingNestedPayload : false)
            .ConfigureAwait(false);

            Debug.Assert(this.JsonReader.NodeType == JsonNodeType.EndOfInput, "Post-Condition: expected JsonNodeType.EndOfInput");
            this.JsonReader.AssertNotBuffering();

            return(entityReferenceLinks);
        }
Beispiel #8
0
        public ODataJsonLightParameterDeserializerTests()
        {
            this.messageReaderSettings = new ODataMessageReaderSettings();

            this.InitializeModel();
            this.propertyAndAnnotationCollector = new PropertyAndAnnotationCollector(true);
        }
Beispiel #9
0
        /// <summary>
        /// Implementation of the collection reader logic when in state 'Start'.
        /// </summary>
        /// <param name="propertyAndAnnotationCollector">The duplicate property names checker for the top-level scope.</param>
        /// <returns>true if more items can be read from the reader; otherwise false.</returns>
        /// <remarks>
        /// Pre-Condition:  JsonNodeType.None:      assumes that the JSON reader has not been used yet when not reading a nested payload.
        /// Post-Condition: The reader is positioned on the first node of the first item or the EndArray node of an empty item array
        /// </remarks>
        private bool ReadAtStartImplementationSynchronously(PropertyAndAnnotationCollector propertyAndAnnotationCollector)
        {
            Debug.Assert(propertyAndAnnotationCollector != null, "propertyAndAnnotationCollector != null");

            IEdmTypeReference actualItemTypeReference;

            this.ExpectedItemTypeReference = ReaderValidationUtils.ValidateCollectionContextUriAndGetPayloadItemTypeReference(
                this.jsonLightCollectionDeserializer.ContextUriParseResult,
                this.ExpectedItemTypeReference);

            // read the start of the collection until we find the content array for top-level collections
            ODataCollectionStart collectionStart = this.jsonLightCollectionDeserializer.ReadCollectionStart(
                propertyAndAnnotationCollector,
                this.IsReadingNestedPayload,
                this.ExpectedItemTypeReference,
                out actualItemTypeReference);

            if (actualItemTypeReference != null)
            {
                this.ExpectedItemTypeReference = actualItemTypeReference;
            }

            this.jsonLightCollectionDeserializer.JsonReader.ReadStartArray();

            this.EnterScope(ODataCollectionReaderState.CollectionStart, collectionStart);

            return(true);
        }
Beispiel #10
0
        /// <summary>
        /// Asynchronous implementation of the collection reader logic when in state 'Start'.
        /// </summary>
        /// <param name="propertyAndAnnotationCollector">The duplicate property names checker for the top-level scope.</param>
        /// <returns>
        /// A task that represents the asynchronous read operation.
        /// The value of the TResult parameter contains true if more items can be read from the reader; otherwise false.
        /// </returns>
        /// <remarks>
        /// Pre-Condition:  JsonNodeType.None:      assumes that the JSON reader has not been used yet when not reading a nested payload.
        /// Post-Condition: The reader is positioned on the first node of the first item or the EndArray node of an empty item array
        /// </remarks>
        private async Task <bool> ReadAtStartImplementationAsynchronously(PropertyAndAnnotationCollector propertyAndAnnotationCollector)
        {
            Debug.Assert(propertyAndAnnotationCollector != null, "propertyAndAnnotationCollector != null");

            IEdmTypeReference actualItemTypeReference;

            this.ExpectedItemTypeReference = ReaderValidationUtils.ValidateCollectionContextUriAndGetPayloadItemTypeReference(
                this.jsonLightCollectionDeserializer.ContextUriParseResult,
                this.ExpectedItemTypeReference);

            // Read the start of the collection until we find the content array for top-level collections
            Tuple <ODataCollectionStart, IEdmTypeReference> readCollectionStartResult = await this.jsonLightCollectionDeserializer.ReadCollectionStartAsync(
                propertyAndAnnotationCollector,
                this.IsReadingNestedPayload,
                this.ExpectedItemTypeReference).ConfigureAwait(false);

            ODataCollectionStart collectionStart = readCollectionStartResult.Item1;

            actualItemTypeReference = readCollectionStartResult.Item2;

            if (actualItemTypeReference != null)
            {
                this.ExpectedItemTypeReference = actualItemTypeReference;
            }

            await this.jsonLightCollectionDeserializer.JsonReader.ReadStartArrayAsync()
            .ConfigureAwait(false);

            this.EnterScope(ODataCollectionReaderState.CollectionStart, collectionStart);

            return(true);
        }
Beispiel #11
0
        /// <summary>
        /// Read the start of the top-level data wrapper in JSON responses.
        /// </summary>
        /// <param name="payloadKind">The kind of payload we are reading; this guides the parsing of the context URI.</param>
        /// <param name="propertyAndAnnotationCollector">The duplicate property names checker.</param>
        /// <param name="isReadingNestedPayload">true if we are deserializing a nested payload, e.g. a resource, a resource set or a collection within a parameters payload.</param>
        /// <param name="allowEmptyPayload">true if we allow a completely empty payload; otherwise false.</param>
        /// <returns>The parsed context URI.</returns>
        /// <remarks>
        /// Pre-Condition:  JsonNodeType.None:      assumes that the JSON reader has not been used yet when not reading a nested payload.
        /// Post-Condition: The reader is positioned on the first property of the payload after having read (or skipped) the context URI property.
        ///                 Or the reader is positioned on an end-object node if there are no properties (other than the context URI which is required in responses and optional in requests).
        /// </remarks>
        internal Task ReadPayloadStartAsync(
            ODataPayloadKind payloadKind,
            PropertyAndAnnotationCollector propertyAndAnnotationCollector,
            bool isReadingNestedPayload,
            bool allowEmptyPayload)
        {
            this.JsonReader.AssertNotBuffering();
            Debug.Assert(isReadingNestedPayload || this.JsonReader.NodeType == JsonNodeType.None, "Pre-Condition: JSON reader must not have been used yet when not reading a nested payload.");

            return(TaskUtils.GetTaskForSynchronousOperation(() =>
            {
                string contextUriAnnotationValue = this.ReadPayloadStartImplementation(
                    payloadKind,
                    propertyAndAnnotationCollector,
                    isReadingNestedPayload,
                    allowEmptyPayload);

                // The context URI is only recognized in non-error response top-level payloads.
                // If the payload is nested (for example when we read URL literals) we don't recognize the context URI.
                // Top-level error payloads don't need and use the context URI.
                if (!isReadingNestedPayload && payloadKind != ODataPayloadKind.Error && contextUriAnnotationValue != null)
                {
                    this.contextUriParseResult = ODataJsonLightContextUriParser.Parse(
                        this.Model,
                        contextUriAnnotationValue,
                        payloadKind,
                        this.MessageReaderSettings.ClientCustomTypeResolver,
                        this.JsonLightInputContext.ReadingResponse);
                }

#if DEBUG
                this.contextUriParseResultReady = true;
#endif
            }));
        }
Beispiel #12
0
        /// <summary>
        /// Reads the odata.context annotation.
        /// </summary>
        /// <param name="payloadKind">The payload kind for which to read the context URI.</param>
        /// <param name="propertyAndAnnotationCollector">The duplicate property names checker.</param>
        /// <param name="failOnMissingContextUriAnnotation">true if the method should fail if the context URI annotation is missing, false if that can be ignored.</param>
        /// <returns>The value of the context URI annotation.</returns>
        internal string ReadContextUriAnnotation(
            ODataPayloadKind payloadKind,
            PropertyAndAnnotationCollector propertyAndAnnotationCollector,
            bool failOnMissingContextUriAnnotation)
        {
            if (this.JsonReader.NodeType != JsonNodeType.Property)
            {
                if (!failOnMissingContextUriAnnotation || payloadKind == ODataPayloadKind.Unsupported)
                {
                    // Do not fail during payload kind detection
                    return(null);
                }

                throw new ODataException(Strings.ODataJsonLightDeserializer_ContextLinkNotFoundAsFirstProperty);
            }

            // Must make sure the input odata.context has a '@' prefix
            string propertyName = this.JsonReader.GetPropertyName();

            if (string.CompareOrdinal(JsonLightConstants.ODataPropertyAnnotationSeparatorChar + ODataAnnotationNames.ODataContext, propertyName) != 0 &&
                !this.CompareSimplifiedODataAnnotation(JsonLightConstants.SimplifiedODataContextPropertyName, propertyName))
            {
                if (!failOnMissingContextUriAnnotation || payloadKind == ODataPayloadKind.Unsupported)
                {
                    // Do not fail during payload kind detection
                    return(null);
                }

                throw new ODataException(Strings.ODataJsonLightDeserializer_ContextLinkNotFoundAsFirstProperty);
            }

            // Read over the property name
            this.JsonReader.ReadNext();
            return(this.JsonReader.ReadStringValue());
        }
        public void OnlyCustomAnnotationsForPropertyAddedShouldReturnEmpty()
        {
            PropertyAndAnnotationCollector duplicateChecker = new PropertyAndAnnotationCollector(true);

            duplicateChecker.AddCustomPropertyAnnotation("property", "custom.annotation", "value");
            duplicateChecker.AddCustomPropertyAnnotation("property", "custom.annotation2", "value");
            duplicateChecker.GetODataPropertyAnnotations("property").Should().BeEmpty();
        }
        public void DuplicatePropertyCustomAnnotationShouldNotFail()
        {
            PropertyAndAnnotationCollector duplicateChecker = new PropertyAndAnnotationCollector(true);
            Action action = () => duplicateChecker.AddCustomPropertyAnnotation("property", "custom.name", "value");

            action.ShouldNotThrow();
            action.ShouldNotThrow();
        }
        public void DuplicatePropertyODataAnnotationShouldFail()
        {
            PropertyAndAnnotationCollector duplicateChecker = new PropertyAndAnnotationCollector(true);
            Action action = () => duplicateChecker.AddODataPropertyAnnotation("property", JsonLightConstants.ODataAnnotationNamespacePrefix + "name", "SomeValue");

            action.ShouldNotThrow();
            action.ShouldThrow <ODataException>().WithMessage(ErrorStrings.DuplicateAnnotationForPropertyNotAllowed(JsonLightConstants.ODataAnnotationNamespacePrefix + "name", "property"));
        }
        public void DuplicateInstanceODataAnnotationShouldFail()
        {
            PropertyAndAnnotationCollector duplicateChecker = new PropertyAndAnnotationCollector(true);
            Action action = () => duplicateChecker.MarkPropertyAsProcessed(JsonLightConstants.ODataAnnotationNamespacePrefix + "name");

            action.ShouldNotThrow();
            action.ShouldThrow <ODataException>().WithMessage(ErrorStrings.DuplicateAnnotationNotAllowed(JsonLightConstants.ODataAnnotationNamespacePrefix + "name"));
        }
        public void ReadInstanceAnnotationValueWillReadJsonNativeTypesWithoutODataType()
        {
            var deserializer = this.CreateJsonLightEntryAndFeedDeserializer("{\"@odata.Int32Annotation\":123}");

            AdvanceReaderToFirstPropertyValue(deserializer.JsonReader);
            var propertyAndAnnotationCollector = new PropertyAndAnnotationCollector(true);

            Assert.Equal(123, deserializer.ReadCustomInstanceAnnotationValue(propertyAndAnnotationCollector, "odata.Int32Annotation"));
        }
Beispiel #18
0
        public void ReadInstanceAnnotationValueWillReadNonJsonNativePrimitiveTypesWithoutODataTypeAsStringValue()
        {
            var deserializer = this.CreateJsonLightEntryAndFeedDeserializer("{\"@Custom.GuidAnnotation\":\"00000000-0000-0000-0000-000000000000\"}");

            AdvanceReaderToFirstPropertyValue(deserializer.JsonReader);
            var propertyAndAnnotationCollector = new PropertyAndAnnotationCollector(true);

            deserializer.ReadCustomInstanceAnnotationValue(propertyAndAnnotationCollector, "Custom.GuidAnnotation").Should().Be("00000000-0000-0000-0000-000000000000");
        }
Beispiel #19
0
        public void ReadInstanceAnnotationValueWillReadNullValueWithoutODataType()
        {
            var deserializer = this.CreateJsonLightEntryAndFeedDeserializer("{\"@odata.NullAnnotation\":null}");

            AdvanceReaderToFirstPropertyValue(deserializer.JsonReader);
            var propertyAndAnnotationCollector = new PropertyAndAnnotationCollector(true);

            deserializer.ReadCustomInstanceAnnotationValue(propertyAndAnnotationCollector, "odata.NullAnnotation").Should().BeNull();
        }
Beispiel #20
0
        public void ReadInstanceAnnotationValueWillReadAsCorrectTypePrimitiveTypesWithODataTypeAnnotation()
        {
            var deserializer = this.CreateJsonLightEntryAndFeedDeserializer("{\"@Custom.GuidAnnotation\":\"00000000-0000-0000-0000-000000000000\"}");

            AdvanceReaderToFirstPropertyValue(deserializer.JsonReader);
            var propertyAndAnnotationCollector = new PropertyAndAnnotationCollector(true);

            propertyAndAnnotationCollector.AddODataPropertyAnnotation("Custom.GuidAnnotation", "odata.type", "Edm.Guid");
            deserializer.ReadCustomInstanceAnnotationValue(propertyAndAnnotationCollector, "Custom.GuidAnnotation").Should().Be(Guid.Empty);
        }
Beispiel #21
0
        public void ReadEntryInstanceAnnotationShouldReadCustomInstanceAnnotationValue()
        {
            var deserializer = this.CreateJsonLightEntryAndFeedDeserializer("{\"@custom.Int32Annotation\":123}");

            AdvanceReaderToFirstPropertyValue(deserializer.JsonReader);
            var    propertyAndAnnotationCollector = new PropertyAndAnnotationCollector(true);
            object value = deserializer.ReadEntryInstanceAnnotation("custom.Int32Annotation", false /*anyPropertyFound*/, true /*typeAnnotationFound*/, propertyAndAnnotationCollector);

            Assert.Equal(123, value);
        }
        public void ReadInstanceAnnotationValueWillReadNullValueWithODataType()
        {
            var deserializer = this.CreateJsonLightEntryAndFeedDeserializer("{\"@odata.NullAnnotation\":null}");

            AdvanceReaderToFirstPropertyValue(deserializer.JsonReader);
            var propertyAndAnnotationCollector = new PropertyAndAnnotationCollector(true);

            propertyAndAnnotationCollector.AddODataPropertyAnnotation("odata.NullAnnotation", "odata.type", "Edm.Guid");
            Assert.Null(deserializer.ReadCustomInstanceAnnotationValue(propertyAndAnnotationCollector, "odata.NullAnnotation"));
        }
Beispiel #23
0
        /// <summary>
        /// Reads the end of a collection; this includes collection-level instance annotations.
        /// </summary>
        /// <param name="isReadingNestedPayload">true if we are reading a nested collection inside a paramter payload; otherwise false.</param>
        /// <remarks>
        /// Pre-Condition:  EndArray node:      End of the collection content array
        /// Post-Condition: EndOfInput:         All of the collection payload has been consumed.
        /// </remarks>
        internal void ReadCollectionEnd(bool isReadingNestedPayload)
        {
            Debug.Assert(this.JsonReader.NodeType == JsonNodeType.EndArray, "Pre-condition: JsonNodeType.EndArray");
            this.JsonReader.AssertNotBuffering();

            this.JsonReader.ReadEndArray();

            if (!isReadingNestedPayload)
            {
                // Create a new duplicate property names checker object here; we don't have to use the one from reading the
                // collection start since we don't allow any annotations/properties after the collection property.
                PropertyAndAnnotationCollector collectionEndPropertyAndAnnotationCollector = this.CreatePropertyAndAnnotationCollector();

                // Fail on anything after the collection that is not a custom instance annotation
                while (this.JsonReader.NodeType == JsonNodeType.Property)
                {
                    this.ProcessProperty(
                        collectionEndPropertyAndAnnotationCollector,
                        this.ReadTypePropertyAnnotationValue,
                        (propertyParsingResult, propertyName) =>
                    {
                        // This method will allow and skip over any custom annotations, but will not report them as enum values, so any result we get other than EndOfObject indicates a malformed payload.
                        switch (propertyParsingResult)
                        {
                        case PropertyParsingResult.CustomInstanceAnnotation:
                            this.JsonReader.SkipValue();
                            break;

                        case PropertyParsingResult.ODataInstanceAnnotation:
                            if (!IsValidODataAnnotationOfCollection(propertyName))
                            {
                                throw new ODataException(ODataErrorStrings.ODataJsonLightCollectionDeserializer_CannotReadCollectionEnd(propertyName));
                            }

                            this.JsonReader.SkipValue();
                            break;

                        case PropertyParsingResult.PropertyWithoutValue:                // fall through
                        case PropertyParsingResult.PropertyWithValue:                   // fall through
                        case PropertyParsingResult.MetadataReferenceProperty:
                            throw new ODataException(ODataErrorStrings.ODataJsonLightCollectionDeserializer_CannotReadCollectionEnd(propertyName));

                        case PropertyParsingResult.EndOfObject:
                            break;

                        default:
                            throw new ODataException(ODataErrorStrings.General_InternalError(InternalErrorCodes.ODataJsonLightCollectionDeserializer_ReadCollectionEnd));
                        }
                    });
                }

                // read the end-object node of the value containing the 'value' property
                this.JsonReader.ReadEndObject();
            }
        }
Beispiel #24
0
        public void ReadInstanceAnnotationValueWhenODataTypeAnnotationIsMissingForCollectionValue()
        {
            var deserializer = this.CreateJsonLightEntryAndFeedDeserializer("{\"@OData.CollectionAnnotation\":[]}");

            AdvanceReaderToFirstPropertyValue(deserializer.JsonReader);
            var    propertyAndAnnotationCollector = new PropertyAndAnnotationCollector(true);
            object tmp = deserializer.ReadCustomInstanceAnnotationValue(propertyAndAnnotationCollector, "OData.CollectionAnnotation");

            tmp.As <ODataCollectionValue>().Items.Cast <string>().Count().Should().Be(0);
            tmp.As <ODataCollectionValue>().TypeName.ShouldBeEquivalentTo(null);
        }
Beispiel #25
0
        public void ReadTopLevelResourceSetAnnotationsForFeedEndAndBufferingShouldSkipAllValues()
        {
            var deserializer = this.CreateJsonLightEntryAndFeedDeserializer("{\"@custom.before\":123,\"value\":[],\"@custom.after\":456}");

            AdvanceReaderToFirstProperty(deserializer.JsonReader);
            var feed = new ODataResourceSet();
            var propertyAndAnnotationCollector = new PropertyAndAnnotationCollector(true);

            deserializer.ReadTopLevelResourceSetAnnotations(feed, propertyAndAnnotationCollector, false /*forResourceSetStart*/, true /*readAllFeedProperties*/);
            feed.InstanceAnnotations.Should().BeEmpty();
        }
Beispiel #26
0
        public void ReadTopLevelResourceSetAnnotationsForFeedEndAndNonBufferingShouldSkipInstanceAnnotationsBasedOnReaderSettings()
        {
            var deserializer = this.CreateJsonLightEntryAndFeedDeserializer("{\"@custom.after\":456}", shouldReadAndValidateCustomInstanceAnnotations: false);

            AdvanceReaderToFirstProperty(deserializer.JsonReader);
            var feed = new ODataResourceSet();
            var propertyAndAnnotationCollector = new PropertyAndAnnotationCollector(true);

            deserializer.ReadTopLevelResourceSetAnnotations(feed, propertyAndAnnotationCollector, false /*forResourceSetStart*/, false /*readAllFeedProperties*/);
            Assert.Equal(0, feed.InstanceAnnotations.Count);
        }
Beispiel #27
0
        public void ReadAndApplyResourceSetInstanceAnnotationValueShouldSetInstanceAnnotationOnFeed()
        {
            var deserializer = this.CreateJsonLightEntryAndFeedDeserializer("{\"@custom.Int32Annotation\":123}");

            AdvanceReaderToFirstPropertyValue(deserializer.JsonReader);
            var propertyAndAnnotationCollector = new PropertyAndAnnotationCollector(true);
            ODataResourceSet feed = new ODataResourceSet();

            deserializer.ReadAndApplyResourceSetInstanceAnnotationValue("custom.Int32Annotation", feed, propertyAndAnnotationCollector);
            Assert.Equal(1, feed.InstanceAnnotations.Count);
            TestUtils.AssertODataValueAreEqual(new ODataPrimitiveValue(123), feed.InstanceAnnotations.Single(ia => ia.Name == "custom.Int32Annotation").Value);
        }
Beispiel #28
0
        public void ReadDateTypeInstanceAnnotationValueWillReadAsCorrectTypeFromModel()
        {
            var deserializer = this.CreateJsonLightEntryAndFeedDeserializer("{\"@custom.DateAnnotation\":\"2013-01-25\"}");

            AdvanceReaderToFirstPropertyValue(deserializer.JsonReader);
            var propertyAndAnnotationCollector = new PropertyAndAnnotationCollector(true);

            object value = deserializer.ReadCustomInstanceAnnotationValue(propertyAndAnnotationCollector, "custom.DateAnnotation");

            value.Should().BeOfType <Date>();
            value.Should().Be(Date.Parse("2013-01-25"));
        }
Beispiel #29
0
        public void ReadTimeOfDayTypeInstanceAnnotationValueWillReadAsCorrectTypeFromModel()
        {
            var deserializer = this.CreateJsonLightEntryAndFeedDeserializer("{\"@custom.TimeOfDayAnnotation\":\"12:30:40.900\"}");

            AdvanceReaderToFirstPropertyValue(deserializer.JsonReader);
            var propertyAndAnnotationCollector = new PropertyAndAnnotationCollector(true);

            object value = deserializer.ReadCustomInstanceAnnotationValue(propertyAndAnnotationCollector, "custom.TimeOfDayAnnotation");

            value.Should().BeOfType <TimeOfDay>();
            value.Should().Be(TimeOfDay.Parse("12:30:40.900"));
        }
Beispiel #30
0
        public void ReadTopLevelResourceSetAnnotationsForFeedEndAndNonBufferingShouldReadRemainingInstanceAnnotationsAfterValue()
        {
            var deserializer = this.CreateJsonLightEntryAndFeedDeserializer("{\"@custom.after\":456}");

            AdvanceReaderToFirstProperty(deserializer.JsonReader);
            var feed = new ODataResourceSet();
            var propertyAndAnnotationCollector = new PropertyAndAnnotationCollector(true);

            deserializer.ReadTopLevelResourceSetAnnotations(feed, propertyAndAnnotationCollector, false /*forResourceSetStart*/, false /*readAllFeedProperties*/);
            Assert.Equal(1, feed.InstanceAnnotations.Count);
            TestUtils.AssertODataValueAreEqual(new ODataPrimitiveValue(456), feed.InstanceAnnotations.Single(ia => ia.Name == "custom.after").Value);
        }