/// <summary>
        /// Writes a set of links (Uris) in response to a $ref query; includes optional count and next-page-link information.
        /// </summary>
        /// <param name="entityReferenceLinks">The set of entity reference links to write out.</param>
        internal void WriteEntityReferenceLinks(ODataEntityReferenceLinks entityReferenceLinks)
        {
            Debug.Assert(entityReferenceLinks != null, "entityReferenceLinks != null");

            this.WriteTopLevelPayload(
                () => this.WriteEntityReferenceLinksImplementation(entityReferenceLinks));
        }
        /// <summary>
        /// Writes a set of links (Uris) in response to a $links query; includes optional count and next-page-link information.
        /// </summary>
        /// <param name="entityReferenceLinks">The set of entity reference links to write out.</param>
        internal void WriteEntityReferenceLinks(ODataEntityReferenceLinks entityReferenceLinks)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(entityReferenceLinks != null, "entityReferenceLinks != null");

            this.WriteTopLevelPayload(
                () => this.WriteEntityReferenceLinksImplementation(entityReferenceLinks, this.Version >= ODataVersion.V2 && this.WritingResponse));
        }
        /// <summary>
        /// Writes a set of links (Uris) in response to a $ref query; includes optional count and next-page-link information.
        /// </summary>
        /// <param name="entityReferenceLinks">The set of entity reference links to write out.</param>
        private void WriteEntityReferenceLinksImplementation(ODataEntityReferenceLinks entityReferenceLinks)
        {
            Debug.Assert(entityReferenceLinks != null, "entityReferenceLinks != null");

            bool wroteNextLink = false;

            // {
            this.JsonWriter.StartObjectScope();

            // "@odata.context": ...
            this.WriteContextUriProperty(ODataPayloadKind.EntityReferenceLinks);

            if (entityReferenceLinks.Count.HasValue)
            {
                // We try to write the count property at the top of the payload if one is available.
                // "@odata.count": ...
                this.WriteCountAnnotation(entityReferenceLinks.Count.Value);
            }

            if (entityReferenceLinks.NextPageLink != null)
            {
                // We try to write the next link at the top of the payload if one is available. If not, we try again at the end.
                wroteNextLink = true;

                // "@odata.next": ...
                this.WriteNextLinkAnnotation(entityReferenceLinks.NextPageLink);
            }

            this.InstanceAnnotationWriter.WriteInstanceAnnotations(entityReferenceLinks.InstanceAnnotations);

            // "value":
            this.JsonWriter.WriteValuePropertyName();

            // "[":
            this.JsonWriter.StartArrayScope();

            IEnumerable<ODataEntityReferenceLink> entityReferenceLinksEnumerable = entityReferenceLinks.Links;
            if (entityReferenceLinksEnumerable != null)
            {
                foreach (ODataEntityReferenceLink entityReferenceLink in entityReferenceLinksEnumerable)
                {
                    WriterValidationUtils.ValidateEntityReferenceLinkNotNull(entityReferenceLink);
                    this.WriteEntityReferenceLinkImplementation(entityReferenceLink, /* isTopLevel */ false);
                }
            }

            // "]"
            this.JsonWriter.EndArrayScope();

            if (!wroteNextLink && entityReferenceLinks.NextPageLink != null)
            {
                // "@odata.next": ...
                this.WriteNextLinkAnnotation(entityReferenceLinks.NextPageLink);
            }

            // "}"
            this.JsonWriter.EndObjectScope();
        }
        /// <summary>
        /// Writes a set of links (Uris) in response to a $links query; includes optional count and next-page-link information.
        /// </summary>
        /// <param name="entityReferenceLinks">The set of entity reference links to write out.</param>
        /// <param name="includeResultsWrapper">true if the 'results' wrapper should be included into the payload; otherwise false.</param>
        private void WriteEntityReferenceLinksImplementation(ODataEntityReferenceLinks entityReferenceLinks, bool includeResultsWrapper)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(entityReferenceLinks != null, "entityReferenceLinks != null");

            if (includeResultsWrapper)
            {
                // {
                this.JsonWriter.StartObjectScope();
            }

            if (entityReferenceLinks.Count.HasValue)
            {
                Debug.Assert(includeResultsWrapper, "Expected 'includeResultsWrapper' to be true if a count is specified.");
                this.JsonWriter.WriteName(JsonConstants.ODataCountName);

                this.JsonWriter.WriteValue(entityReferenceLinks.Count.Value);
            }

            if (includeResultsWrapper)
            {
                // "results":
                this.JsonWriter.WriteDataArrayName();
            }

            this.JsonWriter.StartArrayScope();

            IEnumerable<ODataEntityReferenceLink> entityReferenceLinksEnumerable = entityReferenceLinks.Links;
            if (entityReferenceLinksEnumerable != null)
            {
                foreach (ODataEntityReferenceLink entityReferenceLink in entityReferenceLinksEnumerable)
                {
                    WriterValidationUtils.ValidateEntityReferenceLinkNotNull(entityReferenceLink);
                    this.WriteEntityReferenceLinkImplementation(entityReferenceLink);
                }
            }

            this.JsonWriter.EndArrayScope();

            if (entityReferenceLinks.NextPageLink != null)
            {
                // "__next": ...
                Debug.Assert(includeResultsWrapper, "Expected 'includeResultsWrapper' to be true if a next page link is specified.");
                this.JsonWriter.WriteName(JsonConstants.ODataNextLinkName);
                this.JsonWriter.WriteValue(this.UriToAbsoluteUriString(entityReferenceLinks.NextPageLink));
            }

            if (includeResultsWrapper)
            {
                this.JsonWriter.EndObjectScope();
            }
        }
 public void ShouldBeAbleToSetLinksReferenceLinks()
 {
     ODataEntityReferenceLink link = new ODataEntityReferenceLink
     {
         Url = new Uri("http://host/Customers(1)")
     };
     ODataEntityReferenceLinks referencelinks = new ODataEntityReferenceLinks()
     {
         Links = new[] { link }
     };
     referencelinks.Should().NotBeNull();
     referencelinks.Links.Should().NotBeNull();
     referencelinks.Links.Count().Should().Be(1);
 }
        /// <summary>
        /// Writes a set of links (Uris) in response to a $ref query; includes optional count and next-page-link information.
        /// </summary>
        /// <param name="entityReferenceLinks">The set of entity reference links to write out.</param>
        internal void WriteEntityReferenceLinks(ODataEntityReferenceLinks entityReferenceLinks)
        {
            Debug.Assert(entityReferenceLinks != null, "entityReferenceLinks != null");

            this.WritePayloadStart();

            // COMPAT 25: Should $link payloads use the default 'd' namespace prefix for data service elements (instead of no prefix)? 

            // <feed> ...
            this.XmlWriter.WriteStartElement(string.Empty, AtomConstants.AtomFeedElementName, AtomConstants.AtomNamespace);

            // xmlns:metadata=
            this.XmlWriter.WriteAttributeString(AtomConstants.XmlnsNamespacePrefix, AtomConstants.ODataMetadataNamespacePrefix, null, AtomConstants.ODataMetadataNamespace);

            // metadata:context
            this.WriteContextUriProperty(this.contextUriBuilder.BuildContextUri(ODataPayloadKind.EntityReferenceLinks));

            if (entityReferenceLinks.Count.HasValue)
            {
                // <m:count>
                this.WriteCount(entityReferenceLinks.Count.Value);
            }

            IEnumerable<ODataEntityReferenceLink> entityReferenceLinkEnumerable = entityReferenceLinks.Links;
            if (entityReferenceLinkEnumerable != null)
            {
                foreach (ODataEntityReferenceLink entityReferenceLink in entityReferenceLinkEnumerable)
                {
                    WriterValidationUtils.ValidateEntityReferenceLinkNotNull(entityReferenceLink);
                    this.WriteEntityReferenceLink(entityReferenceLink, false);
                }
            }

            if (entityReferenceLinks.NextPageLink != null)
            {
                // <d:next>
                string nextLink = this.UriToUrlAttributeValue(entityReferenceLinks.NextPageLink);
                this.XmlWriter.WriteElementString(string.Empty, AtomConstants.ODataNextLinkElementName, AtomConstants.ODataNamespace, nextLink);
            }

            // </feed>
            this.XmlWriter.WriteEndElement();

            this.WritePayloadEnd();
        }
        /// <summary>
        /// Read a set of top-level entity reference links.
        /// </summary>
        /// <returns>An <see cref="ODataEntityReferenceLinks"/> representing the read links.</returns>
        internal ODataEntityReferenceLinks ReadEntityReferenceLinks()
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(this.JsonReader.NodeType == JsonNodeType.None, "Pre-Condition: expected JsonNodeType.None, the reader must not have been used yet.");
            this.JsonReader.AssertNotBuffering();

            // Set to true if the entity reference links are expected to have the 'results' wrapper.
            // Entity reference links are only expected to have a results wrapper if
            // (a) the protocol version is >= 2 AND
            // (b) we are reading a response
            // NOTE: OIPI does not specify a format for >= v2 entity reference links in requests; we thus use the v1 format and consequently do not expect a result wrapper.
            bool isResultsWrapperExpected = this.Version >= ODataVersion.V2 && this.ReadingResponse;

            ODataJsonReaderUtils.EntityReferenceLinksWrapperPropertyBitMask propertiesFoundBitField =
                ODataJsonReaderUtils.EntityReferenceLinksWrapperPropertyBitMask.None;
            ODataEntityReferenceLinks entityReferenceLinks = new ODataEntityReferenceLinks();

            // Read the response wrapper "d" if expected.
            this.ReadPayloadStart(false /*isReadingNestedPayload*/);

            if (isResultsWrapperExpected)
            {
                // Read the start object of the results wrapper object
                this.JsonReader.ReadStartObject();

                bool foundResultsProperty = this.ReadEntityReferenceLinkProperties(entityReferenceLinks, ref propertiesFoundBitField);

                if (!foundResultsProperty)
                {
                    throw new ODataException(Strings.ODataJsonEntityReferenceLinkDeserializer_ExpectedEntityReferenceLinksResultsPropertyNotFound);
                }
            }

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

            List<ODataEntityReferenceLink> links = new List<ODataEntityReferenceLink>();

            while (this.JsonReader.NodeType != JsonNodeType.EndArray)
            {
                // read another link
                ODataEntityReferenceLink entityReferenceLink = this.ReadSingleEntityReferenceLink();
                links.Add(entityReferenceLink);
            }

            // Read over the end object - note that this might be the last node in the input (in case there's no response wrapper)
            this.JsonReader.ReadEndArray();

            if (isResultsWrapperExpected)
            {
                this.ReadEntityReferenceLinkProperties(entityReferenceLinks, ref propertiesFoundBitField);

                // Read the end object of the results wrapper object
                this.JsonReader.ReadEndObject();
            }

            entityReferenceLinks.Links = new ReadOnlyEnumerable<ODataEntityReferenceLink>(links);

            // Read the end of the response wrapper "d" if expected.
            this.ReadPayloadEnd(false /*isReadingNestedPayload*/);

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

            return entityReferenceLinks;
        }
 private static string WriteToString(ODataEntityReferenceLinks referencelinks, bool writingResponse = true, bool synchronous = true)
 {
     MemoryStream stream = new MemoryStream();
     var outputContext = CreateJsonLightOutputContext(stream, writingResponse, synchronous);
     outputContext.WriteEntityReferenceLinks(referencelinks);
     stream.Seek(0, SeekOrigin.Begin);
     return (new StreamReader(stream)).ReadToEnd();
 }
 public void TheNewEntityReferenceLinksShouldNotBeNull()
 {
     ODataEntityReferenceLinks referencelinks = new ODataEntityReferenceLinks();
     referencelinks.Should().NotBeNull();
     referencelinks.Links.Should().BeNull();
 }
Ejemplo n.º 10
0
 private static void SameEntityReferenceLinks(ODataEntityReferenceLinks links1, ODataEntityReferenceLinks links2)
 {
     links1.Should().NotBeNull();
     links2.Should().NotBeNull();
     links1.Links.Should().NotBeNull();
     links2.Links.Should().NotBeNull();
     links1.Links.Count().Should().Equals(links2.Links.Count());
     for (var i = 0; i < links1.Links.Count(); ++i)
     {
         SameEntityReferenceLink(links1.Links.ElementAt(i), links2.Links.ElementAt(i));
     }
     SameInstanceAnnotations(links1.InstanceAnnotations, links2.InstanceAnnotations);
 }
        /// <summary>
        /// Reads the entity reference link instance annotations.
        /// </summary>
        /// <param name="links">The <see cref="ODataEntityReferenceLinks"/> to read the annotations for.</param>
        /// <param name="propertyAndAnnotationCollector">The duplicate property names checker for the entity reference links scope.</param>
        /// <param name="forLinksStart">true when parsing the instance annotations before the 'value' property;
        /// false when parsing the instance annotations after the 'value' property.</param>
        /// <remarks>
        /// Pre-Condition:  JsonNodeType.Property               The first property in the payload (or the first property after the context URI in responses)
        ///                 JsonNodeType.EndObject              The end of the entity reference links object
        /// Post-Condition: JsonNodeType.EndObject              When the end of the entity reference links object is reached
        ///                 Any                                 The first node of the value of the 'url' property (if found)
        /// </remarks>
        private void ReadEntityReferenceLinksAnnotations(ODataEntityReferenceLinks links, PropertyAndAnnotationCollector propertyAndAnnotationCollector, bool forLinksStart)
        {
            Debug.Assert(links != null, "links != null");
            Debug.Assert(propertyAndAnnotationCollector != null, "propertyAndAnnotationCollector != null");
            this.AssertJsonCondition(JsonNodeType.Property, JsonNodeType.EndObject);
            this.JsonReader.AssertNotBuffering();

            while (this.JsonReader.NodeType == JsonNodeType.Property)
            {
                // OData property annotations are not supported on entity reference links.
                Func <string, object> propertyAnnotationValueReader =
                    annotationName => { throw new ODataException(ODataErrorStrings.ODataJsonLightEntityReferenceLinkDeserializer_PropertyAnnotationForEntityReferenceLinks); };

                bool foundValueProperty = false;
                this.ProcessProperty(
                    propertyAndAnnotationCollector,
                    propertyAnnotationValueReader,
                    (propertyParseResult, propertyName) =>
                {
                    switch (propertyParseResult)
                    {
                    case PropertyParsingResult.ODataInstanceAnnotation:
                        if (string.CompareOrdinal(ODataAnnotationNames.ODataNextLink, propertyName) == 0)
                        {
                            this.ReadEntityReferenceLinksNextLinkAnnotationValue(links);
                        }
                        else if (string.CompareOrdinal(ODataAnnotationNames.ODataCount, propertyName) == 0)
                        {
                            this.ReadEntityReferenceCountAnnotationValue(links);
                        }
                        else
                        {
                            throw new ODataException(ODataErrorStrings.ODataJsonLightPropertyAndValueDeserializer_UnexpectedAnnotationProperties(propertyName));
                        }

                        break;

                    case PropertyParsingResult.CustomInstanceAnnotation:
                        Debug.Assert(!string.IsNullOrEmpty(propertyName), "!string.IsNullOrEmpty(propertyName)");
                        this.AssertJsonCondition(JsonNodeType.PrimitiveValue, JsonNodeType.StartObject, JsonNodeType.StartArray);
                        ODataAnnotationNames.ValidateIsCustomAnnotationName(propertyName);
                        Debug.Assert(
                            !this.MessageReaderSettings.ShouldSkipAnnotation(propertyName),
                            "!this.MessageReaderSettings.ShouldReadAndValidateAnnotation(propertyName) -- otherwise we should have already skipped the custom annotation and won't see it here.");
                        object annotationValue = this.ReadCustomInstanceAnnotationValue(propertyAndAnnotationCollector, propertyName);
                        links.InstanceAnnotations.Add(new ODataInstanceAnnotation(propertyName, annotationValue.ToODataValue()));
                        break;

                    case PropertyParsingResult.PropertyWithValue:
                        if (string.CompareOrdinal(JsonLightConstants.ODataValuePropertyName, propertyName) != 0)
                        {
                            // We did not find a supported link collection property; fail.
                            throw new ODataException(ODataErrorStrings.ODataJsonLightEntityReferenceLinkDeserializer_InvalidEntityReferenceLinksPropertyFound(propertyName, JsonLightConstants.ODataValuePropertyName));
                        }

                        // We found the link collection property and are done parsing property annotations;
                        foundValueProperty = true;
                        break;

                    case PropertyParsingResult.PropertyWithoutValue:
                        // If we find a property without a value it means that we did not find the entity reference links property (yet)
                        // but an invalid property annotation
                        throw new ODataException(ODataErrorStrings.ODataJsonLightEntityReferenceLinkDeserializer_InvalidPropertyAnnotationInEntityReferenceLinks(propertyName));

                    case PropertyParsingResult.EndOfObject:
                        break;

                    case PropertyParsingResult.MetadataReferenceProperty:
                        throw new ODataException(ODataErrorStrings.ODataJsonLightPropertyAndValueDeserializer_UnexpectedMetadataReferenceProperty(propertyName));

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

                if (foundValueProperty)
                {
                    return;
                }
            }

            if (forLinksStart)
            {
                // We did not find the 'value' property.
                throw new ODataException(ODataErrorStrings.ODataJsonLightEntityReferenceLinkDeserializer_ExpectedEntityReferenceLinksPropertyNotFound(JsonLightConstants.ODataValuePropertyName));
            }

            this.AssertJsonCondition(JsonNodeType.EndObject);
        }
Ejemplo n.º 12
0
 internal void WriteEntityReferenceLinks(ODataEntityReferenceLinks entityReferenceLinks)
 {
     base.WriteTopLevelPayload(() => this.WriteEntityReferenceLinksImplementation(entityReferenceLinks, (this.Version >= ODataVersion.V2) && this.WritingResponse));
 }
Ejemplo n.º 13
0
        /// <summary>
        /// Visits an item in the object model.
        /// </summary>
        /// <param name="objectModelItem">The item to visit.</param>
        public virtual T Visit(object objectModelItem)
        {
            ODataFeed feed = objectModelItem as ODataFeed;

            if (feed != null)
            {
                return(this.VisitFeed(feed));
            }

            ODataEntry entry = objectModelItem as ODataEntry;

            if (entry != null)
            {
                return(this.VisitEntry(entry));
            }

            ODataProperty property = objectModelItem as ODataProperty;

            if (property != null)
            {
                return(this.VisitProperty(property));
            }

            ODataNavigationLink navigationLink = objectModelItem as ODataNavigationLink;

            if (navigationLink != null)
            {
                return(this.VisitNavigationLink(navigationLink));
            }

            ODataComplexValue complexValue = objectModelItem as ODataComplexValue;

            if (complexValue != null)
            {
                return(this.VisitComplexValue(complexValue));
            }

            ODataCollectionValue collection = objectModelItem as ODataCollectionValue;

            if (collection != null)
            {
                return(this.VisitCollectionValue(collection));
            }

            ODataStreamReferenceValue streamReferenceValue = objectModelItem as ODataStreamReferenceValue;

            if (streamReferenceValue != null)
            {
                return(this.VisitStreamReferenceValue(streamReferenceValue));
            }

            ODataCollectionStart collectionStart = objectModelItem as ODataCollectionStart;

            if (collectionStart != null)
            {
                return(this.VisitCollectionStart(collectionStart));
            }

            ODataServiceDocument serviceDocument = objectModelItem as ODataServiceDocument;

            if (serviceDocument != null)
            {
                return(this.VisitWorkspace(serviceDocument));
            }

            ODataEntitySetInfo entitySetInfo = objectModelItem as ODataEntitySetInfo;

            if (entitySetInfo != null)
            {
                return(this.VisitResourceCollection(entitySetInfo));
            }

            ODataError error = objectModelItem as ODataError;

            if (error != null)
            {
                return(this.VisitError(error));
            }

            ODataInnerError innerError = objectModelItem as ODataInnerError;

            if (innerError != null)
            {
                return(this.VisitInnerError(innerError));
            }

            ODataEntityReferenceLinks entityReferenceLinks = objectModelItem as ODataEntityReferenceLinks;

            if (entityReferenceLinks != null)
            {
                return(this.VisitEntityReferenceLinks(entityReferenceLinks));
            }

            ODataEntityReferenceLink entityReferenceLink = objectModelItem as ODataEntityReferenceLink;

            if (entityReferenceLink != null)
            {
                return(this.VisitEntityReferenceLink(entityReferenceLink));
            }

            ODataAction action = objectModelItem as ODataAction;

            if (action != null)
            {
                return(this.VisitODataOperation(action));
            }

            ODataFunction function = objectModelItem as ODataFunction;

            if (function != null)
            {
                return(this.VisitODataOperation(function));
            }

            ODataParameters parameters = objectModelItem as ODataParameters;

            if (parameters != null)
            {
                return(this.VisitParameters(parameters));
            }

            ODataBatch batch = objectModelItem as ODataBatch;

            if (batch != null)
            {
                return(this.VisitBatch(batch));
            }

            if (objectModelItem == null || objectModelItem.GetType().IsValueType || objectModelItem is string ||
                objectModelItem is byte[] || objectModelItem is ISpatial)
            {
                return(this.VisitPrimitiveValue(objectModelItem));
            }

            return(this.VisitUnsupportedValue(objectModelItem));
        }
        /// <summary>
        /// Read a set of top-level entity reference links.
        /// </summary>
        /// <param name="duplicatePropertyNamesChecker">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(DuplicatePropertyNamesChecker duplicatePropertyNamesChecker)
        {
            Debug.Assert(duplicatePropertyNamesChecker != null, "duplicatePropertyNamesChecker != null");

            ODataEntityReferenceLinks entityReferenceLinks = new ODataEntityReferenceLinks();

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

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

            List<ODataEntityReferenceLink> links = new List<ODataEntityReferenceLink>();
            DuplicatePropertyNamesChecker linkDuplicatePropertyNamesChecker = this.JsonLightInputContext.CreateDuplicatePropertyNamesChecker();

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

            this.JsonReader.ReadEndArray();

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

            this.JsonReader.ReadEndObject();

            entityReferenceLinks.Links = new ReadOnlyEnumerable<ODataEntityReferenceLink>(links);
            return entityReferenceLinks;
        }
        /// <summary>
        /// Reads the entity reference link instance annotations.
        /// </summary>
        /// <param name="links">The <see cref="ODataEntityReferenceLinks"/> to read the annotations for.</param>
        /// <param name="duplicatePropertyNamesChecker">The duplicate property names checker for the entity reference links scope.</param>
        /// <param name="forLinksStart">true when parsing the instance annotations before the 'value' property; 
        /// false when parsing the instance annotations after the 'value' property.</param>
        /// <remarks>
        /// Pre-Condition:  JsonNodeType.Property               The first property in the payload (or the first property after the context URI in responses)
        ///                 JsonNodeType.EndObject              The end of the entity reference links object
        /// Post-Condition: JsonNodeType.EndObject              When the end of the entity reference links object is reached
        ///                 Any                                 The first node of the value of the 'url' property (if found)
        /// </remarks>
        private void ReadEntityReferenceLinksAnnotations(ODataEntityReferenceLinks links, DuplicatePropertyNamesChecker duplicatePropertyNamesChecker, bool forLinksStart)
        {
            Debug.Assert(links != null, "links != null");
            Debug.Assert(duplicatePropertyNamesChecker != null, "duplicatePropertyNamesChecker != null");
            this.AssertJsonCondition(JsonNodeType.Property, JsonNodeType.EndObject);
            this.JsonReader.AssertNotBuffering();

            while (this.JsonReader.NodeType == JsonNodeType.Property)
            {
                // OData property annotations are not supported on entity reference links.
                Func<string, object> propertyAnnotationValueReader =
                    annotationName => { throw new ODataException(ODataErrorStrings.ODataJsonLightEntityReferenceLinkDeserializer_PropertyAnnotationForEntityReferenceLinks); };

                bool foundValueProperty = false;
                this.ProcessProperty(
                    duplicatePropertyNamesChecker,
                    propertyAnnotationValueReader,
                    (propertyParseResult, propertyName) =>
                    {
                        switch (propertyParseResult)
                        {
                            case PropertyParsingResult.ODataInstanceAnnotation:
                                if (string.CompareOrdinal(ODataAnnotationNames.ODataNextLink, propertyName) == 0)
                                {
                                    this.ReadEntityReferenceLinksNextLinkAnnotationValue(links);
                                }
                                else if (string.CompareOrdinal(ODataAnnotationNames.ODataCount, propertyName) == 0)
                                {
                                    this.ReadEntityReferenceCountAnnotationValue(links);
                                }
                                else
                                {
                                    throw new ODataException(ODataErrorStrings.ODataJsonLightPropertyAndValueDeserializer_UnexpectedAnnotationProperties(propertyName));
                                }

                                break;

                            case PropertyParsingResult.CustomInstanceAnnotation:
                                this.JsonReader.SkipValue();
                                break;

                            case PropertyParsingResult.PropertyWithValue:
                                if (string.CompareOrdinal(JsonLightConstants.ODataValuePropertyName, propertyName) != 0)
                                {
                                    // We did not find a supported link collection property; fail.
                                    throw new ODataException(ODataErrorStrings.ODataJsonLightEntityReferenceLinkDeserializer_InvalidEntityReferenceLinksPropertyFound(propertyName, JsonLightConstants.ODataValuePropertyName));
                                }

                                // We found the link collection property and are done parsing property annotations;
                                foundValueProperty = true;
                                break;

                            case PropertyParsingResult.PropertyWithoutValue:
                                // If we find a property without a value it means that we did not find the entity reference links property (yet)
                                // but an invalid property annotation
                                throw new ODataException(ODataErrorStrings.ODataJsonLightEntityReferenceLinkDeserializer_InvalidPropertyAnnotationInEntityReferenceLinks(propertyName));

                            case PropertyParsingResult.EndOfObject:
                                break;

                            case PropertyParsingResult.MetadataReferenceProperty:
                                throw new ODataException(ODataErrorStrings.ODataJsonLightPropertyAndValueDeserializer_UnexpectedMetadataReferenceProperty(propertyName));

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

                if (foundValueProperty)
                {
                    return;
                }
            }

            if (forLinksStart)
            {
                // We did not find the 'value' property.
                throw new ODataException(ODataErrorStrings.ODataJsonLightEntityReferenceLinkDeserializer_ExpectedEntityReferenceLinksPropertyNotFound(JsonLightConstants.ODataValuePropertyName));
            }

            this.AssertJsonCondition(JsonNodeType.EndObject);
        }
 private void WriteEntityReferenceLinks(ODataMessageWriterTestWrapper messageWriter, ODataEntityReferenceLinks referenceLinks)
 {
     messageWriter.WriteEntityReferenceLinks(referenceLinks);
 }
 /// <summary>
 /// Visits an entity reference link collection.
 /// </summary>
 /// <param name="entityReferenceLinks">The entity reference link collection to visit.</param>
 protected override void VisitEntityReferenceLinks(ODataEntityReferenceLinks entityReferenceLinks)
 {
     this.ValidateUri(entityReferenceLinks.NextPageLink);
     base.VisitEntityReferenceLinks(entityReferenceLinks);
 }
Ejemplo n.º 18
0
        /// <summary>
        /// Read a set of top-level entity reference links.
        /// </summary>
        /// <returns>An <see cref="ODataEntityReferenceLinks"/> representing the read links.</returns>
        internal ODataEntityReferenceLinks ReadEntityReferenceLinks()
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(this.JsonReader.NodeType == JsonNodeType.None, "Pre-Condition: expected JsonNodeType.None, the reader must not have been used yet.");
            this.JsonReader.AssertNotBuffering();

            // Set to true if the entity reference links are expected to have the 'results' wrapper.
            // Entity reference links are only expected to have a results wrapper if
            // (a) the protocol version is >= 2 AND
            // (b) we are reading a response
            // NOTE: OIPI does not specify a format for >= v2 entity reference links in requests; we thus use the v1 format and consequently do not expect a result wrapper.
            bool isResultsWrapperExpected = this.Version >= ODataVersion.V2 && this.ReadingResponse;

            ODataJsonReaderUtils.EntityReferenceLinksWrapperPropertyBitMask propertiesFoundBitField =
                ODataJsonReaderUtils.EntityReferenceLinksWrapperPropertyBitMask.None;
            ODataEntityReferenceLinks entityReferenceLinks = new ODataEntityReferenceLinks();

            // Read the response wrapper "d" if expected.
            this.ReadPayloadStart(false /*isReadingNestedPayload*/);

            if (isResultsWrapperExpected)
            {
                // Read the start object of the results wrapper object
                this.JsonReader.ReadStartObject();

                bool foundResultsProperty = this.ReadEntityReferenceLinkProperties(entityReferenceLinks, ref propertiesFoundBitField);

                if (!foundResultsProperty)
                {
                    throw new ODataException(Strings.ODataJsonEntityReferenceLinkDeserializer_ExpectedEntityReferenceLinksResultsPropertyNotFound);
                }
            }

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

            List <ODataEntityReferenceLink> links = new List <ODataEntityReferenceLink>();

            while (this.JsonReader.NodeType != JsonNodeType.EndArray)
            {
                // read another link
                ODataEntityReferenceLink entityReferenceLink = this.ReadSingleEntityReferenceLink();
                links.Add(entityReferenceLink);
            }

            // Read over the end object - note that this might be the last node in the input (in case there's no response wrapper)
            this.JsonReader.ReadEndArray();

            if (isResultsWrapperExpected)
            {
                this.ReadEntityReferenceLinkProperties(entityReferenceLinks, ref propertiesFoundBitField);

                // Read the end object of the results wrapper object
                this.JsonReader.ReadEndObject();
            }

            entityReferenceLinks.Links = new ReadOnlyEnumerable <ODataEntityReferenceLink>(links);

            // Read the end of the response wrapper "d" if expected.
            this.ReadPayloadEnd(false /*isReadingNestedPayload*/);

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

            return(entityReferenceLinks);
        }
Ejemplo n.º 19
0
 internal override void WriteEntityReferenceLinks(ODataEntityReferenceLinks links)
 {
     this.WriteEntityReferenceLinksImplementation(links);
     this.Flush();
 }
        /// <summary>
        /// Asynchronously writes a set of links (Uris) in response to a $ref query; includes optional count and next-page-link information.
        /// </summary>
        /// <param name="entityReferenceLinks">The set of entity reference links to write out.</param>
        private async Task WriteEntityReferenceLinksImplementationAsync(ODataEntityReferenceLinks entityReferenceLinks)
        {
            Debug.Assert(entityReferenceLinks != null, "entityReferenceLinks != null");

            bool wroteNextLink = false;

            // {
            await this.AsynchronousJsonWriter.StartObjectScopeAsync()
            .ConfigureAwait(false);

            // "@odata.context": ...
            await this.WriteContextUriPropertyAsync(ODataPayloadKind.EntityReferenceLinks)
            .ConfigureAwait(false);

            if (entityReferenceLinks.Count.HasValue)
            {
                // We try to write the count property at the top of the payload if one is available.
                // "@odata.count": ...
                await this.WriteCountAnnotationAsync(entityReferenceLinks.Count.Value)
                .ConfigureAwait(false);
            }

            if (entityReferenceLinks.NextPageLink != null)
            {
                // We try to write the next link at the top of the payload if one is available. If not, we try again at the end.
                wroteNextLink = true;

                // "@odata.next": ...
                await this.WriteNextLinkAnnotationAsync(entityReferenceLinks.NextPageLink)
                .ConfigureAwait(false);
            }

            this.InstanceAnnotationWriter.WriteInstanceAnnotations(entityReferenceLinks.InstanceAnnotations);

            // "value":
            await this.AsynchronousJsonWriter.WriteValuePropertyNameAsync()
            .ConfigureAwait(false);

            // "[":
            await this.AsynchronousJsonWriter.StartArrayScopeAsync()
            .ConfigureAwait(false);

            IEnumerable <ODataEntityReferenceLink> entityReferenceLinksEnumerable = entityReferenceLinks.Links;

            if (entityReferenceLinksEnumerable != null)
            {
                foreach (ODataEntityReferenceLink entityReferenceLink in entityReferenceLinksEnumerable)
                {
                    WriterValidationUtils.ValidateEntityReferenceLinkNotNull(entityReferenceLink);
                    await this.WriteEntityReferenceLinkImplementationAsync(entityReferenceLink, /* isTopLevel */ false)
                    .ConfigureAwait(false);
                }
            }

            // "]"
            await this.AsynchronousJsonWriter.EndArrayScopeAsync()
            .ConfigureAwait(false);

            if (!wroteNextLink && entityReferenceLinks.NextPageLink != null)
            {
                // "@odata.next": ...
                await this.WriteNextLinkAnnotationAsync(entityReferenceLinks.NextPageLink)
                .ConfigureAwait(false);
            }

            // "}"
            await this.AsynchronousJsonWriter.EndObjectScopeAsync()
            .ConfigureAwait(false);
        }
        public void ShouldWriteForEntityReferenceLinksWithMultpleLinks()
        {
            ODataEntityReferenceLink link1 = new ODataEntityReferenceLink
            {
                Url = new Uri("http://host/Customers(1)")
            };
            link1.InstanceAnnotations.Add(new ODataInstanceAnnotation("Is.New", new ODataPrimitiveValue(true)));
            ODataEntityReferenceLink link2 = new ODataEntityReferenceLink
            {
                Url = new Uri("http://host/Customers(2)")
            };
            link2.InstanceAnnotations.Add(new ODataInstanceAnnotation("TestNamespace.unknown", new ODataPrimitiveValue(123)));
            link2.InstanceAnnotations.Add(new ODataInstanceAnnotation("custom.annotation", new ODataPrimitiveValue(456)));

            ODataEntityReferenceLinks referencelinks = new ODataEntityReferenceLinks()
            {
                Links = new[] { link1, link2 }
            };
            string expectedPayload = "{\"@odata.context\":\"http://odata.org/test/$metadata#Collection($ref)\",\"value\":[{\"@odata.id\":\"http://host/Customers(1)\",\"@Is.New\":true},{\"@odata.id\":\"http://host/Customers(2)\",\"@TestNamespace.unknown\":123,\"@custom.annotation\":456}]}";
            WriteAndValidate(referencelinks, expectedPayload, writingResponse: false);
            WriteAndValidate(referencelinks, expectedPayload, writingResponse: true);
        }
        /// <summary>
        /// Reads the odata.nextlink value of an entity reference links nextlink annotation.
        /// </summary>
        /// <param name="links">The entity reference links to read the next link value for; the value of the nextlink will be assigned to this instance.</param>
        /// <remarks>
        /// Pre-Condition:  JsonNodeType.PrimitiveValue         The value of the instance annotation
        /// Post-Condition: JsonNodeType.EndObject              The end of the entity reference links object
        ///                 JsonNodeType.Property               The next property after the instance annotation
        /// </remarks>
        private void ReadEntityReferenceLinksNextLinkAnnotationValue(ODataEntityReferenceLinks links)
        {
            Debug.Assert(links != null, "links != null");
            this.AssertJsonCondition(JsonNodeType.PrimitiveValue);

            Uri nextPageUri = this.ReadAndValidateAnnotationStringValueAsUri(ODataAnnotationNames.ODataNextLink);
            Debug.Assert(links.NextPageLink == null, "We should have checked for duplicates already.");
            links.NextPageLink = nextPageUri;
        }
Ejemplo n.º 23
0
        public static string ConvertToUriLiteral(object value, ODataVersion version, IEdmModel model)
        {
            if (value == null)
            {
                value = new ODataNullValue();
            }

            if (model == null)
            {
                model = Microsoft.OData.Edm.Library.EdmCoreModel.Instance;
            }

            ODataNullValue nullValue = value as ODataNullValue;

            if (nullValue != null)
            {
                return(ExpressionConstants.KeywordNull);
            }

            ODataCollectionValue collectionValue = value as ODataCollectionValue;

            if (collectionValue != null)
            {
                return(ODataUriConversionUtils.ConvertToUriCollectionLiteral(collectionValue, model, version));
            }

            ODataComplexValue complexValue = value as ODataComplexValue;

            if (complexValue != null)
            {
                return(ODataUriConversionUtils.ConvertToUriComplexLiteral(complexValue, model, version));
            }

            ODataEnumValue enumValue = value as ODataEnumValue;

            if (enumValue != null)
            {
                return(ODataUriConversionUtils.ConvertToUriEnumLiteral(enumValue, version));
            }

            ODataEntry entry = value as ODataEntry;

            if (entry != null)
            {
                return(ODataUriConversionUtils.ConvertToUriEntityLiteral(entry, model));
            }

            ODataEntityReferenceLink link = value as ODataEntityReferenceLink;

            if (link != null)
            {
                return(ODataUriConversionUtils.ConvertToUriEntityReferenceLiteral(link, model));
            }

            ODataEntityReferenceLinks links = value as ODataEntityReferenceLinks;

            if (links != null)
            {
                return(ODataUriConversionUtils.ConvertToUriEntityReferencesLiteral(links, model));
            }

            var list = value as IEnumerable <ODataEntry>;

            if (list != null)
            {
                return(ODataUriConversionUtils.ConvertToUriEntitiesLiteral(list, model));
            }

            // Try to convert uints to their underlying type first according to the model.
            value = model.ConvertToUnderlyingTypeIfUIntValue(value);

            return(ODataUriConversionUtils.ConvertToUriPrimitiveLiteral(value, version));
        }
 /// <summary>
 /// Reads the value of an entity reference links count annotation.
 /// </summary>
 /// <param name="links">The entity reference links to read the count value for; the value of the count will be assigned to this instance.</param>
 /// <remarks>
 /// Pre-Condition:  JsonNodeType.PrimitiveValue         The value of the instance annotation
 /// Post-Condition: JsonNodeType.EndObject              The end of the entity reference links object
 ///                 JsonNodeType.Property               The next property after the instance annotation
 /// </remarks>
 private void ReadEntityReferenceCountAnnotationValue(ODataEntityReferenceLinks links)
 {
     Debug.Assert(links != null, "links != null");
     this.AssertJsonCondition(JsonNodeType.PrimitiveValue);
     Debug.Assert(!links.Count.HasValue, "We should have checked for duplicates already.");
     links.Count = this.ReadAndValidateAnnotationAsLongForIeee754Compatible(ODataAnnotationNames.ODataCount);
 }
Ejemplo n.º 25
0
        /// <summary>
        /// Writes a set of links (Uris) in response to a $links query; includes optional count and next-page-link information.
        /// </summary>
        /// <param name="entityReferenceLinks">The set of entity reference links to write out.</param>
        /// <param name="entitySet">The entity set of the navigation property</param>
        /// <param name="navigationProperty">The navigation property for which the entity reference links are being written, or null if none is available.</param>
        private void WriteEntityReferenceLinksImplementation(ODataEntityReferenceLinks entityReferenceLinks, IEdmEntitySet entitySet, IEdmNavigationProperty navigationProperty)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(entityReferenceLinks != null, "entityReferenceLinks != null");

            bool wroteNextLink = false;
            bool wroteCount    = false;

            // {
            this.JsonWriter.StartObjectScope();

            Uri metadataUri;

            if (this.metadataUriBuilder.TryBuildEntityReferenceLinksMetadataUri(entityReferenceLinks.SerializationInfo, entitySet, navigationProperty, out metadataUri))
            {
                this.WriteMetadataUriProperty(metadataUri);
            }

            if (entityReferenceLinks.Count.HasValue)
            {
                // We try to write the count property at the top of the payload if one is available. If not, we try again at the end.
                wroteCount = true;

                // "odata.count": ...
                this.WriteCountAnnotation(entityReferenceLinks.Count.Value);
            }

            if (entityReferenceLinks.NextPageLink != null)
            {
                // We try to write the next link at the top of the payload if one is available. If not, we try again at the end.
                wroteNextLink = true;

                // "odata.next": ...
                this.WriteNextLinkAnnotation(entityReferenceLinks.NextPageLink);
            }

            // "value":
            this.JsonWriter.WriteValuePropertyName();

            // "[":
            this.JsonWriter.StartArrayScope();

            IEnumerable <ODataEntityReferenceLink> entityReferenceLinksEnumerable = entityReferenceLinks.Links;

            if (entityReferenceLinksEnumerable != null)
            {
                foreach (ODataEntityReferenceLink entityReferenceLink in entityReferenceLinksEnumerable)
                {
                    WriterValidationUtils.ValidateEntityReferenceLinkNotNull(entityReferenceLink);
                    this.WriteEntityReferenceLinkImplementation(entityReferenceLink, entitySet, /* navigationProperty */ null, /* isTopLevel */ false);
                }
            }

            // "]"
            this.JsonWriter.EndArrayScope();

            if (!wroteCount && entityReferenceLinks.Count.HasValue)
            {
                // "odata.count": ...
                this.WriteCountAnnotation(entityReferenceLinks.Count.Value);
            }

            if (!wroteNextLink && entityReferenceLinks.NextPageLink != null)
            {
                // "odata.next": ...
                this.WriteNextLinkAnnotation(entityReferenceLinks.NextPageLink);
            }

            // "}"
            this.JsonWriter.EndObjectScope();
        }
Ejemplo n.º 26
0
        /// <summary>
        /// Parse the constant entity collection node.
        /// </summary>
        /// <param name="nodeIn">The input constant node.</param>
        /// <returns>The parsed object.</returns>
        private object ParseEntityCollection(ConstantNode nodeIn)
        {
            ODataMessageReaderSettings settings = new ODataMessageReaderSettings();
            InMemoryMessage            message  = new InMemoryMessage()
            {
                Stream = new MemoryStream(System.Text.Encoding.UTF8.GetBytes(nodeIn.LiteralText)),
            };

            var entityType =
                ((nodeIn.TypeReference.Definition as IEdmCollectionType).ElementType as IEdmEntityTypeReference)
                .Definition as IEdmEntityType;
            object     list      = null;
            MethodInfo addMethod = null;

            using (
                ODataMessageReader reader = new ODataMessageReader(message as IODataRequestMessage, settings,
                                                                   this.UriParser.Model))
            {
                if (nodeIn.LiteralText.Contains("@odata.id"))
                {
                    ODataEntityReferenceLinks referenceLinks = reader.ReadEntityReferenceLinks();
                    foreach (var referenceLink in referenceLinks.Links)
                    {
                        var queryContext = new QueryContext(this.UriParser.ServiceRoot, referenceLink.Url,
                                                            this.DataSource.Model);
                        var target = queryContext.ResolveQuery(this.DataSource);

                        if (list == null)
                        {
                            // create the list. This would require the first type is not derived type.
                            Type listType = typeof(List <>).MakeGenericType(target.GetType());
                            addMethod = listType.GetMethod("Add");
                            list      = Activator.CreateInstance(listType);
                        }

                        addMethod.Invoke(list, new[] { target });
                    }

                    return(list);
                }

                var feedReader = reader.CreateODataFeedReader(
                    new EdmEntitySet(new EdmEntityContainer("NS", "Test"), "TestType", entityType),
                    entityType);
                ODataEntry entry = null;
                while (feedReader.Read())
                {
                    if (feedReader.State == ODataReaderState.EntryEnd)
                    {
                        entry = feedReader.Item as ODataEntry;
                        object item = ODataObjectModelConverter.ConvertPropertyValue(entry);


                        if (list == null)
                        {
                            // create the list. This would require the first type is not derived type.
                            var  type     = EdmClrTypeUtils.GetInstanceType(entry.TypeName);
                            Type listType = typeof(List <>).MakeGenericType(type);
                            addMethod = listType.GetMethod("Add");
                            list      = Activator.CreateInstance(listType);
                        }

                        addMethod.Invoke(list, new[] { item });
                    }
                }
                return(list);
            }
        }
Ejemplo n.º 27
0
 /// <summary>
 /// Visits an entity reference links instance.
 /// </summary>
 /// <param name="entityReferenceLinks">The entity reference links to visit.</param>
 protected override void VisitEntityReferenceLinks(ODataEntityReferenceLinks entityReferenceLinks)
 {
     this.ValidateEnumerable <ODataEntityReferenceLink>(entityReferenceLinks.Links, "ODataEntityReferenceLinks.Links");
     base.VisitEntityReferenceLinks(entityReferenceLinks);
 }
Ejemplo n.º 28
0
        public void WriteEntryWithWrongSerializationInfo()
        {
            foreach (var mimeType in this.testMimeTypes)
            {
                var settings = new ODataMessageWriterSettings();
                settings.ODataUri = new ODataUri()
                {
                    ServiceRoot = this.ServiceUri
                };

                // wrong EntitySetName for entry
                var responseMessageWithoutModel = new StreamResponseMessage(new MemoryStream());
                responseMessageWithoutModel.SetHeader("Content-Type", mimeType);
                using (var messageWriter = new ODataMessageWriter(responseMessageWithoutModel, settings))
                {
                    var odataWriter = messageWriter.CreateODataResourceWriter();
                    var entry       = this.CreatePersonEntryWithoutSerializationInfo();

                    entry.SetSerializationInfo(new ODataResourceSerializationInfo()
                    {
                        NavigationSourceName = "Parsen", NavigationSourceEntityTypeName = NameSpace + "Person"
                    });
                    odataWriter.WriteStart(entry);
                    odataWriter.WriteEnd();
                    var result = WritePayloadHelper.ReadStreamContent(responseMessageWithoutModel.GetStream());
                    Assert.IsTrue(result.Contains("\"PersonId\":-5"));
                    if (!mimeType.Contains(MimeTypes.ODataParameterNoMetadata))
                    {
                        // no metadata does not write odata.metadata
                        Assert.IsTrue(result.Contains("$metadata#Parsen/$entity"));
                        Assert.IsTrue(result.Contains("Person(-5)\",\"PersonId\":-5"));
                    }
                    else
                    {
                        Assert.IsFalse(result.Contains("Person(-5)\",\"PersonId\":-5"));
                    }
                }

                // wrong EntitySetName for feed
                responseMessageWithoutModel = new StreamResponseMessage(new MemoryStream());
                responseMessageWithoutModel.SetHeader("Content-Type", mimeType);
                using (var messageWriter = new ODataMessageWriter(responseMessageWithoutModel, settings))
                {
                    var odataWriter = messageWriter.CreateODataResourceSetWriter();

                    var feed = this.CreatePersonFeed();
                    feed.SetSerializationInfo(new ODataResourceSerializationInfo()
                    {
                        NavigationSourceName = "Parsen", NavigationSourceEntityTypeName = NameSpace + "Person"
                    });
                    var entry = this.CreatePersonEntryWithoutSerializationInfo();
                    odataWriter.WriteStart(feed);
                    odataWriter.WriteStart(entry);
                    odataWriter.WriteEnd();
                    odataWriter.WriteEnd();
                    var result = WritePayloadHelper.ReadStreamContent(responseMessageWithoutModel.GetStream());
                    Assert.IsTrue(result.Contains("\"PersonId\":-5"));
                    if (!mimeType.Contains(MimeTypes.ODataParameterNoMetadata))
                    {
                        // no metadata does not write odata.metadata
                        Assert.IsTrue(result.Contains("$metadata#Parsen\""));
                        Assert.IsTrue(result.Contains("Person(-5)\",\"PersonId\":-5"));
                    }
                    else
                    {
                        Assert.IsFalse(result.Contains("Person(-5)\",\"PersonId\":-5"));
                    }
                }

                // wrong complex collection type name
                responseMessageWithoutModel = new StreamResponseMessage(new MemoryStream());
                responseMessageWithoutModel.SetHeader("Content-Type", mimeType);
                using (var messageWriter = new ODataMessageWriter(responseMessageWithoutModel, settings))
                {
                    var odataWriter       = messageWriter.CreateODataResourceSetWriter();
                    var complexCollection = new ODataResourceSetWrapper()
                    {
                        ResourceSet = new ODataResourceSet(),
                        Resources   = new List <ODataResourceWrapper>()
                        {
                            WritePayloadHelper.CreatePrimaryContactODataWrapper()
                        }
                    };

                    complexCollection.ResourceSet.SetSerializationInfo(new ODataResourceSerializationInfo()
                    {
                        ExpectedTypeName = NameSpace + "ContactDETAIL"
                    });
                    ODataWriterHelper.WriteResourceSet(odataWriter, complexCollection);
                    var result = WritePayloadHelper.ReadStreamContent(responseMessageWithoutModel.GetStream());
                    if (!mimeType.Contains(MimeTypes.ODataParameterNoMetadata))
                    {
                        // [{"@odata.type":"#Microsoft.Test.OData.Services.AstoriaDefaultService.ContactDetails","*****@*****.**":"#Collection(String)"...
                        Assert.IsTrue(result.Contains("\"value\":[{\"@odata.type\":\"#Microsoft.Test.OData.Services.AstoriaDefaultService.ContactDetails\",\"EmailBag"));

                        // no metadata does not write odata.metadata
                        Assert.IsTrue(result.Contains("$metadata#Collection(" + NameSpace + "ContactDETAIL)"));
                    }
                    else
                    {
                        Assert.IsFalse(result.Contains("\"@odata.type\":\"#Microsoft.Test.OData.Services.AstoriaDefaultService.ContactDetails\""));
                    }
                }

                // The following two cases of wrong reference link info is no longer active. The ODataEntityReferenceLinkSerializationInfo is ignored when writer writes the payload.
                // Consider removing them.

                // wrong reference link info
                responseMessageWithoutModel = new StreamResponseMessage(new MemoryStream());
                responseMessageWithoutModel.SetHeader("Content-Type", mimeType);
                using (var messageWriter = new ODataMessageWriter(responseMessageWithoutModel, settings))
                {
                    var link = new ODataEntityReferenceLink()
                    {
                        Url = new Uri(this.ServiceUri + "Order(-10)")
                    };
                    messageWriter.WriteEntityReferenceLink(link);
                    var result = WritePayloadHelper.ReadStreamContent(responseMessageWithoutModel.GetStream());
                    Assert.IsTrue(result.Contains(this.ServiceUri + "Order(-10)"));
                    if (!mimeType.Contains(MimeTypes.ODataParameterNoMetadata))
                    {
                        // no metadata does not write odata.context
                        Assert.IsTrue(result.Contains("$metadata#$ref"));
                    }
                }

                // wrong reference links info
                responseMessageWithoutModel = new StreamResponseMessage(new MemoryStream());
                responseMessageWithoutModel.SetHeader("Content-Type", mimeType);
                using (var messageWriter = new ODataMessageWriter(responseMessageWithoutModel, settings))
                {
                    var links = new ODataEntityReferenceLinks()
                    {
                        Links = new[]
                        {
                            new ODataEntityReferenceLink()
                            {
                                Url = new Uri(this.ServiceUri + "Order(-10)")
                            }
                        },
                    };

                    messageWriter.WriteEntityReferenceLinks(links);
                    var result = WritePayloadHelper.ReadStreamContent(responseMessageWithoutModel.GetStream());
                    Assert.IsTrue(result.Contains(this.ServiceUri + "Order(-10)"));
                    if (!mimeType.Contains(MimeTypes.ODataParameterNoMetadata))
                    {
                        // no metadata does not write odata.metadata
                        Assert.IsTrue(result.Contains("$metadata#Collection($ref)"));
                    }
                }
            }
        }
Ejemplo n.º 29
0
 /// <summary>
 /// Writes the result of a $links query as the message payload.
 /// </summary>
 /// <param name="links">The entity reference links to write as message payload.</param>
 private void WriteEntityReferenceLinksImplementation(ODataEntityReferenceLinks links)
 {
     ODataAtomEntityReferenceLinkSerializer atomEntityReferenceLinkSerializer = new ODataAtomEntityReferenceLinkSerializer(this);
     atomEntityReferenceLinkSerializer.WriteEntityReferenceLinks(links);
 }
Ejemplo n.º 30
0
        public void WriteWithoutSerializationInfo()
        {
            foreach (var mimeType in this.testMimeTypes)
            {
                var settings = new ODataMessageWriterSettings();
                settings.ODataUri = new ODataUri()
                {
                    ServiceRoot = this.ServiceUri
                };

                // write entry without serialization info
                var responseMessageWithoutModel = new StreamResponseMessage(new MemoryStream());
                responseMessageWithoutModel.SetHeader("Content-Type", mimeType);
                using (var messageWriter = new ODataMessageWriter(responseMessageWithoutModel, settings))
                {
                    var odataWriter   = messageWriter.CreateODataResourceWriter();
                    var entry         = this.CreatePersonEntryWithoutSerializationInfo();
                    var expectedError = mimeType.Contains(MimeTypes.ODataParameterNoMetadata)
                                               ? null
                                               : "ODataResourceTypeContext_MetadataOrSerializationInfoMissing";
                    AssertThrows <ODataException>(() => odataWriter.WriteStart(entry), expectedError);
                }

                // write feed without serialization info
                responseMessageWithoutModel = new StreamResponseMessage(new MemoryStream());
                responseMessageWithoutModel.SetHeader("Content-Type", mimeType);
                using (var messageWriter = new ODataMessageWriter(responseMessageWithoutModel, settings))
                {
                    var odataWriter = messageWriter.CreateODataResourceSetWriter();
                    var feed        = this.CreatePersonFeed();
                    var entry       = this.CreatePersonEntryWithoutSerializationInfo();
                    entry.SetSerializationInfo(new ODataResourceSerializationInfo()
                    {
                        NavigationSourceName = "Person", NavigationSourceEntityTypeName = NameSpace + "Person"
                    });
                    var expectedError = mimeType.Contains(MimeTypes.ODataParameterNoMetadata)
                                               ? null
                                               : "ODataResourceTypeContext_MetadataOrSerializationInfoMissing";
                    AssertThrows <ODataException>(() => odataWriter.WriteStart(feed), expectedError);
                }

                // write collection without serialization info
                responseMessageWithoutModel = new StreamResponseMessage(new MemoryStream());
                responseMessageWithoutModel.SetHeader("Content-Type", mimeType);
                using (var messageWriter = new ODataMessageWriter(responseMessageWithoutModel, settings))
                {
                    var odataWriter     = messageWriter.CreateODataCollectionWriter();
                    var collectionStart = new ODataCollectionStart()
                    {
                        Name = "BackupContactInfo"
                    };
                    var expectedError = mimeType.Contains(MimeTypes.ODataParameterNoMetadata)
                                               ? null
                                               : "ODataContextUriBuilder_TypeNameMissingForTopLevelCollection";
                    AssertThrows <ODataException>(() => odataWriter.WriteStart(collectionStart), expectedError);
                }

                // write a reference link without serialization info
                responseMessageWithoutModel = new StreamResponseMessage(new MemoryStream());
                responseMessageWithoutModel.SetHeader("Content-Type", mimeType);
                using (var messageWriter = new ODataMessageWriter(responseMessageWithoutModel, settings))
                {
                    var link = new ODataEntityReferenceLink()
                    {
                        Url = new Uri(this.ServiceUri + "Order(-10)")
                    };
                    messageWriter.WriteEntityReferenceLink(link);

                    // No exception is expected. Simply verify the writing succeeded.
                    if (!mimeType.Contains(MimeTypes.ODataParameterNoMetadata))
                    {
                        Stream stream = responseMessageWithoutModel.GetStream();
                        Assert.IsTrue(WritePayloadHelper.ReadStreamContent(stream).Contains("$metadata#$ref"));
                    }
                }

                // write reference links without serialization info
                responseMessageWithoutModel = new StreamResponseMessage(new MemoryStream());
                responseMessageWithoutModel.SetHeader("Content-Type", mimeType);
                using (var messageWriter = new ODataMessageWriter(responseMessageWithoutModel, settings))
                {
                    var links = new ODataEntityReferenceLinks()
                    {
                        Links = new[]
                        {
                            new ODataEntityReferenceLink()
                            {
                                Url = new Uri(this.ServiceUri + "Order(-10)")
                            }
                        },
                    };
                    messageWriter.WriteEntityReferenceLinks(links);

                    // No exception is expected. Simply verify the writing succeeded.
                    if (!mimeType.Contains(MimeTypes.ODataParameterNoMetadata))
                    {
                        Stream stream = responseMessageWithoutModel.GetStream();
                        Assert.IsTrue(WritePayloadHelper.ReadStreamContent(stream).Contains("$metadata#Collection($ref)"));
                    }
                }

                // write request message containing an entry
                var requestMessageWithoutModel = new StreamRequestMessage(new MemoryStream(),
                                                                          new Uri(this.ServiceUri + "Person"), "POST");
                requestMessageWithoutModel.SetHeader("Content-Type", mimeType);
                using (var messageWriter = new ODataMessageWriter(requestMessageWithoutModel, settings))
                {
                    var odataWriter = messageWriter.CreateODataResourceWriter();
                    var entry       = this.CreatePersonEntryWithoutSerializationInfo();
                    odataWriter.WriteStart(entry);
                    odataWriter.WriteEnd();
                    Stream stream = requestMessageWithoutModel.GetStream();
                    Assert.IsTrue(WritePayloadHelper.ReadStreamContent(stream).Contains("Person(-5)\",\"PersonId\":-5,\"Name\":\"xhsdckkeqzvlnprheujeycqrglfehtdocildrequohlffazfgtvmddyqsaxrojqxrsckohrakdxlrghgmzqnyruzu\""));
                }
            }
        }
        /// <summary>
        /// Reads the properties of an entity reference link.
        /// </summary>
        /// <param name="entityReferenceLinks">The <see cref="ODataEntityReferenceLinks"/> instance to set the read property values on.</param>
        /// <param name="propertiesFoundBitField">The bit field with all the properties already read.</param>
        /// <returns>true if the method found the 'results' property; otherwise false.</returns>
        private bool ReadEntityReferenceLinkProperties(
            ODataEntityReferenceLinks entityReferenceLinks,
            ref ODataJsonReaderUtils.EntityReferenceLinksWrapperPropertyBitMask propertiesFoundBitField)
        {
            Debug.Assert(entityReferenceLinks != null, "entityReferenceLinks != null");
            this.JsonReader.AssertNotBuffering();

            while (this.JsonReader.NodeType == JsonNodeType.Property)
            {
                string propertyName = this.JsonReader.ReadPropertyName();
                switch (propertyName)
                {
                    case JsonConstants.ODataResultsName:
                        ODataJsonReaderUtils.VerifyEntityReferenceLinksWrapperPropertyNotFound(
                            ref propertiesFoundBitField,
                            ODataJsonReaderUtils.EntityReferenceLinksWrapperPropertyBitMask.Results,
                            JsonConstants.ODataResultsName);
                        this.JsonReader.AssertNotBuffering();
                        return true;

                    case JsonConstants.ODataCountName:
                        ODataJsonReaderUtils.VerifyEntityReferenceLinksWrapperPropertyNotFound(
                            ref propertiesFoundBitField,
                            ODataJsonReaderUtils.EntityReferenceLinksWrapperPropertyBitMask.Count,
                            JsonConstants.ODataCountName);
                        object countValue = this.JsonReader.ReadPrimitiveValue();
                        long? count = (long?)ODataJsonReaderUtils.ConvertValue(countValue, EdmCoreModel.Instance.GetInt64(true), this.MessageReaderSettings, this.Version, /*validateNullValue*/ true);
                        ODataJsonReaderUtils.ValidateCountPropertyInEntityReferenceLinks(count);
                        entityReferenceLinks.Count = count;
                        break;

                    case JsonConstants.ODataNextLinkName:
                        ODataJsonReaderUtils.VerifyEntityReferenceLinksWrapperPropertyNotFound(
                            ref propertiesFoundBitField,
                            ODataJsonReaderUtils.EntityReferenceLinksWrapperPropertyBitMask.NextPageLink,
                            JsonConstants.ODataNextLinkName);
                        string nextLinkString = this.JsonReader.ReadStringValue(JsonConstants.ODataNextLinkName);
                        ODataJsonReaderUtils.ValidateEntityReferenceLinksStringProperty(nextLinkString, JsonConstants.ODataNextLinkName);
                        entityReferenceLinks.NextPageLink = this.ProcessUriFromPayload(nextLinkString);
                        break;

                    default:
                        // Skip all unrecognized properties
                        this.JsonReader.SkipValue();
                        break;
                }
            }

            this.JsonReader.AssertNotBuffering();
            return false;
        }
Ejemplo n.º 32
0
        public void EntityReferenceLinksTest()
        {
            string resultUri1String = "http://odata.org/linkresult1";
            string resultUri2String = "linkresult2";
            string resultUri3String = "http://odata.org/linkresult3";
            ODataEntityReferenceLink entityReferenceLink1 = new ODataEntityReferenceLink {
                Url = new Uri(resultUri1String)
            };
            ODataEntityReferenceLink entityReferenceLink2 = new ODataEntityReferenceLink {
                Url = new Uri(resultUri2String, UriKind.Relative)
            };
            ODataEntityReferenceLink entityReferenceLink3 = new ODataEntityReferenceLink {
                Url = new Uri(resultUri3String)
            };

            entityReferenceLink3.InstanceAnnotations.Add(new ODataInstanceAnnotation("TestModel.unknown", new ODataPrimitiveValue(123)));
            entityReferenceLink3.InstanceAnnotations.Add(new ODataInstanceAnnotation("custom.name", new ODataPrimitiveValue(456)));

            Uri nextPageLink         = new Uri("http://odata.org/nextpage");
            Uri relativeNextPageLink = new Uri("relative-nextpage", UriKind.Relative);

            long?[] inputCounts    = new long?[] { null, 1, 3, -1, -3, 0, long.MaxValue, long.MinValue };
            Uri[]   inputNextLinks = new Uri[] { nextPageLink, relativeNextPageLink, null };
            ODataInstanceAnnotation[][] inputAnnotations = new ODataInstanceAnnotation[][]
            {
                new ODataInstanceAnnotation[0],
                new ODataInstanceAnnotation[]
                {
                    new ODataInstanceAnnotation("TestModel.annotation", new ODataPrimitiveValue(321)),
                    new ODataInstanceAnnotation("custom.annotation", new ODataPrimitiveValue(654))
                }
            };
            ODataEntityReferenceLink[][] inputReferenceLinks = new ODataEntityReferenceLink[][]
            {
                new ODataEntityReferenceLink[] { entityReferenceLink1, entityReferenceLink2, entityReferenceLink3 },
                new ODataEntityReferenceLink[] { entityReferenceLink1, entityReferenceLink3 },
                new ODataEntityReferenceLink[] { entityReferenceLink1 },
                new ODataEntityReferenceLink[0],
                null
            };
            var testCases = inputCounts.SelectMany(
                inputCount => inputNextLinks.SelectMany(
                    inputNextLink => inputReferenceLinks.Select(
                        (inputReferenceLink, index) => new ODataEntityReferenceLinks {
                Count = inputCount, Links = inputReferenceLink, NextPageLink = inputNextLink, InstanceAnnotations = inputAnnotations[index == 1 ? 1 : 0]
            })));

            var testDescriptors = testCases.Select(
                testCase =>
                new PayloadWriterTestDescriptor <ODataEntityReferenceLinks>(this.Settings, testCase, this.CreateExpectedCallback(testCase, /*forceNextLinkAndCountAtEnd*/ false)));

            // TODO: also cover the cases in protocol v1 (errors for inline count and next page link; different format for JSON)
            this.CombinatorialEngineProvider.RunCombinations(
                testDescriptors,
                this.WriterTestConfigurationProvider.ExplicitFormatConfigurationsWithIndent,
                (testDescriptor, testConfiguration) =>
            {
                ODataEntityReferenceLinks entityReferenceLinks = testDescriptor.PayloadItems.Single();

                testConfiguration = testConfiguration.Clone();
                testConfiguration.MessageWriterSettings.SetServiceDocumentUri(ServiceDocumentUri);
                if (!testConfiguration.IsRequest)
                {
                    testConfiguration.MessageWriterSettings.ShouldIncludeAnnotation = ODataUtils.CreateAnnotationFilter("*");
                }

                // When writing JSON lite, always provide a model and a non-null nav prop.
                // The error cases when a model isn't provided or the nav prop is null are tested in JsonLightEntityReferenceLinkWriterTests
                if (testConfiguration.Format == ODataFormat.Json)
                {
                    testDescriptor.Model = CreateModelWithNavProps();
                    var edmModel         = testDescriptor.GetMetadataProvider();
                }

                TestWriterUtils.WriteAndVerifyTopLevelContent(
                    testDescriptor,
                    testConfiguration,
                    (messageWriter) => messageWriter.WriteEntityReferenceLinks(entityReferenceLinks),
                    this.Assert,
                    baselineLogger: this.Logger);
            });
        }
 private static void WriteAndValidate(ODataEntityReferenceLinks referencelinks, string expectedPayload, bool writingResponse = true, bool synchronous = true)
 {
     string payload = WriteToString(referencelinks, writingResponse, synchronous);
     Console.WriteLine(payload);
     Console.WriteLine(expectedPayload);
     payload.Should().Be(expectedPayload);
 }
Ejemplo n.º 34
0
        public void EntityReferenceLinksPropertyAccessOrderTest()
        {
            //// NOTE: this tests is important as Astoria relies on this behavior. Astoria only provides a next link after all the entity reference
            ////       links have been written so we must not access the next link before that point.

            ODataEntityReferenceLink entityReferenceLink1 = new ODataEntityReferenceLink {
                Url = new Uri("http://odata.org/linkresult1")
            };
            ODataEntityReferenceLink entityReferenceLink2 = new ODataEntityReferenceLink {
                Url = new Uri("http://odata.org/linkresult2")
            };
            ODataEntityReferenceLink entityReferenceLink3 = new ODataEntityReferenceLink {
                Url = new Uri("http://odata.org/linkresult3")
            };

            Uri  nextPageLink          = new Uri("http://odata.org/nextpage");
            Uri  incorrectNextPageLink = new Uri("http://odata.org/incorrectnextpage");
            long correctCountValue     = 3;

            // the expected result instance
            ODataEntityReferenceLinks expectedResult = new ODataEntityReferenceLinks
            {
                Count        = 3,
                Links        = new ODataEntityReferenceLink[] { entityReferenceLink1, entityReferenceLink2, entityReferenceLink3 },
                NextPageLink = nextPageLink
            };

            PayloadWriterTestDescriptor.WriterTestExpectedResultCallback expectedResultCallback = this.CreateExpectedCallback(expectedResult, /*forceNextLinkAndCountAtEnd*/ true);

            this.CombinatorialEngineProvider.RunCombinations(
                this.WriterTestConfigurationProvider.ExplicitFormatConfigurationsWithIndent.Where(tc => !tc.IsRequest),
                (testConfiguration) =>
            {
                testConfiguration = testConfiguration.Clone();
                testConfiguration.MessageWriterSettings.SetServiceDocumentUri(ServiceDocumentUri);

                // The instance with the proper inline count set but an incorrect next link; as we enumerate the links themselves
                // we will invalidate the inline count and set the correct next link to guarantee the correct order of property accesses
                // NOTE: we need to create this new for each iteration since the checking enumerable can (intentionally) only be enumerated once.
                ODataEntityReferenceLinks testReferenceLink = new ODataEntityReferenceLinks
                {
                    Count = correctCountValue,
                    // In JSON lite, we will write the next link first if one is available.  Otherwise, we'll write it at the end.
                    NextPageLink = testConfiguration.Format == ODataFormat.Json ? null : incorrectNextPageLink
                };
                testReferenceLink.Links = new CheckingEntityReferenceLinkEnumerable(
                    testReferenceLink,
                    correctCountValue,
                    nextPageLink /* correct next link */,
                    entityReferenceLink1,
                    entityReferenceLink2,
                    entityReferenceLink3);

                PayloadWriterTestDescriptor <ODataEntityReferenceLinks> testDescriptor =
                    new PayloadWriterTestDescriptor <ODataEntityReferenceLinks>(this.Settings, testReferenceLink, expectedResultCallback);

                IEdmNavigationProperty navProp = null;
                IEdmEntitySet entitySet        = null;
                // When writing JSON lite, always provide a model and a non-null nav prop.
                // The error cases when a model isn't provided or the nav prop is null are tested in JsonLightEntityReferenceLinkWriterTests
                if (testConfiguration.Format == ODataFormat.Json)
                {
                    testDescriptor.Model = CreateModelWithNavProps();
                    var edmModel         = testDescriptor.GetMetadataProvider();
                    navProp   = GetCollectionNavProp(edmModel);
                    entitySet = GetCollectionEntitySet(edmModel);
                }

                ODataEntityReferenceLinks entityReferenceLinks = testDescriptor.PayloadItems.Single();

                TestWriterUtils.WriteAndVerifyTopLevelContent(
                    testDescriptor,
                    testConfiguration,
                    (messageWriter) => messageWriter.WriteEntityReferenceLinks(entityReferenceLinks),
                    this.Assert,
                    baselineLogger: this.Logger);
            });
        }
 public void InstanceAnnotationsPropertyShouldNotBeNullAtCreation()
 {
     ODataEntityReferenceLinks referencelinks = new ODataEntityReferenceLinks();
     referencelinks.InstanceAnnotations.Should().NotBeNull();
     referencelinks.InstanceAnnotations.Count.Should().Be(0);
 }
Ejemplo n.º 36
0
        /// <summary>
        /// Creates the expected result callback for the provided <paramref name="entityReferenceLinks"/>.
        /// </summary>
        /// <param name="entityReferenceLinks">The entity reference links to create the expected result for.</param>
        /// <param name="forceNextLinkAndCountAtEnd">Whether the next link and count should be expected at the end of the payload for JSON lite.</param>
        /// <returns>The expected result callback for the <paramref name="entityReferenceLinks"/>.</returns>
        private WriterTestDescriptor.WriterTestExpectedResultCallback CreateExpectedCallback(ODataEntityReferenceLinks entityReferenceLinks, bool forceNextLinkAndCountAtEnd = false)
        {
            long?  count = entityReferenceLinks.Count;
            string nextPageLinkString = entityReferenceLinks.NextPageLink == null ? null : entityReferenceLinks.NextPageLink.OriginalString;

            return((testConfiguration) =>
            {
                ExpectedException expectedException = null;
                if (testConfiguration.IsRequest)
                {
                    // Top-level EntityReferenceLinks payload write requests are not allowed.
                    expectedException = ODataExpectedExceptions.ODataException("ODataMessageWriter_EntityReferenceLinksInRequestNotAllowed");
                }

                if (expectedException == null)
                {
                    ODataEntityReferenceLink relativeLink = entityReferenceLinks.Links == null ? null : entityReferenceLinks.Links.FirstOrDefault(l => !l.Url.IsAbsoluteUri);
                    bool nextPageLinkRelative = entityReferenceLinks.NextPageLink == null ? false : !entityReferenceLinks.NextPageLink.IsAbsoluteUri;
                    if ((relativeLink != null || nextPageLinkRelative) && testConfiguration.MessageWriterSettings.BaseUri == null)
                    {
                        // We allow relative Uri strings in JSON Light.
                        if (testConfiguration.Format != ODataFormat.Json)
                        {
                            string relativeUriString = relativeLink == null ? entityReferenceLinks.NextPageLink.OriginalString : relativeLink.Url.OriginalString;
                            expectedException = ODataExpectedExceptions.ODataException("ODataWriter_RelativeUriUsedWithoutBaseUriSpecified", relativeUriString);
                        }
                    }
                }

                if (expectedException != null)
                {
                    return new WriterTestExpectedResults(this.Settings.ExpectedResultSettings)
                    {
                        ExpectedException2 = expectedException
                    };
                }

                string[] resultUriStrings = entityReferenceLinks.Links == null ? null : entityReferenceLinks.Links.Select(l => GetResultUri(l.Url, testConfiguration)).ToArray();

                List <string> atomStrings = new List <string>();
                List <string> jsonLightStrings = new List <string>();
                string nextLinkString = null;

                jsonLightStrings.Add("{");
                var jsonLightFirstLine = "$(Indent)\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataContextAnnotationName + "\":\"http://odata.org/test/$metadata#Collection($ref)\",";

                if ((resultUriStrings == null || resultUriStrings.Length == 0) && !count.HasValue && nextPageLinkString == null && testConfiguration.Format != ODataFormat.Json)
                {
                    atomStrings.Add(@"<links xmlns=""http://docs.oasis-open.org/odata/ns/data"" />");
                }
                else
                {
                    atomStrings.Add(@"<links xmlns=""http://docs.oasis-open.org/odata/ns/data"">");
                    if (count.HasValue)
                    {
                        atomStrings.Add(@"<m:count xmlns:m=""" + TestAtomConstants.ODataMetadataNamespace + @""">" + count.Value + @"</m:count>");

                        if (!forceNextLinkAndCountAtEnd)
                        {
                            jsonLightFirstLine += "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataCountAnnotationName + "\":\"" + count.Value + "\",";
                        }
                    }

                    if (nextPageLinkString != null && !forceNextLinkAndCountAtEnd)
                    {
                        // In JSON lite, the next link comes at the beginning of the payload if available, but in JSON verbose and ATOM it comes at the end.
                        jsonLightFirstLine += "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataNextLinkAnnotationName + "\":\"" + nextPageLinkString + "\",";
                    }

                    jsonLightFirstLine += "\"value\":[";

                    jsonLightStrings.Add(jsonLightFirstLine);

                    int length = resultUriStrings == null ? 0 : resultUriStrings.Length;
                    if (length == 0)
                    {
                        jsonLightStrings.Add("$(Indent)$(Indent)");
                    }
                    else
                    {
                        for (int i = 0; i < length; ++i)
                        {
                            atomStrings.Add(@"<uri>" + resultUriStrings[i] + @"</uri>");
                            if (i == 0)
                            {
                                jsonLightStrings.Add("$(Indent)$(Indent){");
                            }
                            else
                            {
                                jsonLightStrings.Add("$(Indent)$(Indent)},{");
                            }

                            jsonLightStrings.Add("$(Indent)$(Indent)$(Indent)" + "\"url\":\"" + resultUriStrings[i] + "\"");

                            if (i == resultUriStrings.Length - 1)
                            {
                                jsonLightStrings.Add("$(Indent)$(Indent)}");
                            }
                        }
                    }

                    var jsonLightLastLine = "$(Indent)]";

                    if (count.HasValue && forceNextLinkAndCountAtEnd)
                    {
                        jsonLightLastLine += ",\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataCountAnnotationName + "\":" + count.Value;
                    }

                    if (nextPageLinkString != null)
                    {
                        atomStrings.Add(@"<next>" + nextPageLinkString + @"</next>");
                        nextLinkString = "\"__next\":\"" + nextPageLinkString + "\"";

                        if (forceNextLinkAndCountAtEnd)
                        {
                            jsonLightLastLine += ",\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataNextLinkAnnotationName + "\":\"" + nextPageLinkString + "\"";
                        }
                    }


                    jsonLightStrings.Add(jsonLightLastLine);
                    jsonLightStrings.Add("}");

                    atomStrings.Add(@"</links>");
                }

                if (testConfiguration.Format == ODataFormat.Json)
                {
                    return new JsonWriterTestExpectedResults(this.Settings.ExpectedResultSettings)
                    {
                        Json = string.Join("$(NL)", jsonLightStrings),
                        FragmentExtractor = (result) => result
                    };
                }
                else
                {
                    throw new TestInfrastructureException("Expected ATOM or JSON Lite.");
                }
            });
        }
 public void ShouldWriteForEntityReferenceLinksWithSingleLink()
 {
     ODataEntityReferenceLink link = new ODataEntityReferenceLink
     {
         Url = new Uri("http://host/Customers(1)")
     };
     link.InstanceAnnotations.Add(new ODataInstanceAnnotation("Is.New", new ODataPrimitiveValue(true)));
     ODataEntityReferenceLinks referencelinks = new ODataEntityReferenceLinks()
     {
         Links = new[] { link }
     };
     string expectedPayload = "{\"@odata.context\":\"http://odata.org/test/$metadata#Collection($ref)\",\"value\":[{\"@odata.id\":\"http://host/Customers(1)\",\"@Is.New\":true}]}";
     WriteAndValidate(referencelinks, expectedPayload, writingResponse: false);
     WriteAndValidate(referencelinks, expectedPayload, writingResponse: true);
 }
Ejemplo n.º 38
0
        /// <summary>
        /// Return the collection of links as ODataEntityReferenceLink instances
        /// </summary>
        /// <param name="elements">Elements whose uri need to be written out.</param>
        /// <param name="linksCollection">LinkCollection instance which represents the collection getting written out.</param>
        /// <returns>Return the collection of links as ODataEntityReferenceLink instances.</returns>
        private IEnumerable <ODataEntityReferenceLink> GetLinksCollection(QueryResultInfo elements, ODataEntityReferenceLinks linksCollection)
        {
            object          lastObject            = null;
            IExpandedResult lastExpandedSkipToken = null;

            while (elements.HasMoved)
            {
                object          element   = elements.Current;
                IExpandedResult skipToken = null;
                if (element != null)
                {
                    IExpandedResult expanded = element as IExpandedResult;
                    if (expanded != null)
                    {
                        element   = GetExpandedElement(expanded);
                        skipToken = this.GetSkipToken(expanded);
                    }
                }

                this.IncrementSegmentResultCount();
                yield return(new ODataEntityReferenceLink {
                    Url = this.GetEntityEditLink(element)
                });

                elements.MoveNext();
                lastObject            = element;
                lastExpandedSkipToken = skipToken;
            }

            if (this.NeedNextPageLink(elements))
            {
                linksCollection.NextPageLink = this.GetNextLinkUri(lastObject, lastExpandedSkipToken, this.RequestDescription.ResultUri);
                yield break;
            }
        }
Ejemplo n.º 39
0
        /// <summary>
        /// Reads the entity reference link instance annotations.
        /// </summary>
        /// <param name="links">The <see cref="ODataEntityReferenceLinks"/> to read the annotations for.</param>
        /// <param name="duplicatePropertyNamesChecker">The duplicate property names checker for the entity reference links scope.</param>
        /// <param name="forLinksStart">true when parsing the instance annotations before the 'value' property;
        /// false when parsing the instance annotations after the 'value' property.</param>
        /// <remarks>
        /// Pre-Condition:  JsonNodeType.Property               The first property in the payload (or the first property after the metadata URI in responses)
        ///                 JsonNodeType.EndObject              The end of the entity reference links object
        /// Post-Condition: JsonNodeType.EndObject              When the end of the entity reference links object is reached
        ///                 Any                                 The first node of the value of the 'url' property (if found)
        /// </remarks>
        private void ReadEntityReferenceLinksAnnotations(ODataEntityReferenceLinks links, DuplicatePropertyNamesChecker duplicatePropertyNamesChecker, bool forLinksStart)
        {
            Debug.Assert(links != null, "links != null");
            Debug.Assert(duplicatePropertyNamesChecker != null, "duplicatePropertyNamesChecker != null");
            this.AssertJsonCondition(JsonNodeType.Property, JsonNodeType.EndObject);
            this.JsonReader.AssertNotBuffering();

            while (this.JsonReader.NodeType == JsonNodeType.Property)
            {
                // OData property annotations are not supported on entity reference links.
                Func <string, object> propertyAnnotationValueReader =
                    annotationName => { throw new ODataException(ODataErrorStrings.ODataJsonLightEntityReferenceLinkDeserializer_PropertyAnnotationForEntityReferenceLinks); };

                bool foundValueProperty = false;
                this.ProcessProperty(
                    duplicatePropertyNamesChecker,
                    propertyAnnotationValueReader,
                    (propertyParseResult, propertyName) =>
                {
                    switch (propertyParseResult)
                    {
                    case PropertyParsingResult.ODataInstanceAnnotation:
                        if (string.CompareOrdinal(ODataAnnotationNames.ODataNextLink, propertyName) == 0)
                        {
                            this.ReadEntityReferenceLinksNextLinkAnnotationValue(links);
                        }
                        else if (string.CompareOrdinal(ODataAnnotationNames.ODataCount, propertyName) == 0)
                        {
                            this.ReadEntityReferenceCountAnnotationValue(links);
                        }
                        else
                        {
                            throw new ODataException(ODataErrorStrings.ODataJsonLightPropertyAndValueDeserializer_UnexpectedAnnotationProperties(propertyName));
                        }

                        break;

                    case PropertyParsingResult.CustomInstanceAnnotation:
                        this.JsonReader.SkipValue();
                        break;

                    case PropertyParsingResult.PropertyWithValue:
                        if (string.CompareOrdinal(JsonLightConstants.ODataValuePropertyName, propertyName) != 0)
                        {
                            // We did not find a supported link collection property; fail.
                            throw new ODataException(ODataErrorStrings.ODataJsonLightEntityReferenceLinkDeserializer_InvalidEntityReferenceLinksPropertyFound(propertyName, JsonLightConstants.ODataValuePropertyName));
                        }

                        // We found the link collection property and are done parsing property annotations;
                        foundValueProperty = true;
                        break;

                    case PropertyParsingResult.PropertyWithoutValue:
                        // If we find a property without a value it means that we did not find the entity reference links property (yet)
                        // but an invalid property annotation
                        throw new ODataException(ODataErrorStrings.ODataJsonLightEntityReferenceLinkDeserializer_InvalidPropertyAnnotationInEntityReferenceLinks(propertyName));

                    case PropertyParsingResult.EndOfObject:
                        break;

                    case PropertyParsingResult.MetadataReferenceProperty:
                        throw new ODataException(ODataErrorStrings.ODataJsonLightPropertyAndValueDeserializer_UnexpectedMetadataReferenceProperty(propertyName));

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

                if (foundValueProperty)
                {
                    return;
                }
            }

            if (forLinksStart)
            {
                // We did not find the 'value' property.
                throw new ODataException(ODataErrorStrings.ODataJsonLightEntityReferenceLinkDeserializer_ExpectedEntityReferenceLinksPropertyNotFound(JsonLightConstants.ODataValuePropertyName));
            }

            this.AssertJsonCondition(JsonNodeType.EndObject);
        }
Ejemplo n.º 40
0
        /// <summary>
        /// Visits an item in the object model.
        /// </summary>
        /// <param name="objectModelItem">The item to visit.</param>
        public virtual void Visit(object objectModelItem)
        {
            ODataResourceSet resourceCollection = objectModelItem as ODataResourceSet;

            if (resourceCollection != null)
            {
                this.VisitFeed(resourceCollection);
                return;
            }

            ODataResource entry = objectModelItem as ODataResource;

            if (entry != null)
            {
                this.VisitEntry(entry);
                return;
            }

            ODataProperty property = objectModelItem as ODataProperty;

            if (property != null)
            {
                this.VisitProperty(property);
                return;
            }

            ODataNestedResourceInfo navigationLink = objectModelItem as ODataNestedResourceInfo;

            if (navigationLink != null)
            {
                this.VisitNavigationLink(navigationLink);
                return;
            }

            ODataResourceValue resourceValue = objectModelItem as ODataResourceValue;

            if (resourceValue != null)
            {
                this.VisitResourceValue(resourceValue);
                return;
            }

            ODataCollectionValue collectionValue = objectModelItem as ODataCollectionValue;

            if (collectionValue != null)
            {
                this.VisitCollectionValue(collectionValue);
                return;
            }

            ODataStreamReferenceValue streamReferenceValue = objectModelItem as ODataStreamReferenceValue;

            if (streamReferenceValue != null)
            {
                this.VisitStreamReferenceValue(streamReferenceValue);
                return;
            }

            ODataCollectionStart collectionStart = objectModelItem as ODataCollectionStart;

            if (collectionStart != null)
            {
                this.VisitCollectionStart(collectionStart);
                return;
            }

            ODataServiceDocument serviceDocument = objectModelItem as ODataServiceDocument;

            if (serviceDocument != null)
            {
                this.VisitServiceDocument(serviceDocument);
                return;
            }

            ODataEntitySetInfo entitySetInfo = objectModelItem as ODataEntitySetInfo;

            if (entitySetInfo != null)
            {
                this.VisitEntitySet(entitySetInfo);
                return;
            }

            ODataError error = objectModelItem as ODataError;

            if (error != null)
            {
                this.VisitError(error);
                return;
            }

            ODataInnerError innerError = objectModelItem as ODataInnerError;

            if (innerError != null)
            {
                this.VisitInnerError(innerError);
                return;
            }

            ODataEntityReferenceLinks entityReferenceLinks = objectModelItem as ODataEntityReferenceLinks;

            if (entityReferenceLinks != null)
            {
                this.VisitEntityReferenceLinks(entityReferenceLinks);
                return;
            }

            ODataEntityReferenceLink entityReferenceLink = objectModelItem as ODataEntityReferenceLink;

            if (entityReferenceLink != null)
            {
                this.VisitEntityReferenceLink(entityReferenceLink);
                return;
            }

            ODataAction action = objectModelItem as ODataAction;

            if (action != null)
            {
                this.VisitODataOperation(action);
                return;
            }

            ODataFunction function = objectModelItem as ODataFunction;

            if (function != null)
            {
                this.VisitODataOperation(function);
                return;
            }

            ODataParameters parameters = objectModelItem as ODataParameters;

            if (parameters != null)
            {
                this.VisitParameters(parameters);
                return;
            }

            ODataBatch batch = objectModelItem as ODataBatch;

            if (batch != null)
            {
                this.VisitBatch(batch);
                return;
            }

            ODataBatchChangeset batchChangeset = objectModelItem as ODataBatchChangeset;

            if (batchChangeset != null)
            {
                this.VisitBatchChangeset(batchChangeset);
                return;
            }

            ODataBatchRequestOperation batchRequestOperation = objectModelItem as ODataBatchRequestOperation;

            if (batchRequestOperation != null)
            {
                this.VisitBatchRequestOperation(batchRequestOperation);
                return;
            }

            ODataBatchResponseOperation batchResponseOperation = objectModelItem as ODataBatchResponseOperation;

            if (batchResponseOperation != null)
            {
                this.VisitBatchResponseOperation(batchResponseOperation);
                return;
            }

            if (objectModelItem == null || objectModelItem.GetType().IsValueType || objectModelItem is string ||
                objectModelItem is byte[] || objectModelItem is ISpatial)
            {
                this.VisitPrimitiveValue(objectModelItem);
                return;
            }

            if (objectModelItem is ODataUntypedValue)
            {
                this.VisitPrimitiveValue(ParseJsonToPrimitiveValue((objectModelItem as ODataUntypedValue).RawValue));
                return;
            }

            this.VisitUnsupportedValue(objectModelItem);
        }
        /// <summary>
        /// Reads all top-level entity reference links and the (optional) inline count and next link elements.
        /// </summary>
        /// <returns>An <see cref="ODataEntityReferenceLinks"/> instance representing the read entity reference links.</returns>
        /// <remarks>
        /// Pre-Condition:  XmlNodeType.Element - The 'feed' element.
        /// Post-Condition:  any                - The node after the 'feed' end element (or empty 'feed' element).
        /// </remarks>
        private ODataEntityReferenceLinks ReadFeedElement()
        {
            Debug.Assert(this.XmlReader != null, "this.XmlReader != null");
            this.AssertXmlCondition(XmlNodeType.Element);
            Debug.Assert(this.XmlReader.NamespaceURI == AtomConstants.AtomNamespace, "this.XmlReader.NamespaceURI == AtomConstants.AtomNamespace");
            Debug.Assert(this.XmlReader.LocalName == this.ODataFeedElementName, "this.XmlReader.LocalName == AtomConstants.ODataLinksElementName");

            ODataEntityReferenceLinks                   links               = new ODataEntityReferenceLinks();
            List <ODataEntityReferenceLink>             linkList            = new List <ODataEntityReferenceLink>();
            DuplicateEntityReferenceLinksElementBitMask elementsReadBitmask = DuplicateEntityReferenceLinksElementBitMask.None;

            if (!this.XmlReader.IsEmptyElement)
            {
                // Move to the first child node of the element.
                this.XmlReader.Read();

                do
                {
                    switch (this.XmlReader.NodeType)
                    {
                    case XmlNodeType.EndElement:
                        // end of the <feed> element
                        continue;

                    case XmlNodeType.Element:
                        // <m:count>
                        if (this.XmlReader.NamespaceEquals(this.XmlReader.ODataMetadataNamespace) &&
                            this.XmlReader.LocalNameEquals(this.ODataCountElementName))
                        {
                            VerifyEntityReferenceLinksElementNotFound(
                                ref elementsReadBitmask,
                                DuplicateEntityReferenceLinksElementBitMask.Count,
                                this.XmlReader.ODataMetadataNamespace,
                                AtomConstants.ODataCountElementName);

                            // Note that we allow negative values to be read.
                            long countValue = (long)AtomValueUtils.ReadPrimitiveValue(this.XmlReader, EdmCoreModel.Instance.GetInt64(false));
                            links.Count = countValue;

                            // Read over the end element of the <m:count> element
                            this.XmlReader.Read();

                            continue;
                        }

                        // <m:ref>
                        if (this.XmlReader.NamespaceEquals(this.XmlReader.ODataMetadataNamespace) &&
                            this.XmlReader.LocalNameEquals(this.ODataRefElementName))
                        {
                            ODataEntityReferenceLink link = this.ReadEntityReferenceId();
                            linkList.Add(link);

                            continue;
                        }

                        // <d:next>
                        if (this.XmlReader.NamespaceEquals(this.XmlReader.ODataNamespace) &&
                            this.XmlReader.LocalNameEquals(this.ODataNextElementName))
                        {
                            VerifyEntityReferenceLinksElementNotFound(
                                ref elementsReadBitmask,
                                DuplicateEntityReferenceLinksElementBitMask.NextLink,
                                this.XmlReader.ODataNamespace,
                                AtomConstants.ODataNextLinkElementName);

                            // NOTE: get the base URI here before we read the content as string; reading the content as string will move the
                            //       reader to the end element and thus we lose the xml:base definition on the element.
                            Uri    xmlBaseUri = this.XmlReader.XmlBaseUri;
                            string uriString  = this.XmlReader.ReadElementValue();
                            links.NextPageLink = this.ProcessUriFromPayload(uriString, xmlBaseUri);

                            continue;
                        }

                        break;

                    default:
                        break;
                    }

                    this.XmlReader.Skip();
                }while (this.XmlReader.NodeType != XmlNodeType.EndElement);
            }

            // Read over the end element, or empty start element.
            this.XmlReader.Read();

            links.Links = new ReadOnlyEnumerable <ODataEntityReferenceLink>(linkList);
            return(links);
        }
Ejemplo n.º 42
0
        public void EntityReferenceLinkValidationTest()
        {
            var testCases = new[] {
                new {
                    InvalidateEntityReferenceLink = new Action <ODataEntityReferenceLink>(entityReferenceLink => entityReferenceLink.Url = null),
                    ExpectedException             = ODataExpectedExceptions.ODataException("WriterValidationUtils_EntityReferenceLinkUrlMustNotBeNull"),
                },
            };

            var testDescriptors = testCases.SelectMany(testCase =>
            {
                ODataEntityReferenceLink entityReferenceLink = ObjectModelUtils.CreateDefaultEntityReferenceLink();
                testCase.InvalidateEntityReferenceLink(entityReferenceLink);
                ODataEntityReferenceLinks entityReferenceLinks = ObjectModelUtils.CreateDefaultEntityReferenceLinks();
                testCase.InvalidateEntityReferenceLink(entityReferenceLinks.Links.First());

                return(new PayloadWriterTestDescriptor[]
                {
                    // Top level entity reference link
                    new PayloadWriterTestDescriptor <ODataEntityReferenceLink>(
                        this.Settings,
                        entityReferenceLink,
                        testConfiguration => new WriterTestExpectedResults(this.Settings.ExpectedResultSettings)
                    {
                        ExpectedException2 = testCase.ExpectedException
                    }),
                    // Entity reference link in entity reference links
                    new PayloadWriterTestDescriptor <ODataEntityReferenceLinks>(
                        this.Settings,
                        entityReferenceLinks,
                        testConfiguration => new WriterTestExpectedResults(this.Settings.ExpectedResultSettings)
                    {
                        // Top-level EntityReferenceLinks payload write requests are not allowed.
                        ExpectedException2 = testConfiguration.IsRequest ?
                                             ODataExpectedExceptions.ODataException("ODataMessageWriter_EntityReferenceLinksInRequestNotAllowed") : testCase.ExpectedException
                    }),
                    new PayloadWriterTestDescriptor <ODataItem>(
                        this.Settings,
                        new ODataItem[] { ObjectModelUtils.CreateDefaultEntry(), ObjectModelUtils.CreateDefaultSingletonLink(), entityReferenceLink, null, null },
                        testConfiguration => new WriterTestExpectedResults(this.Settings.ExpectedResultSettings)
                    {
                        ExpectedException2 = testConfiguration.IsRequest ? testCase.ExpectedException : ODataExpectedExceptions.ODataException("ODataWriterCore_EntityReferenceLinkInResponse")
                    }),
                });
            });

            this.CombinatorialEngineProvider.RunCombinations(
                testDescriptors,
                this.WriterTestConfigurationProvider.AtomFormatConfigurations,
                (testDescriptor, testConfiguration) =>
            {
                testConfiguration = testConfiguration.Clone();
                testConfiguration.MessageWriterSettings.SetServiceDocumentUri(ServiceDocumentUri);

                PayloadWriterTestDescriptor <ODataEntityReferenceLink> entityReferenceLinkTestDescriptor = testDescriptor as PayloadWriterTestDescriptor <ODataEntityReferenceLink>;
                if (entityReferenceLinkTestDescriptor != null)
                {
                    TestWriterUtils.WriteAndVerifyTopLevelContent(
                        entityReferenceLinkTestDescriptor,
                        testConfiguration,
                        (messageWriter) => messageWriter.WriteEntityReferenceLink(entityReferenceLinkTestDescriptor.PayloadItems.Single()),
                        this.Assert,
                        baselineLogger: this.Logger);
                    return;
                }

                PayloadWriterTestDescriptor <ODataEntityReferenceLinks> entityReferenceLinksTestDescriptor = testDescriptor as PayloadWriterTestDescriptor <ODataEntityReferenceLinks>;
                if (entityReferenceLinksTestDescriptor != null)
                {
                    TestWriterUtils.WriteAndVerifyTopLevelContent(
                        entityReferenceLinksTestDescriptor,
                        testConfiguration,
                        (messageWriter) => messageWriter.WriteEntityReferenceLinks(entityReferenceLinksTestDescriptor.PayloadItems.Single()),
                        this.Assert,
                        baselineLogger: this.Logger);
                    return;
                }

                TestWriterUtils.WriteAndVerifyODataPayload((PayloadWriterTestDescriptor <ODataItem>)testDescriptor, testConfiguration, this.Assert, this.Logger);
            });
        }
        /// <summary>
        /// Writes the result of a $ref query as the message payload.
        /// </summary>
        /// <param name="links">The entity reference links to write as message payload.</param>
        private void WriteEntityReferenceLinksImplementation(ODataEntityReferenceLinks links)
        {
            ODataAtomEntityReferenceLinkSerializer atomEntityReferenceLinkSerializer = new ODataAtomEntityReferenceLinkSerializer(this);

            atomEntityReferenceLinkSerializer.WriteEntityReferenceLinks(links);
        }
 public void ShouldReadForEntityReferenceLinksWithSingleLink()
 {
     ODataEntityReferenceLink link = new ODataEntityReferenceLink
     {
         Url = new Uri("http://host/Customers(1)")
     };
     link.InstanceAnnotations.Add(new ODataInstanceAnnotation("Is.New", new ODataPrimitiveValue(true)));
     ODataEntityReferenceLinks referencelinks = new ODataEntityReferenceLinks()
     {
         Links = new[] { link }
     };
     var deserializer = this.CreateJsonLightEntryAndFeedDeserializer("{\"@odata.context\":\"http://odata.org/test/$metadata#Collection($ref)\",\"value\":[{\"@odata.id\":\"http://host/Customers(1)\",\"@Is.New\":true}]}");
     ODataEntityReferenceLinks links = deserializer.ReadEntityReferenceLinks();
     SameEntityReferenceLinks(referencelinks, links);
 }
Ejemplo n.º 45
0
 /// <summary>
 /// Visits an entity reference link collection.
 /// </summary>
 /// <param name="entityReferenceLinks">The entity reference link collection to visit.</param>
 protected abstract T VisitEntityReferenceLinks(ODataEntityReferenceLinks entityReferenceLinks);
        public void ShouldReadForEntityReferenceLinksWithReferenceLinksAnnotations()
        {
            ODataEntityReferenceLink link1 = new ODataEntityReferenceLink
            {
                Url = new Uri("http://host/Customers(1)")
            };
            link1.InstanceAnnotations.Add(new ODataInstanceAnnotation("Is.New", new ODataPrimitiveValue(true)));
            ODataEntityReferenceLink link2 = new ODataEntityReferenceLink
            {
                Url = new Uri("http://host/Customers(2)")
            };
            link2.InstanceAnnotations.Add(new ODataInstanceAnnotation("TestNamespace.unknown", new ODataPrimitiveValue(123)));
            link2.InstanceAnnotations.Add(new ODataInstanceAnnotation("custom.annotation", new ODataPrimitiveValue(456)));

            ODataEntityReferenceLinks referencelinks = new ODataEntityReferenceLinks()
            {
                Links = new[] { link1, link2 }
            };

            referencelinks.InstanceAnnotations.Add(new ODataInstanceAnnotation("TestNamespace.name", new ODataPrimitiveValue(321)));
            referencelinks.InstanceAnnotations.Add(new ODataInstanceAnnotation("custom.name", new ODataPrimitiveValue(654)));
            string payload = "{\"@odata.context\":\"http://odata.org/test/$metadata#Collection($ref)\",\"@TestNamespace.name\":321,\"value\":[{\"@odata.id\":\"http://host/Customers(1)\",\"@Is.New\":true},{\"@odata.id\":\"http://host/Customers(2)\",\"@TestNamespace.unknown\":123,\"@custom.annotation\":456}],\"@custom.name\":654}";
   
            var deserializer = this.CreateJsonLightEntryAndFeedDeserializer(payload);
            ODataEntityReferenceLinks links = deserializer.ReadEntityReferenceLinks();
            SameEntityReferenceLinks(referencelinks, links);
        }
Ejemplo n.º 47
0
        public override void Process(IODataRequestMessage requestMessage, IODataResponseMessage responseMessage)
        {
            if (this.TryDispatch(requestMessage, responseMessage))
            {
                return;
            }

            this.QueryContext.InitializeServerDrivenPaging(this.PreferenceContext);
            this.QueryContext.InitializeTrackingChanges(this.PreferenceContext);

            object queryResults = this.QueryContext.ResolveQuery(this.DataSource);

            if (queryResults == null)
            {
                // For individual property or $value
                if (this.QueryContext.Target.Property != null)
                {
                    // Protocol 9.1.4 Response Code 204 No Content
                    // A request returns 204 No Content if the requested resource has the null value,
                    // or if the service applies a return=minimal preference. In this case, the response body MUST be empty.
                    ResponseWriter.WriteEmptyResponse(responseMessage);

                    return;
                }
                else
                {
                    throw Utility.BuildException(HttpStatusCode.NotFound);
                }
            }

            // Handle the prefer of "odata.include-annotations", including it in response header
            if (!string.IsNullOrEmpty(this.PreferenceContext.IncludeAnnotations))
            {
                responseMessage.AddPreferenceApplied(string.Format("{0}={1}",
                                                                   ServiceConstants.Preference_IncludeAnnotations, this.PreferenceContext.IncludeAnnotations));
            }

            if (this.PreferenceContext.MaxPageSize.HasValue)
            {
                responseMessage.AddPreferenceApplied(string.Format("{0}={1}", ServiceConstants.Preference_MaxPageSize, this.QueryContext.appliedPageSize.Value));
            }

            if (this.PreferenceContext.TrackingChanges)
            {
                responseMessage.AddPreferenceApplied(ServiceConstants.Preference_TrackChanging);
            }

            responseMessage.SetStatusCode(HttpStatusCode.OK);

            using (var messageWriter = this.CreateMessageWriter(responseMessage))
            {
                IEdmNavigationSource navigationSource   = this.QueryContext.Target.NavigationSource;
                IEnumerable          iEnumerableResults = queryResults as IEnumerable;

                if (this.QueryContext.Target.IsReference && this.QueryContext.Target.TypeKind == EdmTypeKind.Collection)
                {
                    // Query a $ref collection
                    IList <ODataEntityReferenceLink> links = new List <ODataEntityReferenceLink>();

                    foreach (var iEnumerableResult in iEnumerableResults)
                    {
                        var link = new ODataEntityReferenceLink
                        {
                            Url = Utility.BuildLocationUri(this.QueryContext, iEnumerableResult),
                        };
                        links.Add(link);
                    }

                    ODataEntityReferenceLinks linksCollection = new ODataEntityReferenceLinks()
                    {
                        Links = links, NextPageLink = this.QueryContext.NextLink
                    };
                    messageWriter.WriteEntityReferenceLinks(linksCollection);
                }
                else if (this.QueryContext.Target.IsReference && this.QueryContext.Target.TypeKind == EdmTypeKind.Entity)
                {
                    // Query a $ref
                    var link = new ODataEntityReferenceLink
                    {
                        Url = Utility.BuildLocationUri(this.QueryContext, queryResults),
                    };

                    messageWriter.WriteEntityReferenceLink(link);
                }
                else if (this.QueryContext.Target.NavigationSource != null && this.QueryContext.Target.TypeKind == EdmTypeKind.Collection)
                {
                    // Query a feed
                    IEdmEntitySetBase entitySet  = navigationSource as IEdmEntitySetBase;
                    IEdmEntityType    entityType = this.QueryContext.Target.ElementType as IEdmEntityType;

                    if (entitySet == null || entityType == null)
                    {
                        throw new InvalidOperationException("Invalid target when query feed.");
                    }

                    ODataWriter resultWriter = messageWriter.CreateODataFeedWriter(entitySet, entityType);

                    ResponseWriter.WriteFeed(resultWriter, iEnumerableResults, entitySet, ODataVersion.V4, this.QueryContext.QuerySelectExpandClause, this.QueryContext.TotalCount, this.QueryContext.DeltaLink, this.QueryContext.NextLink, this.RequestHeaders);
                    resultWriter.Flush();
                }
                else if (this.QueryContext.Target.NavigationSource != null && this.QueryContext.Target.TypeKind == EdmTypeKind.Entity)
                {
                    var currentETag = Utility.GetETagValue(queryResults);
                    // if the current entity has ETag field
                    if (currentETag != null)
                    {
                        string requestETag;
                        if (Utility.TryGetIfNoneMatch(this.RequestHeaders, out requestETag) && (requestETag == ServiceConstants.ETagValueAsterisk || requestETag == currentETag))
                        {
                            ResponseWriter.WriteEmptyResponse(responseMessage, HttpStatusCode.NotModified);
                            return;
                        }

                        responseMessage.SetHeader(ServiceConstants.HttpHeaders.ETag, currentETag);
                    }

                    // Query a single entity
                    IEdmEntityType entityType = this.QueryContext.Target.Type as IEdmEntityType;

                    ODataWriter resultWriter = messageWriter.CreateODataEntryWriter(navigationSource, entityType);
                    ResponseWriter.WriteEntry(resultWriter, queryResults, navigationSource, ODataVersion.V4, this.QueryContext.QuerySelectExpandClause, this.RequestHeaders);
                    resultWriter.Flush();
                }
                else if (this.QueryContext.Target.Property != null && !this.QueryContext.Target.IsRawValue)
                {
                    // Query a individual property
                    ODataProperty property = ODataObjectModelConverter.CreateODataProperty(queryResults, this.QueryContext.Target.Property.Name);
                    messageWriter.WriteProperty(property);
                }
                else if (this.QueryContext.Target.IsRawValue)
                {
                    // Query a $value or $count
                    var propertyValue = ODataObjectModelConverter.CreateODataValue(queryResults);
                    messageWriter.WriteValue(propertyValue);
                }
                else
                {
                    throw Utility.BuildException(HttpStatusCode.NotImplemented);
                }
            }
        }
        /// <summary>
        /// Reads all top-level entity reference links and the (optional) inline count and next link elements.
        /// </summary>
        /// <returns>An <see cref="ODataEntityReferenceLinks"/> instance representing the read entity reference links.</returns>
        /// <remarks>
        /// Pre-Condition:  XmlNodeType.Element - The 'feed' element.
        /// Post-Condition:  any                - The node after the 'feed' end element (or empty 'feed' element).
        /// </remarks>
        private ODataEntityReferenceLinks ReadFeedElement()
        {
            Debug.Assert(this.XmlReader != null, "this.XmlReader != null");
            this.AssertXmlCondition(XmlNodeType.Element);
            Debug.Assert(this.XmlReader.NamespaceURI == AtomConstants.AtomNamespace, "this.XmlReader.NamespaceURI == AtomConstants.AtomNamespace");
            Debug.Assert(this.XmlReader.LocalName == this.ODataFeedElementName, "this.XmlReader.LocalName == AtomConstants.ODataLinksElementName");

            ODataEntityReferenceLinks links = new ODataEntityReferenceLinks();
            List<ODataEntityReferenceLink> linkList = new List<ODataEntityReferenceLink>();
            DuplicateEntityReferenceLinksElementBitMask elementsReadBitmask = DuplicateEntityReferenceLinksElementBitMask.None;

            if (!this.XmlReader.IsEmptyElement)
            {
                // Move to the first child node of the element.
                this.XmlReader.Read();

                do
                {
                    switch (this.XmlReader.NodeType)
                    {
                        case XmlNodeType.EndElement:
                            // end of the <feed> element
                            continue;

                        case XmlNodeType.Element:
                            // <m:count>
                            if (this.XmlReader.NamespaceEquals(this.XmlReader.ODataMetadataNamespace) &&
                                this.XmlReader.LocalNameEquals(this.ODataCountElementName))
                            {
                                VerifyEntityReferenceLinksElementNotFound(
                                    ref elementsReadBitmask,
                                    DuplicateEntityReferenceLinksElementBitMask.Count,
                                    this.XmlReader.ODataMetadataNamespace,
                                    AtomConstants.ODataCountElementName);

                                // Note that we allow negative values to be read.
                                long countValue = (long)AtomValueUtils.ReadPrimitiveValue(this.XmlReader, EdmCoreModel.Instance.GetInt64(false));
                                links.Count = countValue;

                                // Read over the end element of the <m:count> element
                                this.XmlReader.Read();

                                continue;
                            }

                            // <m:ref>
                            if (this.XmlReader.NamespaceEquals(this.XmlReader.ODataMetadataNamespace)
                                && this.XmlReader.LocalNameEquals(this.ODataRefElementName))
                            {
                                ODataEntityReferenceLink link = this.ReadEntityReferenceId();
                                linkList.Add(link);

                                continue;
                            }

                            // <d:next>
                            if (this.XmlReader.NamespaceEquals(this.XmlReader.ODataNamespace)
                                && this.XmlReader.LocalNameEquals(this.ODataNextElementName))
                            {
                                VerifyEntityReferenceLinksElementNotFound(
                                    ref elementsReadBitmask,
                                    DuplicateEntityReferenceLinksElementBitMask.NextLink,
                                    this.XmlReader.ODataNamespace,
                                    AtomConstants.ODataNextLinkElementName);

                                // NOTE: get the base URI here before we read the content as string; reading the content as string will move the 
                                //       reader to the end element and thus we lose the xml:base definition on the element.
                                Uri xmlBaseUri = this.XmlReader.XmlBaseUri;
                                string uriString = this.XmlReader.ReadElementValue();
                                links.NextPageLink = this.ProcessUriFromPayload(uriString, xmlBaseUri);

                                continue;
                            }

                            break;
                        default:
                            break;
                    }

                    this.XmlReader.Skip();
                }
                while (this.XmlReader.NodeType != XmlNodeType.EndElement);
            }

            // Read over the end element, or empty start element.
            this.XmlReader.Read();

            links.Links = new ReadOnlyEnumerable<ODataEntityReferenceLink>(linkList);
            return links;
        }
Ejemplo n.º 49
0
        /// <summary>
        /// Writes the result of a $ref query as the message payload.
        /// </summary>
        /// <param name="links">The entity reference links to write as message payload.</param>
        private void WriteEntityReferenceLinksImplementation(ODataEntityReferenceLinks links)
        {
            ODataJsonLightEntityReferenceLinkSerializer jsonLightEntityReferenceLinkSerializer = new ODataJsonLightEntityReferenceLinkSerializer(this);

            jsonLightEntityReferenceLinkSerializer.WriteEntityReferenceLinks(links);
        }
        /// <summary>
        /// Asynchronously writes the result of a $ref query as the message payload.
        /// </summary>
        /// <param name="links">The entity reference links to write as message payload.</param>
        /// <returns>A task representing the asynchronous writing of the entity reference links.</returns>
        /// <remarks>It is the responsibility of this method to flush the output before the task finishes.</remarks>
        internal override Task WriteEntityReferenceLinksAsync(ODataEntityReferenceLinks links)
        {
            this.AssertAsynchronous();

            return TaskUtils.GetTaskForSynchronousOperationReturningTask(
                () =>
                {
                    this.WriteEntityReferenceLinksImplementation(links);
                    return this.FlushAsync();
                });
        }
Ejemplo n.º 51
0
        /// <summary>
        /// Writes the result of a $links query as the message payload.
        /// </summary>
        /// <param name="links">The entity reference links to write as message payload.</param>
        /// <remarks>It is the responsibility of this method to flush the output before the method returns.</remarks>
        internal override void WriteEntityReferenceLinks(ODataEntityReferenceLinks links)
        {
            DebugUtils.CheckNoExternalCallers();
            this.AssertSynchronous();

            this.WriteEntityReferenceLinksImplementation(links);
            this.Flush();
        }
Ejemplo n.º 52
0
 private void WriteEntityReferenceLinksImplementation(ODataEntityReferenceLinks links)
 {
     new ODataJsonEntityReferenceLinkSerializer(this).WriteEntityReferenceLinks(links);
 }
        public void WriteForEntityReferenceLinksWithDuplicateAnnotationNameShouldThrow()
        {
            ODataEntityReferenceLink link1 = new ODataEntityReferenceLink
            {
                Url = new Uri("http://host/Customers(1)")
            };
            link1.InstanceAnnotations.Add(new ODataInstanceAnnotation("Is.New", new ODataPrimitiveValue(true)));
            ODataEntityReferenceLink link2 = new ODataEntityReferenceLink
            {
                Url = new Uri("http://host/Customers(2)")
            };
            link2.InstanceAnnotations.Add(new ODataInstanceAnnotation("TestNamespace.unknown", new ODataPrimitiveValue(123)));
            link2.InstanceAnnotations.Add(new ODataInstanceAnnotation("custom.annotation", new ODataPrimitiveValue(456)));

            ODataEntityReferenceLinks referencelinks = new ODataEntityReferenceLinks()
            {
                Links = new[] { link1, link2 }
            };

            referencelinks.InstanceAnnotations.Add(new ODataInstanceAnnotation("TestNamespace.name", new ODataPrimitiveValue(321)));
            referencelinks.InstanceAnnotations.Add(new ODataInstanceAnnotation("TestNamespace.name", new ODataPrimitiveValue(654)));
            string expectedPayload = "{\"@odata.context\":\"http://odata.org/test/$metadata#Collection($ref)\",\"@TestNamespace.name\":321,\"@TestNamespace.name\":654,\"value\":[{\"@odata.id\":\"http://host/Customers(1)\",\"@Is.New\":true},{\"@odata.id\":\"http://host/Customers(2)\",\"@TestNamespace.unknown\":123,\"@custom.annotation\":456}]}";
            Action writeResult = () => WriteAndValidate(referencelinks, expectedPayload, writingResponse: false);
            writeResult.ShouldThrow<ODataException>().WithMessage(ODataErrorStrings.JsonLightInstanceAnnotationWriter_DuplicateAnnotationNameInCollection("TestNamespace.name"));
            writeResult = () => WriteAndValidate(referencelinks, expectedPayload, writingResponse: true);
            writeResult.ShouldThrow<ODataException>().WithMessage(ODataErrorStrings.JsonLightInstanceAnnotationWriter_DuplicateAnnotationNameInCollection("TestNamespace.name"));
        }
Ejemplo n.º 54
0
        public void WriteEntryWithWrongSerializationInfo()
        {
            foreach (var mimeType in this.testMimeTypes)
            {
                var settings = new ODataMessageWriterSettings();
                settings.ODataUri = new ODataUri()
                {
                    ServiceRoot = this.ServiceUri
                };

                // wrong EntitySetName for entry
                var responseMessageWithoutModel = new StreamResponseMessage(new MemoryStream());
                responseMessageWithoutModel.SetHeader("Content-Type", mimeType);
                using (var messageWriter = new ODataMessageWriter(responseMessageWithoutModel, settings))
                {
                    var odataWriter = messageWriter.CreateODataEntryWriter();
                    var entry       = this.CreatePersonEntryWithoutSerializationInfo();

                    entry.SetSerializationInfo(new ODataFeedAndEntrySerializationInfo()
                    {
                        NavigationSourceName = "Parsen", NavigationSourceEntityTypeName = NameSpace + "Person"
                    });
                    odataWriter.WriteStart(entry);
                    odataWriter.WriteEnd();
                    var result = WritePayloadHelper.ReadStreamContent(responseMessageWithoutModel.GetStream());
                    Assert.IsTrue(result.Contains("Person(-5)\",\"PersonId\":-5"));
                    if (!mimeType.Contains(MimeTypes.ODataParameterNoMetadata))
                    {
                        // no metadata does not write odata.metadata
                        Assert.IsTrue(result.Contains("$metadata#Parsen/$entity"));
                    }
                }

                // wrong EntitySetName for feed
                responseMessageWithoutModel = new StreamResponseMessage(new MemoryStream());
                responseMessageWithoutModel.SetHeader("Content-Type", mimeType);
                using (var messageWriter = new ODataMessageWriter(responseMessageWithoutModel, settings))
                {
                    var odataWriter = messageWriter.CreateODataFeedWriter();

                    var feed = this.CreatePersonFeed();
                    feed.SetSerializationInfo(new ODataFeedAndEntrySerializationInfo()
                    {
                        NavigationSourceName = "Parsen", NavigationSourceEntityTypeName = NameSpace + "Person"
                    });
                    var entry = this.CreatePersonEntryWithoutSerializationInfo();
                    odataWriter.WriteStart(feed);
                    odataWriter.WriteStart(entry);
                    odataWriter.WriteEnd();
                    odataWriter.WriteEnd();
                    var result = WritePayloadHelper.ReadStreamContent(responseMessageWithoutModel.GetStream());
                    Assert.IsTrue(result.Contains("Person(-5)\",\"PersonId\":-5"));
                    if (!mimeType.Contains(MimeTypes.ODataParameterNoMetadata))
                    {
                        // no metadata does not write odata.metadata
                        Assert.IsTrue(result.Contains("$metadata#Parsen\""));
                    }
                }

                // wrong collection type name
                responseMessageWithoutModel = new StreamResponseMessage(new MemoryStream());
                responseMessageWithoutModel.SetHeader("Content-Type", mimeType);
                using (var messageWriter = new ODataMessageWriter(responseMessageWithoutModel, settings))
                {
                    var odataWriter    = messageWriter.CreateODataCollectionWriter();
                    var collctionStart = new ODataCollectionStart()
                    {
                        Name = "BackupContactInfo"
                    };
                    collctionStart.SetSerializationInfo(new ODataCollectionStartSerializationInfo()
                    {
                        CollectionTypeName = "Collection(" + NameSpace + "ContactDETAIL)"
                    });

                    odataWriter.WriteStart(collctionStart);
                    odataWriter.WriteItem(
                        WritePayloadHelper.CreatePrimaryContactODataComplexValue());
                    odataWriter.WriteEnd();
                    var result = WritePayloadHelper.ReadStreamContent(responseMessageWithoutModel.GetStream());
                    Assert.IsTrue(result.Contains("value\":[{\"EmailBag\":["));
                    if (!mimeType.Contains(MimeTypes.ODataParameterNoMetadata))
                    {
                        // no metadata does not write odata.metadata
                        Assert.IsTrue(result.Contains("$metadata#Collection(" + NameSpace + "ContactDETAIL)"));
                    }
                }

                // The following two cases of wrong reference link info is no longer active. The ODataEntityReferenceLinkSerializationInfo is ignored when writer writes the payload.
                // Consider removing them.

                // wrong reference link info
                responseMessageWithoutModel = new StreamResponseMessage(new MemoryStream());
                responseMessageWithoutModel.SetHeader("Content-Type", mimeType);
                using (var messageWriter = new ODataMessageWriter(responseMessageWithoutModel, settings))
                {
                    var link = new ODataEntityReferenceLink()
                    {
                        Url = new Uri(this.ServiceUri + "Order(-10)")
                    };
                    messageWriter.WriteEntityReferenceLink(link);
                    var result = WritePayloadHelper.ReadStreamContent(responseMessageWithoutModel.GetStream());
                    Assert.IsTrue(result.Contains(this.ServiceUri + "Order(-10)"));
                    if (!mimeType.Contains(MimeTypes.ODataParameterNoMetadata))
                    {
                        // no metadata does not write odata.context
                        Assert.IsTrue(result.Contains("$metadata#$ref"));
                    }
                }

                // wrong reference links info
                responseMessageWithoutModel = new StreamResponseMessage(new MemoryStream());
                responseMessageWithoutModel.SetHeader("Content-Type", mimeType);
                using (var messageWriter = new ODataMessageWriter(responseMessageWithoutModel, settings))
                {
                    var links = new ODataEntityReferenceLinks()
                    {
                        Links = new[]
                        {
                            new ODataEntityReferenceLink()
                            {
                                Url = new Uri(this.ServiceUri + "Order(-10)")
                            }
                        },
                    };

                    messageWriter.WriteEntityReferenceLinks(links);
                    var result = WritePayloadHelper.ReadStreamContent(responseMessageWithoutModel.GetStream());
                    Assert.IsTrue(result.Contains(this.ServiceUri + "Order(-10)"));
                    if (!mimeType.Contains(MimeTypes.ODataParameterNoMetadata))
                    {
                        // no metadata does not write odata.metadata
                        Assert.IsTrue(result.Contains("$metadata#Collection($ref)"));
                    }
                }
            }
        }
        /// <summary>
        /// Writes the result of a $ref query as the message payload.
        /// </summary>
        /// <param name="links">The entity reference links to write as message payload.</param>
        /// <remarks>It is the responsibility of this method to flush the output before the method returns.</remarks>
        internal override void WriteEntityReferenceLinks(ODataEntityReferenceLinks links)
        {
            this.AssertSynchronous();

            this.WriteEntityReferenceLinksImplementation(links);
            this.Flush();
        }
        public void ShouldWriteAndReadForEntityReferenceLinksWithReferenceLinksAnnotation()
        {
            ODataEntityReferenceLink link1 = new ODataEntityReferenceLink
            {
                Url = new Uri("http://host/Customers(1)")
            };
            link1.InstanceAnnotations.Add(new ODataInstanceAnnotation("Is.New", new ODataPrimitiveValue(true)));
            ODataEntityReferenceLink link2 = new ODataEntityReferenceLink
            {
                Url = new Uri("http://host/Customers(2)")
            };
            link2.InstanceAnnotations.Add(new ODataInstanceAnnotation("TestNamespace.unknown", new ODataPrimitiveValue(123)));
            link2.InstanceAnnotations.Add(new ODataInstanceAnnotation("custom.annotation", new ODataPrimitiveValue(456)));

            ODataEntityReferenceLinks referencelinks = new ODataEntityReferenceLinks()
            {
                Links = new[] { link1, link2 }
            };

            referencelinks.InstanceAnnotations.Add(new ODataInstanceAnnotation("TestNamespace.name", new ODataPrimitiveValue(321)));
            referencelinks.InstanceAnnotations.Add(new ODataInstanceAnnotation("custom.name", new ODataPrimitiveValue(654)));
            
            string midplayoad = WriteToString(referencelinks, writingResponse: false);
            var deserializer = this.CreateJsonLightEntryAndFeedDeserializer(midplayoad);
            ODataEntityReferenceLinks links = deserializer.ReadEntityReferenceLinks();
            SameEntityReferenceLinks(referencelinks, links);
        }
 /// <summary>
 /// Writes the result of a $ref query as the message payload.
 /// </summary>
 /// <param name="links">The entity reference links to write as message payload.</param>
 private void WriteEntityReferenceLinksImplementation(ODataEntityReferenceLinks links)
 {
     ODataJsonLightEntityReferenceLinkSerializer jsonLightEntityReferenceLinkSerializer = new ODataJsonLightEntityReferenceLinkSerializer(this);
     jsonLightEntityReferenceLinkSerializer.WriteEntityReferenceLinks(links);
 }
 private static void SameEntityReferenceLinks(ODataEntityReferenceLinks links1, ODataEntityReferenceLinks links2)
 {
     links1.Should().NotBeNull();
     links2.Should().NotBeNull();
     links1.Links.Should().NotBeNull();
     links2.Links.Should().NotBeNull();
     links1.Links.Count().Should().Equals(links2.Links.Count());
     for (var i = 0; i < links1.Links.Count(); ++i)
     {
         SameEntityReferenceLink(links1.Links.ElementAt(i), links2.Links.ElementAt(i));
     }
     SameInstanceAnnotations(links1.InstanceAnnotations, links2.InstanceAnnotations);
 }
        public void WriteTopLevelEntityReferenceLinks()
        {
            ODataEntityReferenceLink link1 = new ODataEntityReferenceLink
            {
                Url = new Uri("http://host/Customers(1)")
            };
            link1.InstanceAnnotations.Add(new ODataInstanceAnnotation("Is.New", new ODataPrimitiveValue(true)));
            ODataEntityReferenceLink link2 = new ODataEntityReferenceLink
            {
                Url = new Uri("http://host/Customers(2)")
            };
            link2.InstanceAnnotations.Add(new ODataInstanceAnnotation("TestNamespace.unknown", new ODataPrimitiveValue(123)));
            link2.InstanceAnnotations.Add(new ODataInstanceAnnotation("custom.annotation", new ODataPrimitiveValue(456)));

            ODataEntityReferenceLinks referencelinks = new ODataEntityReferenceLinks()
            {
                Links = new[] { link1, link2 }
            };

            var writerSettings = new ODataMessageWriterSettings { DisableMessageStreamDisposal = true };
            writerSettings.SetContentType(ODataFormat.Json);
            writerSettings.SetServiceDocumentUri(new Uri("http://odata.org/test"));
            MemoryStream stream = new MemoryStream();
            IODataResponseMessage requestMessageToWrite = new InMemoryMessage { StatusCode = 200, Stream = stream };
            requestMessageToWrite.PreferenceAppliedHeader().AnnotationFilter = "*";

            using (var messageWriter = new ODataMessageWriter(requestMessageToWrite, writerSettings, EdmModel))
            {
                messageWriter.WriteEntityReferenceLinks(referencelinks);
            }
            stream.Position = 0;
            string payload = (new StreamReader(stream)).ReadToEnd();

            string expectedPayload = "{\"@odata.context\":\"http://odata.org/test/$metadata#Collection($ref)\",\"value\":[{\"@odata.id\":\"http://host/Customers(1)\",\"@Is.New\":true},{\"@odata.id\":\"http://host/Customers(2)\",\"@TestNamespace.unknown\":123,\"@custom.annotation\":456}]}";

            Assert.Equal(expectedPayload, payload);
        }
Ejemplo n.º 60
0
        /// <summary>
        /// Writes the result of a $links query as the message payload.
        /// </summary>
        /// <param name="links">The entity reference links to write as message payload.</param>
        /// <param name="entitySet">The entity set of the navigation property.</param>
        /// <param name="navigationProperty">The navigation property for which the entity reference links are being written, or null if none is available.</param>
        private void WriteEntityReferenceLinksImplementation(ODataEntityReferenceLinks links, IEdmEntitySet entitySet, IEdmNavigationProperty navigationProperty)
        {
            ODataJsonLightEntityReferenceLinkSerializer jsonLightEntityReferenceLinkSerializer = new ODataJsonLightEntityReferenceLinkSerializer(this);

            jsonLightEntityReferenceLinkSerializer.WriteEntityReferenceLinks(links, entitySet, navigationProperty);
        }