Example #1
0
        /// <summary>
        /// Start writing a feed.
        /// </summary>
        /// <param name="feed">The feed to write.</param>
        protected override void StartFeed(ODataFeed feed)
        {
            Debug.Assert(feed != null, "feed != null");

            // We need to write the "results" wrapper for V2 and higher and only for responses or for expanded links
            // Feeds are allowed in expanded links even in requests, but they are not allowed on top-level in requests.
            if (this.Version >= ODataVersion.V2 && (this.WritingResponse || !this.IsTopLevel))
            {
                // {
                this.jsonWriter.StartObjectScope();

                long?inlineCount = feed.Count;
                if (inlineCount.HasValue)
                {
                    this.jsonWriter.WriteName(JsonConstants.ODataCountName);

                    this.jsonWriter.WriteValue(inlineCount.Value);
                }

                // If the feed is an expanded collection of entities this is the place to write the relationship links
                ODataLink parentExpandedLink = this.ParentExpandedLink;
                if (parentExpandedLink != null)
                {
                    // TODO: Write relationship link of the this.ParentExpandedLink here
                    // TODO: Version check for relationship link
                }

                // "results":
                this.jsonWriter.WriteDataArrayName();
            }

            // Start array which will hold the entries in the feed.
            this.jsonWriter.StartArrayScope();
        }
Example #2
0
        /// <summary>
        /// Start writing a link.
        /// </summary>
        /// <param name="link">Link to write.</param>
        public sealed override void WriteStart(ODataLink link)
        {
            ExceptionUtils.CheckArgumentNotNull(link, "link");

            this.VerifyNotDisposed();
            this.EnterScope(WriterState.Link, link);
        }
Example #3
0
        /// <summary>
        /// Start writing a regular (non-expanded) link.
        /// </summary>
        /// <param name="link">The link to write.</param>
        protected override void WriteLink(ODataLink link)
        {
            Debug.Assert(link != null, "link != null");

            ValidationUtils.ValidateLink(link);

            // Link must specify the Url for non-expanded links
            // NOTE: we currently only require a non-null Url for ATOM payloads and non-expanded links in JSON.
            //       There is no place in JSON to write a Url if the link is expanded. We can't change that for v1 and v2; we
            //       might fix the protocol for v3.
            if (link.Url == null)
            {
                throw new ODataException(Strings.ODataWriter_LinkMustSpecifyUrl);
            }

            Debug.Assert(!string.IsNullOrEmpty(link.Name), "The link Name should have been validated by now.");
            this.jsonWriter.WriteName(link.Name);

            // A deferred link is represented as an object
            this.jsonWriter.StartObjectScope();

            // "__deferred": {
            this.jsonWriter.WriteName(JsonConstants.ODataDeferredName);
            this.jsonWriter.StartObjectScope();

            Debug.Assert(link.Url != null, "The link Url should have been validated by now.");
            this.jsonWriter.WriteName(JsonConstants.ODataLinkUriName);
            this.jsonWriter.WriteValue(ODataJsonWriterUtils.UriToAbsoluteUriString(link.Url, this.BaseUri));

            // End the __deferred object
            this.jsonWriter.EndObjectScope();

            // End the link value
            this.jsonWriter.EndObjectScope();
        }
Example #4
0
        /// <summary>
        /// Start writing a link.
        /// </summary>
        /// <param name="link">The link to write.</param>
        protected override void WriteLink(ODataLink link)
        {
            Debug.Assert(link != null, "link != null");

            this.WriteLinkStart(link);
            this.WriteLinkEnd();
        }
Example #5
0
        /// <summary>
        /// Creates the value for the navigation property's link relation attribute.
        /// </summary>
        /// <param name="link">The link representing the navigation property for which the relation value is created.</param>
        /// <returns>The relation attribute value for the navigation property's link relation.</returns>
        internal static string ComputeODataLinkRelation(ODataLink link)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(link != null, "link != null");
            Debug.Assert(link.Name != null, "link.Name != null");

            return string.Join("/", new string[] { AtomConstants.ODataNamespace, AtomConstants.ODataNavigationPropertiesRelatedSegmentName, link.Name });
        }
Example #6
0
        /// <summary>
        /// Creates the value for the navigation property's type attribute.
        /// </summary>
        /// <param name="link">The link representing the navigation property for which the type value is created.</param>
        /// <returns>The type attribute value for the navigation property.</returns>
        internal static string ComputeODataLinkType(ODataLink link)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(link != null, "link != null");

            // "application/atom+xml;type=entry" or type="application/atom+xml;type=feed"
            return link.IsCollection ? MimeConstants.MimeApplicationAtomXmlTypeFeed : MimeConstants.MimeApplicationAtomXmlTypeEntry;
        }
Example #7
0
        /// <summary>
        /// Creates the value for the navigation property's type attribute.
        /// </summary>
        /// <param name="link">The link representing the navigation property for which the type value is created.</param>
        /// <returns>The type attribute value for the navigation property.</returns>
        internal static string ComputeODataLinkType(ODataLink link)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(link != null, "link != null");

            // "application/atom+xml;type=entry" or type="application/atom+xml;type=feed"
            return(link.IsCollection ? MimeConstants.MimeApplicationAtomXmlTypeFeed : MimeConstants.MimeApplicationAtomXmlTypeEntry);
        }
Example #8
0
        /// <summary>
        /// Creates the value for the navigation property's link relation attribute.
        /// </summary>
        /// <param name="link">The link representing the navigation property for which the relation value is created.</param>
        /// <returns>The relation attribute value for the navigation property's link relation.</returns>
        internal static string ComputeODataLinkRelation(ODataLink link)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(link != null, "link != null");
            Debug.Assert(link.Name != null, "link.Name != null");

            return(string.Join("/", new string[] { AtomConstants.ODataNamespace, AtomConstants.ODataNavigationPropertiesRelatedSegmentName, link.Name }));
        }
Example #9
0
        /// <summary>
        /// Finish writing an expanded link.
        /// </summary>
        /// <param name="link">The link to write.</param>
        protected override void EndExpandedLink(ODataLink link)
        {
            Debug.Assert(link != null, "link != null");

            // </m:inline>
            this.writer.WriteEndElement();

            this.WriteLinkEnd();
        }
Example #10
0
        /// <summary>
        /// Start writing am expanded link.
        /// </summary>
        /// <param name="link">The link to write.</param>
        protected override void StartExpandedLink(ODataLink link)
        {
            Debug.Assert(link != null, "link != null");

            // write the start element of the link
            this.WriteLinkStart(link);

            // <m:inline>
            this.writer.WriteStartElement(AtomConstants.ODataMetadataNamespacePrefix, AtomConstants.ODataInlineElementName, AtomConstants.ODataMetadataNamespace);
        }
Example #11
0
        /// <summary>
        /// Validates an <see cref="ODataLink"/> to ensure all required information is specified and valid.
        /// </summary>
        /// <param name="link">The link to validate.</param>
        internal static void ValidateLink(ODataLink link)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(link != null, "link != null");

            // Link must have a non-empty name
            if (string.IsNullOrEmpty(link.Name))
            {
                throw new ODataException(Strings.ODataWriter_LinkMustSpecifyName);
            }
        }
        /// <summary>
        /// Write the metadata for an OData link; makes sure any duplicate of the link's values duplicated in metadata are equal.
        /// </summary>
        /// <param name="writer">The Xml writer to write to.</param>
        /// <param name="baseUri">The base Uri of the document or null if none was specified.</param>
        /// <param name="link">The link for which to write the metadata.</param>
        internal static void WriteODataLinkMetadata(XmlWriter writer, Uri baseUri, ODataLink link)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(writer != null, "writer != null");
            Debug.Assert(link != null, "link != null");
            Debug.Assert(!string.IsNullOrEmpty(link.Name), "The link name was not verified yet.");
            Debug.Assert(link.Url != null, "The link Url was not verified yet.");

            string linkRelation = AtomUtils.ComputeODataLinkRelation(link);
            string linkHref     = AtomUtils.ToUrlAttributeValue(link.Url, baseUri);
            string linkHrefLang = null;
            string linkType     = AtomUtils.ComputeODataLinkType(link);
            string linkTitle    = link.Name;
            int?   linkLength   = null;

            AtomLinkMetadata linkMetadata = link.Atom();

            if (linkMetadata != null)
            {
                Uri metadataHref = linkMetadata.Href;
                if (metadataHref != null)
                {
                    string metadataHrefString = AtomUtils.ToUrlAttributeValue(metadataHref, baseUri);
                    if (metadataHrefString != linkHref)
                    {
                        throw new ODataException(Strings.ODataAtomWriter_LinkMetadataHrefMustBeEqualWithLinkUrl(metadataHrefString, linkHref));
                    }
                }

                string metadataRelation = linkMetadata.Relation;
                if (metadataRelation != null && metadataRelation != linkRelation)
                {
                    throw new ODataException(Strings.ODataAtomWriter_LinkMetadataRelationMustBeEqualWithComputedRelation(metadataRelation, linkRelation));
                }

                string metadataType = linkMetadata.MediaType;
                if (metadataType != null && metadataType != linkType)
                {
                    throw new ODataException(Strings.ODataAtomWriter_LinkMetadataMediaTypeMustBeEqualWithComputedType(metadataType, linkType));
                }

                string metadataTitle = linkMetadata.Title;
                if (metadataTitle != null && metadataTitle != linkTitle)
                {
                    throw new ODataException(Strings.ODataAtomWriter_LinkMetadataTitleMustBeEqualWithLinkName(metadataTitle, linkTitle));
                }

                linkHrefLang = linkMetadata.HrefLang;
                linkLength   = linkMetadata.Length;
            }

            WriteAtomLinkMetadataAttributes(writer, linkRelation, linkHref, linkHrefLang, linkTitle, linkType, linkLength);
        }
Example #13
0
        /// <summary>
        /// Start writing an entry.
        /// </summary>
        /// <param name="entry">The entry to write.</param>
        protected override void StartEntry(ODataEntry entry)
        {
            Debug.Assert(entry != null, "entry != null");

            // Write just the object start, nothing else, since we might not have complete information yet
            this.jsonWriter.StartObjectScope();

            ODataLink parentExpandedLink = this.ParentExpandedLink;

            if (parentExpandedLink != null)
            {
                // TODO: Write out the relationship link for the expanded link here
                // TODO: Version check for relationship link
            }
        }
Example #14
0
        /// <summary>
        /// Start writing an expanded link.
        /// </summary>
        /// <param name="link">The link to write.</param>
        protected override void StartExpandedLink(ODataLink link)
        {
            Debug.Assert(link != null, "link != null");

            ValidationUtils.ValidateLink(link);

            Debug.Assert(!string.IsNullOrEmpty(link.Name), "The link name should have been verified by now.");
            this.jsonWriter.WriteName(link.Name);

            // Everything else is done in the expanded feed or entry since we include the link related information
            // in the feed/entry object.

            // TODO: Design issue # 27: JSON doesn't store link Url for expanded links
            //   figure out if we are going to fix this for V3 and then we would need to write it somewhere around here.
        }
Example #15
0
        /// <summary>
        /// Writes the link's start element and atom metadata.
        /// </summary>
        /// <param name="link">The link to write.</param>
        private void WriteLinkStart(ODataLink link)
        {
            ValidationUtils.ValidateLink(link);

            // Link must specify the Url
            // NOTE: we currently only require a non-null Url for ATOM payloads and non-expanded links in JSON.
            //       There is no place in JSON to write a Url if the link is expanded. We can't change that for v1 and v2; we
            //       might fix the protocol for v3.
            if (link.Url == null)
            {
                throw new ODataException(Strings.ODataWriter_LinkMustSpecifyUrl);
            }

            // <atom:link>
            this.writer.WriteStartElement(AtomConstants.AtomNamespacePrefix, AtomConstants.AtomLinkElementName, AtomConstants.AtomNamespace);

            ODataAtomWriterMetadataUtils.WriteODataLinkMetadata(this.writer, this.BaseUri, link);
        }
Example #16
0
        /// <summary>
        /// Checks whether we are currently writing a link and switches to ExpandedLink state if we do.
        /// </summary>
        /// <param name="writingExpandedLinkForFeed">Flag indicating whether we are currently trying to write a feed or an entry.</param>
        private void CheckForExpandedLink(bool writingExpandedLinkForFeed)
        {
            Scope current = this.scopes.Peek();

            if (current.State == WriterState.Link)
            {
                ODataLink currentLink = (ODataLink)current.Item;

                // make sure the IsCollection property is set correctly on the link
                bool isCollection = currentLink.IsCollection;
                if (writingExpandedLinkForFeed != isCollection)
                {
                    string uri   = currentLink.Url == null ? "null" : UriUtils.UriToString(currentLink.Url);
                    string error = writingExpandedLinkForFeed
                        ? Strings.ODataWriterCore_EntryExpandedLinkWithFeedContent(uri)
                        : Strings.ODataWriterCore_FeedExpandedLinkWithEntryContent(uri);
                    this.ThrowODataException(error, currentLink);
                }

                // we are writing an expanded link; change the state
                this.ReplaceScope(WriterState.ExpandedLink, currentLink);
                this.InterceptException(() => this.StartExpandedLink(currentLink));
            }
        }
Example #17
0
 /// <summary>
 /// Start writing a link.
 /// </summary>
 /// <param name="link">Link to write.</param>
 public abstract void WriteStart(ODataLink link);
Example #18
0
 /// <summary>
 /// Start writing a link.
 /// </summary>
 /// <param name="link">Link to write.</param>
 public abstract void WriteStart(ODataLink link);
Example #19
0
        public static AtomLinkMetadata Atom(this ODataLink link)
        {
            ExceptionUtils.CheckArgumentNotNull(link, "link");

            return(link.GetAnnotation <AtomLinkMetadata>());
        }
Example #20
0
        /// <summary>
        /// Finish writing an expanded link.
        /// </summary>
        /// <param name="link">The link to write.</param>
        protected override void EndExpandedLink(ODataLink link)
        {
            Debug.Assert(link != null, "link != null");

            // Nothing to do here, the link is represented as a JSON object which is either the feed or entry
        }
Example #21
0
        /// <summary>
        /// Start writing a link.
        /// </summary>
        /// <param name="link">Link to write.</param>
        public sealed override void WriteStart(ODataLink link)
        {
            ExceptionUtils.CheckArgumentNotNull(link, "link");

            this.VerifyNotDisposed();
            this.EnterScope(WriterState.Link, link);
        }
Example #22
0
 /// <summary>
 /// Finish writing an expanded link.
 /// </summary>
 /// <param name="link">The link to write.</param>
 protected abstract void EndExpandedLink(ODataLink link);
Example #23
0
 /// <summary>
 /// Write a regular (non-expanded) link.
 /// </summary>
 /// <param name="link">The link to write.</param>
 protected abstract void WriteLink(ODataLink link);
Example #24
0
        /// <summary>
        /// Start writing a regular (non-expanded) link.
        /// </summary>
        /// <param name="link">The link to write.</param>
        protected override void WriteLink(ODataLink link)
        {
            Debug.Assert(link != null, "link != null");

            ValidationUtils.ValidateLink(link);

            // Link must specify the Url for non-expanded links
            // NOTE: we currently only require a non-null Url for ATOM payloads and non-expanded links in JSON.
            //       There is no place in JSON to write a Url if the link is expanded. We can't change that for v1 and v2; we
            //       might fix the protocol for v3.
            if (link.Url == null)
            {
                throw new ODataException(Strings.ODataWriter_LinkMustSpecifyUrl);
            }

            Debug.Assert(!string.IsNullOrEmpty(link.Name), "The link Name should have been validated by now.");
            this.jsonWriter.WriteName(link.Name);

            // A deferred link is represented as an object
            this.jsonWriter.StartObjectScope();

            // "__deferred": {
            this.jsonWriter.WriteName(JsonConstants.ODataDeferredName);
            this.jsonWriter.StartObjectScope();

            Debug.Assert(link.Url != null, "The link Url should have been validated by now.");
            this.jsonWriter.WriteName(JsonConstants.ODataLinkUriName);
            this.jsonWriter.WriteValue(ODataJsonWriterUtils.UriToAbsoluteUriString(link.Url, this.BaseUri));

            // End the __deferred object
            this.jsonWriter.EndObjectScope();

            // End the link value
            this.jsonWriter.EndObjectScope();
        }
Example #25
0
 /// <summary>
 /// Finish writing an expanded link.
 /// </summary>
 /// <param name="link">The link to write.</param>
 protected abstract void EndExpandedLink(ODataLink link);
Example #26
0
        /// <summary>
        /// Writes the link's start element and atom metadata.
        /// </summary>
        /// <param name="link">The link to write.</param>
        private void WriteLinkStart(ODataLink link)
        {
            ValidationUtils.ValidateLink(link);

            // Link must specify the Url
            // NOTE: we currently only require a non-null Url for ATOM payloads and non-expanded links in JSON.
            //       There is no place in JSON to write a Url if the link is expanded. We can't change that for v1 and v2; we
            //       might fix the protocol for v3.
            if (link.Url == null)
            {
                throw new ODataException(Strings.ODataWriter_LinkMustSpecifyUrl);
            }

            // <atom:link>
            this.writer.WriteStartElement(AtomConstants.AtomNamespacePrefix, AtomConstants.AtomLinkElementName, AtomConstants.AtomNamespace);

            ODataAtomWriterMetadataUtils.WriteODataLinkMetadata(this.writer, this.BaseUri, link);
        }
        /// <summary>
        /// Write the metadata for an OData link; makes sure any duplicate of the link's values duplicated in metadata are equal.
        /// </summary>
        /// <param name="writer">The Xml writer to write to.</param>
        /// <param name="baseUri">The base Uri of the document or null if none was specified.</param>
        /// <param name="link">The link for which to write the metadata.</param>
        internal static void WriteODataLinkMetadata(XmlWriter writer, Uri baseUri, ODataLink link)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(writer != null, "writer != null");
            Debug.Assert(link != null, "link != null");
            Debug.Assert(!string.IsNullOrEmpty(link.Name), "The link name was not verified yet.");
            Debug.Assert(link.Url != null, "The link Url was not verified yet.");

            string linkRelation = AtomUtils.ComputeODataLinkRelation(link);
            string linkHref = AtomUtils.ToUrlAttributeValue(link.Url, baseUri);
            string linkHrefLang = null;
            string linkType = AtomUtils.ComputeODataLinkType(link);
            string linkTitle = link.Name;
            int? linkLength = null;
            
            AtomLinkMetadata linkMetadata = link.Atom();
            if (linkMetadata != null)
            {
                Uri metadataHref = linkMetadata.Href;
                if (metadataHref != null)
                {
                    string metadataHrefString = AtomUtils.ToUrlAttributeValue(metadataHref, baseUri);
                    if (metadataHrefString != linkHref)
                    {
                        throw new ODataException(Strings.ODataAtomWriter_LinkMetadataHrefMustBeEqualWithLinkUrl(metadataHrefString, linkHref));
                    }
                }

                string metadataRelation = linkMetadata.Relation;
                if (metadataRelation != null && metadataRelation != linkRelation)
                {
                    throw new ODataException(Strings.ODataAtomWriter_LinkMetadataRelationMustBeEqualWithComputedRelation(metadataRelation, linkRelation));
                }

                string metadataType = linkMetadata.MediaType;
                if (metadataType != null && metadataType != linkType)
                {
                    throw new ODataException(Strings.ODataAtomWriter_LinkMetadataMediaTypeMustBeEqualWithComputedType(metadataType, linkType));
                }

                string metadataTitle = linkMetadata.Title;
                if (metadataTitle != null && metadataTitle != linkTitle)
                {
                    throw new ODataException(Strings.ODataAtomWriter_LinkMetadataTitleMustBeEqualWithLinkName(metadataTitle, linkTitle));
                }

                linkHrefLang = linkMetadata.HrefLang;
                linkLength = linkMetadata.Length;
            }

            WriteAtomLinkMetadataAttributes(writer, linkRelation, linkHref, linkHrefLang, linkTitle, linkType, linkLength);
        }
Example #28
0
        /// <summary>
        /// Finish writing an expanded link.
        /// </summary>
        /// <param name="link">The link to write.</param>
        protected override void EndExpandedLink(ODataLink link)
        {
            Debug.Assert(link != null, "link != null");

            // </m:inline>
            this.writer.WriteEndElement();

            this.WriteLinkEnd();
        }
Example #29
0
        /// <summary>
        /// Start writing am expanded link.
        /// </summary>
        /// <param name="link">The link to write.</param>
        protected override void StartExpandedLink(ODataLink link)
        {
            Debug.Assert(link != null, "link != null");

            // write the start element of the link
            this.WriteLinkStart(link);

            // <m:inline>
            this.writer.WriteStartElement(AtomConstants.ODataMetadataNamespacePrefix, AtomConstants.ODataInlineElementName, AtomConstants.ODataMetadataNamespace);
        }
Example #30
0
        /// <summary>
        /// Start writing an expanded link.
        /// </summary>
        /// <param name="link">The link to write.</param>
        protected override void StartExpandedLink(ODataLink link)
        {
            Debug.Assert(link != null, "link != null");

            ValidationUtils.ValidateLink(link);

            Debug.Assert(!string.IsNullOrEmpty(link.Name), "The link name should have been verified by now.");
            this.jsonWriter.WriteName(link.Name);

            // Everything else is done in the expanded feed or entry since we include the link related information
            // in the feed/entry object.
            
            // TODO: Design issue # 27: JSON doesn't store link Url for expanded links
            //   figure out if we are going to fix this for V3 and then we would need to write it somewhere around here.
        }
Example #31
0
 /// <summary>
 /// Write a regular (non-expanded) link.
 /// </summary>
 /// <param name="link">The link to write.</param>
 protected abstract void WriteLink(ODataLink link);
Example #32
0
 /// <summary>
 /// Start writing am expanded link.
 /// </summary>
 /// <param name="link">The link to write.</param>
 protected abstract void StartExpandedLink(ODataLink link);
Example #33
0
 /// <summary>
 /// Start writing am expanded link.
 /// </summary>
 /// <param name="link">The link to write.</param>
 protected abstract void StartExpandedLink(ODataLink link);
Example #34
0
        /// <summary>
        /// Finish writing an expanded link.
        /// </summary>
        /// <param name="link">The link to write.</param>
        protected override void EndExpandedLink(ODataLink link)
        {
            Debug.Assert(link != null, "link != null");

            // Nothing to do here, the link is represented as a JSON object which is either the feed or entry
        }
Example #35
0
        /// <summary>
        /// Start writing a link.
        /// </summary>
        /// <param name="link">The link to write.</param>
        protected override void WriteLink(ODataLink link)
        {
            Debug.Assert(link != null, "link != null");

            this.WriteLinkStart(link);
            this.WriteLinkEnd();
        }
Example #36
0
        /// <summary>
        /// Validates an <see cref="ODataLink"/> to ensure all required information is specified and valid.
        /// </summary>
        /// <param name="link">The link to validate.</param>
        internal static void ValidateLink(ODataLink link)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(link != null, "link != null");

            // Link must have a non-empty name
            if (string.IsNullOrEmpty(link.Name))
            {
                throw new ODataException(Strings.ODataWriter_LinkMustSpecifyName);
            }
        }