/// <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(); }
/// <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); }
/// <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(); }
/// <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(); }
/// <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 }); }
/// <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; }
/// <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); }
/// <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 })); }
/// <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(); }
/// <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); }
/// <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); }
/// <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 } }
/// <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. }
/// <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> /// 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)); } }
/// <summary> /// Start writing a link. /// </summary> /// <param name="link">Link to write.</param> public abstract void WriteStart(ODataLink link);
public static AtomLinkMetadata Atom(this ODataLink link) { ExceptionUtils.CheckArgumentNotNull(link, "link"); return(link.GetAnnotation <AtomLinkMetadata>()); }
/// <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 }
/// <summary> /// Finish writing an expanded link. /// </summary> /// <param name="link">The link to write.</param> protected abstract void EndExpandedLink(ODataLink link);
/// <summary> /// Write a regular (non-expanded) link. /// </summary> /// <param name="link">The link to write.</param> protected abstract void WriteLink(ODataLink link);
/// <summary> /// Start writing am expanded link. /// </summary> /// <param name="link">The link to write.</param> protected abstract void StartExpandedLink(ODataLink link);