예제 #1
0
 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;
 }
예제 #2
0
        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);
            }
        }
예제 #3
0
        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);
            }
        }
예제 #4
0
        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);
            }
        }
예제 #5
0
        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);
        }
예제 #6
0
        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();
            });
        }
예제 #7
0
 protected void ValidateAssociationLink(ODataAssociationLink associationLink, IEdmEntityType entryEntityType)
 {
     WriterValidationUtils.ValidateAssociationLink(associationLink, this.Version, this.WritingResponse);
     WriterValidationUtils.ValidateNavigationPropertyDefined(associationLink.Name, entryEntityType);
 }