Beispiel #1
0
        /// <summary>
        /// This method is for parsing CUD operation payloads which are expected to contain one of the following:
        ///
        ///     - Single AtomEntry
        ///         This is the typical response we expect in the non-error case.
        ///     - Feed with a single AtomEntry
        ///         This is not valid per OData protocol, but we allowed this in V1/V2 and will continue to accept it since we can still treat it like a single entry.
        ///     - Error
        ///         Parser handles this case as we read the payload, it's not explicitly handled here.
        ///
        /// Since we don't control the payload, it may contain something that doesn't fit these requirements, in which case we will throw.
        /// </summary>
        /// <param name="reader">the reader for the payload</param>
        /// <param name="responseInfo">The current ResponseInfo object</param>
        /// <returns>the AtomEntry that was read</returns>
        internal static AtomEntry ParseSingleEntityPayload(XmlReader reader, ResponseInfo responseInfo)
        {
            using (AtomParser parser = new AtomParser(reader, AtomParser.XElementBuilderCallback, CommonUtil.UriToString(responseInfo.TypeScheme), responseInfo.DataNamespace, responseInfo.BaseUriResolver, responseInfo.MaxProtocolVersion))
            {
                Debug.Assert(parser.DataKind == AtomDataKind.None, "the parser didn't start in the right state");
                AtomEntry entry = null;
                while (parser.Read())
                {
                    if (parser.DataKind != AtomDataKind.Feed && parser.DataKind != AtomDataKind.Entry)
                    {
                        throw new InvalidOperationException(Strings.AtomParser_SingleEntry_ExpectedFeedOrEntry);
                    }

                    if (parser.DataKind == AtomDataKind.Entry)
                    {
                        if (entry != null)
                        {
                            throw new InvalidOperationException(Strings.AtomParser_SingleEntry_MultipleFound);
                        }

                        entry = parser.CurrentEntry;
                    }
                }

                if (entry == null)
                {
                    throw new InvalidOperationException(Strings.AtomParser_SingleEntry_NoneFound);
                }

                Debug.Assert(parser.DataKind == AtomDataKind.Finished, "the parser didn't end in the right state");
                return entry;
            }
        }
Beispiel #2
0
        private void HandleExpandedNavigationProperties(AtomEntry targetEntry, string propertyName, bool isFeed)
        {
            Debug.Assert(!this.reader.IsEmptyElement, "the current element has some child content");

            if (!ReadChildElement(this.reader, XmlConstants.AtomInlineElementName, XmlConstants.DataWebMetadataNamespace))
            {
                return;
            }

            bool emptyInlineCollection = this.reader.IsEmptyElement;
            object propertyValue = null;

            if (!emptyInlineCollection)
            {
                AtomFeed nestedFeed = null;
                AtomEntry nestedEntry = null;
                List<AtomEntry> feedEntries = null;

                Debug.Assert(this.reader is Xml.XmlWrappingReader, "reader must be a instance of XmlWrappingReader");
                Uri readerBaseUri = string.IsNullOrEmpty(this.reader.BaseURI) ? null : new Uri(this.reader.BaseURI, UriKind.Absolute);
                XmlReader nestedReader = Xml.XmlWrappingReader.CreateReader(readerBaseUri, this.reader.ReadSubtree());
                nestedReader.Read();
                Debug.Assert(nestedReader.LocalName == "inline", "nestedReader.LocalName == 'inline'");

                AtomParser nested = new AtomParser(nestedReader, this.entryCallback, this.typeScheme, this.currentDataNamespace, this.baseUriResolver, this.MaxProtocolVersion);
                while (nested.Read())
                {
                    switch (nested.DataKind)
                    {
                        case AtomDataKind.Feed:
                            feedEntries = new List<AtomEntry>();
                            nestedFeed = nested.CurrentFeed;
                            propertyValue = nestedFeed;
                            break;
                        case AtomDataKind.Entry:
                            nestedEntry = nested.CurrentEntry;
                            if (feedEntries != null)
                            {
                                feedEntries.Add(nestedEntry);
                            }
                            else
                            {
                                propertyValue = nestedEntry;
                            }

                            break;
                        case AtomDataKind.PagingLinks:
                            // Here the inner feed parser found a paging link, and stored it on nestedFeed.NextPageLink
                            // we are going to add it into a link table and associate
                            // with the collection at AtomMaterializer::Materialize()
                            // Do nothing for now.
                            break;
                        default:
                            throw new InvalidOperationException(Strings.AtomParser_UnexpectedContentUnderExpandedLink);
                    }
                }

                if (nestedFeed != null)
                {
                    Debug.Assert(
                        nestedFeed.Entries == null,
                        "nestedFeed.Entries == null -- otherwise someone initialized this for us");
                    nestedFeed.Entries = feedEntries;
                }
            }

            AtomContentProperty property = new AtomContentProperty();
            property.Name = propertyName;

            if (emptyInlineCollection || propertyValue == null)
            {
                property.IsNull = true;
                if (isFeed)
                {
                    property.Feed = new AtomFeed();
                    property.Feed.Entries = Enumerable.Empty<AtomEntry>();
                }
                else
                {
                    property.Entry = new AtomEntry(this.MaxProtocolVersion);
                    property.Entry.IsNull = true;
                }
            }
            else
            {
                property.Feed = propertyValue as AtomFeed;
                property.Entry = propertyValue as AtomEntry;
            }

            targetEntry.DataValues.Add(property);
        }