public ODataMessageWriter(IODataResponseMessage responseMessage, ODataMessageWriterSettings settings, IEdmModel model) { this.writerPayloadKind = ODataPayloadKind.Unsupported; ExceptionUtils.CheckArgumentNotNull <IODataResponseMessage>(responseMessage, "responseMessage"); this.settings = (settings == null) ? new ODataMessageWriterSettings() : new ODataMessageWriterSettings(settings); WriterValidationUtils.ValidateMessageWriterSettings(this.settings); this.writingResponse = true; this.message = new ODataResponseMessage(responseMessage, true, this.settings.DisableMessageStreamDisposal, -1L); this.urlResolver = responseMessage as IODataUrlResolver; this.model = model ?? EdmCoreModel.Instance; }
private void WriteEntityReferenceLinkImplementation(ODataEntityReferenceLink entityReferenceLink) { Action action = null; if (this.outputContext.WritingResponse) { this.ThrowODataException(Microsoft.Data.OData.Strings.ODataWriterCore_EntityReferenceLinkInResponse, null); } this.CheckForNavigationLinkWithContent(ODataPayloadKind.EntityReferenceLink); if (!this.SkipWriting) { if (action == null) { action = delegate { WriterValidationUtils.ValidateEntityReferenceLink(entityReferenceLink); this.WriteEntityReferenceInNavigationLinkContent((ODataNavigationLink)this.CurrentScope.Item, entityReferenceLink); }; } this.InterceptException(action); } }
private void CheckForNavigationLinkWithContent(ODataPayloadKind contentPayloadKind) { Scope currentScope = this.CurrentScope; if ((currentScope.State == WriterState.NavigationLink) || (currentScope.State == WriterState.NavigationLinkWithContent)) { Action action = null; ODataNavigationLink currentNavigationLink = (ODataNavigationLink)currentScope.Item; IEdmType navigationPropertyType = null; this.InterceptException(delegate { navigationPropertyType = WriterValidationUtils.ValidateNavigationLink(currentNavigationLink, this.ParentEntryEntityType, new ODataPayloadKind?(contentPayloadKind)); ((NavigationLinkScope)this.CurrentScope).NavigationPropertyType = navigationPropertyType; }); if (currentScope.State != WriterState.NavigationLinkWithContent) { this.PromoteNavigationLinkScope(); if (!this.SkipWriting) { if (action == null) { action = delegate { this.DuplicatePropertyNamesChecker.CheckForDuplicatePropertyNames(currentNavigationLink, contentPayloadKind != ODataPayloadKind.EntityReferenceLink, new bool?(contentPayloadKind == ODataPayloadKind.Feed)); this.StartNavigationLinkWithContent(currentNavigationLink); }; } this.InterceptException(action); } } else if (this.outputContext.WritingResponse || (currentNavigationLink.IsCollection != true)) { this.ThrowODataException(Microsoft.Data.OData.Strings.ODataWriterCore_MultipleItemsInNavigationLinkContent, currentNavigationLink); } } else if (contentPayloadKind == ODataPayloadKind.EntityReferenceLink) { this.ThrowODataException(Microsoft.Data.OData.Strings.ODataWriterCore_EntityReferenceLinkWithoutNavigationLink, null); } }
private void WriteStartEntryImplementation(ODataEntry entry) { Action action = null; this.StartPayloadInStartState(); this.CheckForNavigationLinkWithContent(ODataPayloadKind.Entry); this.EnterScope(WriterState.Entry, entry); if (!this.SkipWriting) { this.IncreaseEntryDepth(); if (action == null) { action = delegate { if (entry != null) { IEdmEntityType entityType = WriterValidationUtils.ValidateEntityTypeName(this.outputContext.Model, entry.TypeName); bool validateMediaResource = this.outputContext.UseDefaultFormatBehavior || this.outputContext.UseServerFormatBehavior; ValidationUtils.ValidateEntryMetadata(entry, entityType, this.outputContext.Model, validateMediaResource); NavigationLinkScope parentNavigationLinkScope = this.ParentNavigationLinkScope; if (parentNavigationLinkScope != null) { WriterValidationUtils.ValidateEntryInExpandedLink(entityType, parentNavigationLinkScope.NavigationPropertyType); } if (this.CurrentFeedValidator != null) { this.CurrentFeedValidator.ValidateEntry(entityType); } ((EntryScope)this.CurrentScope).EntityType = entityType; WriterValidationUtils.ValidateEntryAtStart(entry); } this.StartEntry(entry); }; } this.InterceptException(action); } }
internal static IEdmType ValidateNavigationLink(ODataNavigationLink navigationLink, IEdmEntityType declaringEntityType, ODataPayloadKind?expandedPayloadKind) { DebugUtils.CheckNoExternalCallers(); Debug.Assert(navigationLink != null, "navigationLink != null"); Debug.Assert( !expandedPayloadKind.HasValue || expandedPayloadKind.Value == ODataPayloadKind.EntityReferenceLink || expandedPayloadKind.Value == ODataPayloadKind.Entry || expandedPayloadKind.Value == ODataPayloadKind.Feed, "If an expanded payload kind is specified it must be entry, feed or entity reference link."); // Navigation link must have a non-empty name if (string.IsNullOrEmpty(navigationLink.Name)) { throw new ODataException(Strings.ValidationUtils_LinkMustSpecifyName); } // If we write an entity reference link, don't validate the multiplicity of the IsCollection // property if it is 'false' (since we allow writing a singleton navigation link for // a colleciton navigation property in requests) nor the consistency of payload kind and metadata // (which is done separately in ODataWriterCore.CheckForNavigationLinkWithContent). bool isEntityReferenceLinkPayload = expandedPayloadKind == ODataPayloadKind.EntityReferenceLink; // true only if the expandedPayloadKind has a value and the value is 'Feed' bool isFeedPayload = expandedPayloadKind == ODataPayloadKind.Feed; // Make sure the IsCollection property agrees with the payload kind for entry and feed payloads Func <object, string> errorTemplate = null; if (!isEntityReferenceLinkPayload && navigationLink.IsCollection.HasValue && expandedPayloadKind.HasValue) { // For feed/entry make sure the IsCollection property is set correctly. if (isFeedPayload != navigationLink.IsCollection.Value) { errorTemplate = expandedPayloadKind.Value == ODataPayloadKind.Feed ? (Func <object, string>)Strings.WriterValidationUtils_ExpandedLinkIsCollectionFalseWithFeedContent : Strings.WriterValidationUtils_ExpandedLinkIsCollectionTrueWithEntryContent; } } IEdmType navigationPropertyType = null; if (declaringEntityType != null) { IEdmProperty navigationProperty = WriterValidationUtils.ValidateNavigationPropertyDefined(navigationLink.Name, declaringEntityType); Debug.Assert(navigationProperty != null, "If we have a declaring type we expect a non-null navigation property since open nav props are not allowed."); navigationPropertyType = navigationProperty.Type.Definition; bool isCollectionType = navigationPropertyType.TypeKind == EdmTypeKind.Collection; // Make sure the IsCollection property agrees with the metadata type for entry and feed payloads if (navigationLink.IsCollection.HasValue && isCollectionType != navigationLink.IsCollection) { // Ignore the case where IsCollection is 'false' and we are writing an entity reference link // (see comment above) if (!(navigationLink.IsCollection == false && isEntityReferenceLinkPayload)) { errorTemplate = isCollectionType ? (Func <object, string>)Strings.WriterValidationUtils_ExpandedLinkIsCollectionFalseWithFeedMetadata : Strings.WriterValidationUtils_ExpandedLinkIsCollectionTrueWithEntryMetadata; } } // Make sure that the payload kind agrees with the metadata. // For entity reference links we check separately in ODataWriterCore.CheckForNavigationLinkWithContent. if (!isEntityReferenceLinkPayload && expandedPayloadKind.HasValue && isCollectionType != isFeedPayload) { errorTemplate = isCollectionType ? (Func <object, string>)Strings.WriterValidationUtils_ExpandedLinkWithEntryPayloadAndFeedMetadata : Strings.WriterValidationUtils_ExpandedLinkWithFeedPayloadAndEntryMetadata; } } if (errorTemplate != null) { string uri = navigationLink.Url == null ? "null" : UriUtilsCommon.UriToString(navigationLink.Url); throw new ODataException(errorTemplate(uri)); } return(navigationPropertyType); }
private void WriteEndImplementation() { this.InterceptException(delegate { Scope currentScope = this.CurrentScope; switch (currentScope.State) { case WriterState.Start: case WriterState.Completed: case WriterState.Error: throw new ODataException(Microsoft.Data.OData.Strings.ODataWriterCore_WriteEndCalledInInvalidState(currentScope.State.ToString())); case WriterState.Entry: if (!this.SkipWriting) { ODataEntry entry = (ODataEntry)currentScope.Item; if (entry != null) { WriterValidationUtils.ValidateEntryAtEnd(entry); } this.EndEntry(entry); this.DecreaseEntryDepth(); } break; case WriterState.Feed: if (!this.SkipWriting) { ODataFeed item = (ODataFeed)currentScope.Item; WriterValidationUtils.ValidateFeedAtEnd(item, !this.outputContext.WritingResponse, this.outputContext.Version); this.EndFeed(item); } break; case WriterState.NavigationLink: if (!this.outputContext.WritingResponse) { throw new ODataException(Microsoft.Data.OData.Strings.ODataWriterCore_DeferredLinkInRequest); } if (!this.SkipWriting) { ODataNavigationLink navigationLink = (ODataNavigationLink)currentScope.Item; ((NavigationLinkScope)this.CurrentScope).NavigationPropertyType = WriterValidationUtils.ValidateNavigationLink(navigationLink, this.ParentEntryEntityType, null); this.DuplicatePropertyNamesChecker.CheckForDuplicatePropertyNames(navigationLink, false, navigationLink.IsCollection); this.WriteDeferredNavigationLink(navigationLink); } break; case WriterState.NavigationLinkWithContent: if (!this.SkipWriting) { this.EndNavigationLinkWithContent((ODataNavigationLink)currentScope.Item); } break; default: throw new ODataException(Microsoft.Data.OData.Strings.General_InternalError(InternalErrorCodes.ODataWriterCore_WriteEnd_UnreachableCodePath)); } this.LeaveScope(); }); }
protected void ValidateAssociationLink(ODataAssociationLink associationLink, IEdmEntityType entryEntityType) { WriterValidationUtils.ValidateAssociationLink(associationLink, this.Version, this.WritingResponse); WriterValidationUtils.ValidateNavigationPropertyDefined(associationLink.Name, entryEntityType); }