private void ReadOpenProperty(IODataJsonReaderEntryState entryState, string propertyName) { object obj2 = base.ReadNonEntityValue(null, null, null, true); ValidationUtils.ValidateOpenPropertyValue(propertyName, obj2); AddEntryProperty(entryState, propertyName, obj2); }
private ODataNavigationLink ReadUndeclaredProperty(IODataJsonReaderEntryState entryState, string propertyName) { bool flag = false; bool flag2 = false; if (base.JsonReader.NodeType == JsonNodeType.StartObject) { base.JsonReader.StartBuffering(); base.JsonReader.Read(); if (base.JsonReader.NodeType == JsonNodeType.Property) { string strA = base.JsonReader.ReadPropertyName(); if (string.CompareOrdinal(strA, "__deferred") == 0) { flag2 = true; } else if (string.CompareOrdinal(strA, "__mediaresource") == 0) { flag = true; } base.JsonReader.SkipValue(); if (base.JsonReader.NodeType != JsonNodeType.EndObject) { flag = false; flag2 = false; } } base.JsonReader.StopBuffering(); } if (flag || flag2) { if (!base.MessageReaderSettings.UndeclaredPropertyBehaviorKinds.HasFlag(ODataUndeclaredPropertyBehaviorKinds.ReportUndeclaredLinkProperty)) { throw new ODataException(Microsoft.Data.OData.Strings.ValidationUtils_PropertyDoesNotExistOnType(propertyName, entryState.EntityType.ODataFullName())); } } else if (!base.MessageReaderSettings.UndeclaredPropertyBehaviorKinds.HasFlag(ODataUndeclaredPropertyBehaviorKinds.IgnoreUndeclaredValueProperty)) { throw new ODataException(Microsoft.Data.OData.Strings.ValidationUtils_PropertyDoesNotExistOnType(propertyName, entryState.EntityType.ODataFullName())); } if (flag2) { ODataNavigationLink navigationLink = new ODataNavigationLink { Name = propertyName, IsCollection = null }; entryState.DuplicatePropertyNamesChecker.CheckForDuplicatePropertyNamesOnNavigationLinkStart(navigationLink); return(navigationLink); } if (flag) { object propertyValue = this.ReadStreamPropertyValue(); AddEntryProperty(entryState, propertyName, propertyValue); return(null); } base.JsonReader.SkipValue(); return(null); }
private static void AddEntryProperty(IODataJsonReaderEntryState entryState, string propertyName, object propertyValue) { ODataProperty property = new ODataProperty { Name = propertyName, Value = propertyValue }; entryState.DuplicatePropertyNamesChecker.CheckForDuplicatePropertyNames(property); ReaderUtils.AddPropertyToPropertiesList(entryState.Entry.Properties, property); }
private void ReadEntryProperty(IODataJsonReaderEntryState entryState, IEdmProperty edmProperty) { ODataNullValueBehaviorKind kind = base.ReadingResponse ? ODataNullValueBehaviorKind.Default : base.Model.NullValueReadBehaviorKind(edmProperty); IEdmTypeReference type = edmProperty.Type; object propertyValue = type.IsStream() ? this.ReadStreamPropertyValue() : base.ReadNonEntityValue(type, null, null, kind == ODataNullValueBehaviorKind.Default); if ((kind != ODataNullValueBehaviorKind.IgnoreValue) || (propertyValue != null)) { AddEntryProperty(entryState, edmProperty.Name, propertyValue); } }
protected override bool ReadAtNavigationLinkStartImplementation() { ODataNavigationLink currentNavigationLink = base.CurrentNavigationLink; IODataJsonReaderEntryState linkParentEntityScope = (IODataJsonReaderEntryState)base.LinkParentEntityScope; if (this.jsonInputContext.ReadingResponse && this.jsonEntryAndFeedDeserializer.IsDeferredLink(true)) { linkParentEntityScope.DuplicatePropertyNamesChecker.CheckForDuplicatePropertyNames(currentNavigationLink, false, currentNavigationLink.IsCollection); this.jsonEntryAndFeedDeserializer.ReadDeferredNavigationLink(currentNavigationLink); this.ReplaceScope(ODataReaderState.NavigationLinkEnd); } else if (!currentNavigationLink.IsCollection.Value) { if (!this.jsonInputContext.ReadingResponse && this.jsonEntryAndFeedDeserializer.IsEntityReferenceLink()) { linkParentEntityScope.DuplicatePropertyNamesChecker.CheckForDuplicatePropertyNames(currentNavigationLink, false, false); ODataEntityReferenceLink item = this.jsonEntryAndFeedDeserializer.ReadEntityReferenceLink(); this.EnterScope(ODataReaderState.EntityReferenceLink, item, null); } else { linkParentEntityScope.DuplicatePropertyNamesChecker.CheckForDuplicatePropertyNames(currentNavigationLink, true, false); if (this.jsonEntryAndFeedDeserializer.JsonReader.NodeType == JsonNodeType.PrimitiveValue) { this.EnterScope(ODataReaderState.EntryStart, null, base.CurrentEntityType); } else { this.ReadEntryStart(); } } } else { linkParentEntityScope.DuplicatePropertyNamesChecker.CheckForDuplicatePropertyNames(currentNavigationLink, true, true); if (this.jsonInputContext.ReadingResponse) { this.ReadFeedStart(true); } else { if ((this.jsonEntryAndFeedDeserializer.JsonReader.NodeType != JsonNodeType.StartObject) && (this.jsonEntryAndFeedDeserializer.JsonReader.NodeType != JsonNodeType.StartArray)) { throw new ODataException(Microsoft.Data.OData.Strings.ODataJsonReader_CannotReadFeedStart(this.jsonEntryAndFeedDeserializer.JsonReader.NodeType)); } bool isResultsWrapperExpected = this.jsonEntryAndFeedDeserializer.JsonReader.NodeType == JsonNodeType.StartObject; this.jsonEntryAndFeedDeserializer.ReadFeedStart(new ODataFeed(), isResultsWrapperExpected, true); this.CurrentJsonScope.FeedHasResultsWrapper = isResultsWrapperExpected; this.ReadExpandedCollectionNavigationLinkContentInRequest(); } } return(true); }
internal void ValidateEntryMetadata(IODataJsonReaderEntryState entryState) { ODataEntry entry = entryState.Entry; IEdmEntityType entityType = entryState.EntityType; if (base.Model.HasDefaultStream(entityType) && (entry.MediaResource == null)) { ODataStreamReferenceValue instance = null; ODataJsonReaderUtils.EnsureInstance <ODataStreamReferenceValue>(ref instance); entry.MediaResource = instance; } bool useDefaultFormatBehavior = base.UseDefaultFormatBehavior; ValidationUtils.ValidateEntryMetadata(entry, entityType, base.Model, useDefaultFormatBehavior); }
private void ReadPropertiesMetadataProperty(IODataJsonReaderEntryState entryState, ref ODataJsonReaderUtils.MetadataPropertyBitMask metadataPropertiesFoundBitField) { if (!base.ReadingResponse || (base.MessageReaderSettings.MaxProtocolVersion < ODataVersion.V3)) { base.JsonReader.SkipValue(); } else { ODataJsonReaderUtils.VerifyMetadataPropertyNotFound(ref metadataPropertiesFoundBitField, ODataJsonReaderUtils.MetadataPropertyBitMask.Properties, "properties"); if (base.JsonReader.NodeType != JsonNodeType.StartObject) { throw new ODataException(Microsoft.Data.OData.Strings.ODataJsonEntryAndFeedDeserializer_PropertyInEntryMustHaveObjectValue("properties", base.JsonReader.NodeType)); } base.JsonReader.ReadStartObject(); while (base.JsonReader.NodeType == JsonNodeType.Property) { string associationLinkName = base.JsonReader.ReadPropertyName(); ValidationUtils.ValidateAssociationLinkName(associationLinkName); ReaderValidationUtils.ValidateNavigationPropertyDefined(associationLinkName, entryState.EntityType, base.MessageReaderSettings); base.JsonReader.ReadStartObject(); while (base.JsonReader.NodeType == JsonNodeType.Property) { if (string.CompareOrdinal(base.JsonReader.ReadPropertyName(), "associationuri") == 0) { string propertyValue = base.JsonReader.ReadStringValue("associationuri"); ODataJsonReaderUtils.ValidateMetadataStringProperty(propertyValue, "associationuri"); ODataAssociationLink associationLink = new ODataAssociationLink { Name = associationLinkName, Url = base.ProcessUriFromPayload(propertyValue) }; ValidationUtils.ValidateAssociationLink(associationLink); entryState.DuplicatePropertyNamesChecker.CheckForDuplicatePropertyNames(associationLink); ReaderUtils.AddAssociationLinkToEntry(entryState.Entry, associationLink); } else { base.JsonReader.SkipValue(); } } base.JsonReader.ReadEndObject(); } base.JsonReader.ReadEndObject(); } }
/// <summary> /// Read an entry-level property and check its version compliance. /// </summary> /// <param name="entryState">The state of the reader for entry to read.</param> /// <param name="edmProperty">The EDM property of the property being read, or null if the property is an open property.</param> /// <remarks> /// Pre-Condition: The reader is positioned on the first node of the property value /// Post-Condition: JsonNodeType.Property: the next property of the entry /// JsonNodeType.EndObject: the end-object node of the entry /// </remarks> private void ReadEntryProperty(IODataJsonReaderEntryState entryState, IEdmProperty edmProperty) { Debug.Assert(entryState != null, "entryState != null"); Debug.Assert(edmProperty != null, "edmProperty != null"); this.JsonReader.AssertNotBuffering(); ODataNullValueBehaviorKind nullValueReadBehaviorKind = this.ReadingResponse ? ODataNullValueBehaviorKind.Default : this.Model.NullValueReadBehaviorKind(edmProperty); IEdmTypeReference propertyTypeReference = edmProperty.Type; object propertyValue = propertyTypeReference.IsStream() ? this.ReadStreamPropertyValue() : this.ReadNonEntityValue( propertyTypeReference, /*duplicatePropertyNamesChecker*/ null, /*collectionValidator*/ null, nullValueReadBehaviorKind == ODataNullValueBehaviorKind.Default); if (nullValueReadBehaviorKind != ODataNullValueBehaviorKind.IgnoreValue || propertyValue != null) { AddEntryProperty(entryState, edmProperty.Name, propertyValue); } this.JsonReader.AssertNotBuffering(); Debug.Assert( this.JsonReader.NodeType == JsonNodeType.Property || this.JsonReader.NodeType == JsonNodeType.EndObject, "Post-Condition: expected JsonNodeType.Property or JsonNodeType.EndObject"); }
/// <summary> /// Read an open property. /// </summary> /// <param name="entryState">The state of the reader for entry to read.</param> /// <param name="propertyName">The name of the open property to read.</param> /// <remarks> /// Pre-Condition: The reader is positioned on the first node of the property value /// Post-Condition: JsonNodeType.Property: the next property of the entry /// JsonNodeType.EndObject: the end-object node of the entry /// </remarks> private void ReadOpenProperty(IODataJsonReaderEntryState entryState, string propertyName) { Debug.Assert(entryState != null, "entryState != null"); Debug.Assert(!string.IsNullOrEmpty(propertyName), "!string.IsNullOrEmpty(propertyName)"); this.JsonReader.AssertNotBuffering(); object propertyValue = this.ReadNonEntityValue( /*expectedValueTypeReference*/ null, /*duplicatePropertyNamesChecker*/ null, /*collectionValidator*/ null, /*validateNullValue*/ true); ValidationUtils.ValidateOpenPropertyValue(propertyName, propertyValue); AddEntryProperty(entryState, propertyName, propertyValue); this.JsonReader.AssertNotBuffering(); Debug.Assert( this.JsonReader.NodeType == JsonNodeType.Property || this.JsonReader.NodeType == JsonNodeType.EndObject, "Post-Condition: expected JsonNodeType.Property or JsonNodeType.EndObject"); }
/// <summary> /// Reads the content of an entry until a navigation link is detected. /// </summary> /// <param name="entryState">The state of the reader for entry to read.</param> /// <param name="navigationProperty">If a navigation link was found this parameter will hold the navigation property for that link, otherwise it's null.</param> /// <returns>A <see cref="ODataNavigationLink"/> instance representing the navigation link detected while reading the entry contents; null if no navigation link was detected.</returns> /// <remarks> /// Pre-Condition: JsonNodeType.Property The property to read /// JsonNodeType.EndObject If no (more) properties exist in the entry's content /// Post-Condition: JsonNodeType.EndObject If no (more) properties exist in the entry's content /// JsonNodeType.StartObject The first node of the navigation link property value to read next /// (deferred link or entry inside expanded link or feed with 'results' wrapper inside expanded link) /// JsonNodeType.StartArray feed without 'results' wrapper inside of expanded link /// JsonNodeType.PrimitiveValue (null) Expanded null entry /// </remarks> internal ODataNavigationLink ReadEntryContent( IODataJsonReaderEntryState entryState, out IEdmNavigationProperty navigationProperty) { DebugUtils.CheckNoExternalCallers(); Debug.Assert(entryState != null, "entryState != null"); Debug.Assert(entryState.EntityType != null && this.Model.IsUserModel(), "A non-null entity type and non-null model are required."); Debug.Assert( this.JsonReader.NodeType == JsonNodeType.Property || this.JsonReader.NodeType == JsonNodeType.EndObject, "Pre-Condition: JsonNodeType.Property or JsonNodeType.EndObject"); this.JsonReader.AssertNotBuffering(); ODataNavigationLink navigationLink = null; navigationProperty = null; IEdmEntityType entityType = entryState.EntityType; Debug.Assert(entityType != null, "In JSON we must always have an entity type when reading entity."); // figure out whether we have more properties for this entry // read all the properties until we hit a link while (this.JsonReader.NodeType == JsonNodeType.Property) { string propertyName = this.JsonReader.ReadPropertyName(); // check the well-known property names first if (string.CompareOrdinal(JsonConstants.ODataMetadataName, propertyName) == 0) { // __metadata property if (entryState.MetadataPropertyFound) { throw new ODataException(o.Strings.ODataJsonEntryAndFeedDeserializer_MultipleMetadataPropertiesInEntryValue); } entryState.MetadataPropertyFound = true; // Just skip over the value since we should have already scanned ahead for it by now. this.JsonReader.SkipValue(); } else { if (!ValidationUtils.IsValidPropertyName(propertyName)) { this.JsonReader.SkipValue(); continue; } IEdmProperty edmProperty = ReaderValidationUtils.FindDefinedProperty(propertyName, entityType, this.MessageReaderSettings); if (edmProperty != null) { // Declared property - read it. navigationProperty = edmProperty as IEdmNavigationProperty; if (navigationProperty != null) { if (this.ShouldEntryPropertyBeSkipped()) { this.JsonReader.SkipValue(); } else { // this can be a deferred link or an expanded link (with entry or feed payload) bool isCollection = navigationProperty.Type.IsCollection(); navigationLink = new ODataNavigationLink { Name = propertyName, IsCollection = isCollection }; this.ValidateNavigationLinkPropertyValue(isCollection); entryState.DuplicatePropertyNamesChecker.CheckForDuplicatePropertyNamesOnNavigationLinkStart(navigationLink); } } else { // NOTE: we currently do not check whether the property should be skipped // here because this can only happen for navigation properties and open properties. this.ReadEntryProperty(entryState, edmProperty); } } else { if (entityType.IsOpen) { if (this.ShouldEntryPropertyBeSkipped()) { this.JsonReader.SkipValue(); } else { // Open property - read it as such. this.ReadOpenProperty(entryState, propertyName); } } else { // Undeclared property on a non-open type - we need to run detection alogorithm here. navigationLink = this.ReadUndeclaredProperty(entryState, propertyName); // Note that if navigation link is returned it's already validated, so we just report it here. } } } if (navigationLink != null) { // we found a navigation link // stop parsing the entry content and return to the caller break; } Debug.Assert( this.JsonReader.NodeType == JsonNodeType.Property || this.JsonReader.NodeType == JsonNodeType.EndObject, "After reading a property the reader should be positioned on another property or have hit the end of the object."); } this.JsonReader.AssertNotBuffering(); // The reader can be either on // - StartObject - if it's an expanded entry, or expanded feed wrapped with 'results' wrapper // - StartArray - if it's an expanded feed that is not wrapped with 'results' wrapper // - PrimitiveValue (null) - if it's an expanded null entry // - EndObject - end of the entry Debug.Assert( navigationLink != null && this.JsonReader.NodeType == JsonNodeType.StartObject || navigationLink != null && this.JsonReader.NodeType == JsonNodeType.StartArray || navigationLink != null && this.JsonReader.NodeType == JsonNodeType.PrimitiveValue && this.JsonReader.Value == null || this.JsonReader.NodeType == JsonNodeType.EndObject, "Post-Condition: expected JsonNodeType.StartObject or JsonNodeType.StartArray or JsonNodeType.EndObject or JsonNodeType.Primitive (with null value)"); return navigationLink; }
/// <summary> /// Adds a new property to an entry. /// </summary> /// <param name="entryState">The entry state for the entry to add the property to.</param> /// <param name="propertyName">The name of the property to add.</param> /// <param name="propertyValue">The value of the property to add.</param> private static void AddEntryProperty(IODataJsonReaderEntryState entryState, string propertyName, object propertyValue) { Debug.Assert(entryState != null, "entryState != null"); Debug.Assert(!string.IsNullOrEmpty(propertyName), "!string.IsNullOrEmpty(propertyName)"); ODataProperty property = new ODataProperty { Name = propertyName, Value = propertyValue }; entryState.DuplicatePropertyNamesChecker.CheckForDuplicatePropertyNames(property); ReaderUtils.AddPropertyToPropertiesList(entryState.Entry.Properties, property); }
/// <summary> /// Reads the entry metadata property. /// </summary> /// <param name="entryState">The state of the reader for entry to read.</param> /// <remarks> /// This method does not move the reader. /// Pre-Condition: JsonNodeType.Object The start object of the __metadata property value. /// Post-Condition: JsonNodeType.EndObject The end object of the __metadtaa property value. /// </remarks> internal void ReadEntryMetadataPropertyValue(IODataJsonReaderEntryState entryState) { DebugUtils.CheckNoExternalCallers(); this.AssertJsonCondition(JsonNodeType.StartObject); this.JsonReader.AssertBuffering(); ODataEntry entry = entryState.Entry; // read over the start-object node this.JsonReader.ReadStartObject(); ODataStreamReferenceValue mediaResource = null; ODataJsonReaderUtils.MetadataPropertyBitMask metadataPropertiesFoundBitField = 0; while (this.JsonReader.NodeType == JsonNodeType.Property) { string propertyName = this.JsonReader.ReadPropertyName(); switch (propertyName) { case JsonConstants.ODataMetadataUriName: // 'uri' this.ReadUriMetadataProperty(entry, ref metadataPropertiesFoundBitField); break; case JsonConstants.ODataEntryIdName: // 'id' this.ReadIdMetadataProperty(entry, ref metadataPropertiesFoundBitField); break; case JsonConstants.ODataMetadataETagName: // 'etag' this.ReadETagMetadataProperty(entry, ref metadataPropertiesFoundBitField); break; case JsonConstants.ODataMetadataTypeName: // 'type' // The type was already read and validated. this.JsonReader.SkipValue(); break; case JsonConstants.ODataMetadataMediaUriName: // 'media_src' this.ReadMediaSourceMetadataProperty(ref metadataPropertiesFoundBitField, ref mediaResource); break; case JsonConstants.ODataMetadataEditMediaName: // 'edit_media' this.ReadEditMediaMetadataProperty(ref metadataPropertiesFoundBitField, ref mediaResource); break; case JsonConstants.ODataMetadataContentTypeName: // 'content_type' this.ReadContentTypeMetadataProperty(ref metadataPropertiesFoundBitField, ref mediaResource); break; case JsonConstants.ODataMetadataMediaETagName: // 'media_etag' this.ReadMediaETagMetadataProperty(ref metadataPropertiesFoundBitField, ref mediaResource); break; case JsonConstants.ODataActionsMetadataName: // 'actions' this.ReadActionsMetadataProperty(entry, ref metadataPropertiesFoundBitField); break; case JsonConstants.ODataFunctionsMetadataName: // 'functions' this.ReadFunctionsMetadataProperty(entry, ref metadataPropertiesFoundBitField); break; case JsonConstants.ODataMetadataPropertiesName: // 'properties' this.ReadPropertiesMetadataProperty(entryState, ref metadataPropertiesFoundBitField); break; default: // ignore all extra properties in __metadata that we don't understand this.JsonReader.SkipValue(); break; } } entry.MediaResource = mediaResource; this.AssertJsonCondition(JsonNodeType.EndObject); }
/// <summary> /// Validates entry metadata properties against the model. /// </summary> /// <param name="entryState">The state of the reader for entry to read.</param> /// <remarks> /// This method must be called only after the ReadEntryMetadata was already called. /// It should be called always, regardless of whether the __metadata property was found ot not. /// </remarks> internal void ValidateEntryMetadata(IODataJsonReaderEntryState entryState) { DebugUtils.CheckNoExternalCallers(); Debug.Assert(entryState != null, "entryState != null"); ODataEntry entry = entryState.Entry; IEdmEntityType entityType = entryState.EntityType; Debug.Assert(entityType != null, "We should have resolved the entity type by now."); if (this.Model.HasDefaultStream(entityType) && entry.MediaResource == null) { ODataStreamReferenceValue mediaResource = null; ODataJsonReaderUtils.EnsureInstance(ref mediaResource); entry.MediaResource = mediaResource; } // By default validate the media resource. // In WCF DS Server mode, do not validate in JSON (here). // In WCF DS Client mode, do not validate. bool validateMediaResource = this.UseDefaultFormatBehavior; ValidationUtils.ValidateEntryMetadata(entry, entityType, this.Model, validateMediaResource); }
/// <summary> /// Read the property metadata for the properties of an entry being read. /// </summary> /// <param name="entryState">The entry state for the current reader.</param> /// <param name="metadataPropertiesFoundBitField">The bit fields with all the properties found in metadata value so far.</param> /// <remarks> /// Pre-Condition: first node of the 'properties' property's value (we will throw if this is not a start object node) /// Post-Condition: JsonNodeType.Property: the next metadata property /// JsonNodeType.EndObject: the end-object node of the metadata object /// /// This method will not validate anything against the model because it will read the type name and thus it can't rely /// on knowing the actual type of the entry being read. /// </remarks> private void ReadPropertiesMetadataProperty( IODataJsonReaderEntryState entryState, ref ODataJsonReaderUtils.MetadataPropertyBitMask metadataPropertiesFoundBitField) { Debug.Assert(entryState != null, "entryState != null"); if (!this.ReadingResponse || this.MessageReaderSettings.MaxProtocolVersion < ODataVersion.V3) { this.JsonReader.SkipValue(); return; } ODataJsonReaderUtils.VerifyMetadataPropertyNotFound( ref metadataPropertiesFoundBitField, ODataJsonReaderUtils.MetadataPropertyBitMask.Properties, JsonConstants.ODataMetadataPropertiesName); this.JsonReader.AssertBuffering(); // make sure the 'properties' property value is an object if (this.JsonReader.NodeType != JsonNodeType.StartObject) { throw new ODataException(o.Strings.ODataJsonEntryAndFeedDeserializer_PropertyInEntryMustHaveObjectValue(JsonConstants.ODataMetadataPropertiesName, this.JsonReader.NodeType)); } // read over the start-object node of the metadata object for 'properties' this.JsonReader.ReadStartObject(); while (this.JsonReader.NodeType == JsonNodeType.Property) { string propertyName = this.JsonReader.ReadPropertyName(); ValidationUtils.ValidateAssociationLinkName(propertyName); ReaderValidationUtils.ValidateNavigationPropertyDefined(propertyName, entryState.EntityType, this.MessageReaderSettings); // read the start-object node of the metadata for the current propertyName this.JsonReader.ReadStartObject(); while (this.JsonReader.NodeType == JsonNodeType.Property) { string innerPropertyName = this.JsonReader.ReadPropertyName(); // ignore all properties we don't understand if (string.CompareOrdinal(innerPropertyName, JsonConstants.ODataMetadataPropertiesAssociationUriName) == 0) { string associationUrlString = this.JsonReader.ReadStringValue(JsonConstants.ODataMetadataPropertiesAssociationUriName); ODataJsonReaderUtils.ValidateMetadataStringProperty(associationUrlString, JsonConstants.ODataMetadataPropertiesAssociationUriName); ODataAssociationLink associationLink = new ODataAssociationLink { Name = propertyName, Url = this.ProcessUriFromPayload(associationUrlString) }; ValidationUtils.ValidateAssociationLink(associationLink); entryState.DuplicatePropertyNamesChecker.CheckForDuplicatePropertyNames(associationLink); ReaderUtils.AddAssociationLinkToEntry(entryState.Entry, associationLink); } else { // skip over all unknown properties and read the next property or // the end of the metadata for the current propertyName this.JsonReader.SkipValue(); } } // read the end-object node of the metadata for the current propertyName this.JsonReader.ReadEndObject(); } // read over the end-object node of the metadata object for 'properties' this.JsonReader.ReadEndObject(); this.JsonReader.AssertBuffering(); Debug.Assert( this.JsonReader.NodeType == JsonNodeType.Property || this.JsonReader.NodeType == JsonNodeType.EndObject, "Post-Condition: expected JsonNodeType.Property or JsonNodeType.EndObject"); }
/// <summary> /// Read an undeclared property. That is a property which is not declared by the model, but the owning type is not an open type. /// </summary> /// <param name="entryState">The state of the reader for entry to read.</param> /// <param name="propertyName">The name of the open property to read.</param> /// <remarks> /// Pre-Condition: The reader is positioned on the first node of the property value /// Post-Condition: JsonNodeType.Property: the next property of the entry /// JsonNodeType.EndObject: the end-object node of the entry /// </remarks> /// <returns>A navigation link instance if the propery read is a navigation link which should be reported to the caller. /// Otherwise null if the property was either ignored or read and added to the list of properties on the entry.</returns> private ODataNavigationLink ReadUndeclaredProperty(IODataJsonReaderEntryState entryState, string propertyName) { Debug.Assert(entryState != null, "entryState != null"); Debug.Assert(!string.IsNullOrEmpty(propertyName), "!string.IsNullOrEmpty(propertyName)"); // Undeclared property // Detect whether it's a link property or value property. // Link properties are stream properties and deferred links. bool streamPropertyFound = false; bool deferredLinkFound = false; if (this.JsonReader.NodeType == JsonNodeType.StartObject) { this.JsonReader.StartBuffering(); // Both stream property and deferred link must be an object with exactly one property in it, with the right name. this.JsonReader.Read(); if (this.JsonReader.NodeType == JsonNodeType.Property) { string innerPropertyName = this.JsonReader.ReadPropertyName(); if (string.CompareOrdinal(innerPropertyName, JsonConstants.ODataDeferredName) == 0) { deferredLinkFound = true; } else if (string.CompareOrdinal(innerPropertyName, JsonConstants.ODataMetadataMediaResourceName) == 0) { streamPropertyFound = true; } this.JsonReader.SkipValue(); // The __mediaresource or __deferred is not the only property, so the value is not a stream property or deferred link. if (this.JsonReader.NodeType != JsonNodeType.EndObject) { streamPropertyFound = false; deferredLinkFound = false; } } this.JsonReader.StopBuffering(); } if (streamPropertyFound || deferredLinkFound) { // Undeclared link properties (stream property or deferred links) are reported if the right flag is used, otherwise we need to fail // reporting the undeclared property. if (!this.MessageReaderSettings.UndeclaredPropertyBehaviorKinds.HasFlag(ODataUndeclaredPropertyBehaviorKinds.ReportUndeclaredLinkProperty)) { throw new ODataException(o.Strings.ValidationUtils_PropertyDoesNotExistOnType(propertyName, entryState.EntityType.ODataFullName())); } } else { // Undeclared value properties (anything which doesn't look like stream property or deferred link) are ignored if the right flag is used, // otherwise we need to fail reporting the undeclared property. if (!this.MessageReaderSettings.UndeclaredPropertyBehaviorKinds.HasFlag(ODataUndeclaredPropertyBehaviorKinds.IgnoreUndeclaredValueProperty)) { throw new ODataException(o.Strings.ValidationUtils_PropertyDoesNotExistOnType(propertyName, entryState.EntityType.ODataFullName())); } } if (deferredLinkFound) { // We've found a deferred link - so report it (we've already checked the flags which allow this). ODataNavigationLink navigationLink = new ODataNavigationLink { Name = propertyName, IsCollection = null }; // Note - no need to validate the navigation link since we know it's a valid deferred link at least from the first object content. entryState.DuplicatePropertyNamesChecker.CheckForDuplicatePropertyNamesOnNavigationLinkStart(navigationLink); return navigationLink; } if (streamPropertyFound) { // We've found a stream property, so read it and report it (we've already checked the flags which allow this). object propertyValue = this.ReadStreamPropertyValue(); AddEntryProperty(entryState, propertyName, propertyValue); return null; } // Primitive, Complex, Collection or expanded link property, or property we don't recognize - treat all of these as value properties // and thus ignore them. // Note that in JSON expanded navigation links don't have the URL of the navigation link (the "href") // and thus we would have nothing to report even if the ReportUndeclaredLinkProperty would be set to true. // As such it's OK to treat them as value properties all up. this.JsonReader.SkipValue(); return null; }
internal ODataNavigationLink ReadEntryContent(IODataJsonReaderEntryState entryState, out IEdmNavigationProperty navigationProperty) { ODataNavigationLink navigationLink = null; navigationProperty = null; IEdmEntityType entityType = entryState.EntityType; while (base.JsonReader.NodeType == JsonNodeType.Property) { string strB = base.JsonReader.ReadPropertyName(); if (string.CompareOrdinal("__metadata", strB) == 0) { if (entryState.MetadataPropertyFound) { throw new ODataException(Microsoft.Data.OData.Strings.ODataJsonEntryAndFeedDeserializer_MultipleMetadataPropertiesInEntryValue); } entryState.MetadataPropertyFound = true; base.JsonReader.SkipValue(); } else { if (!ValidationUtils.IsValidPropertyName(strB)) { base.JsonReader.SkipValue(); continue; } IEdmProperty edmProperty = ReaderValidationUtils.FindDefinedProperty(strB, entityType, base.MessageReaderSettings); if (edmProperty != null) { navigationProperty = edmProperty as IEdmNavigationProperty; if (navigationProperty != null) { if (this.ShouldEntryPropertyBeSkipped()) { base.JsonReader.SkipValue(); } else { bool flag = navigationProperty.Type.IsCollection(); navigationLink = new ODataNavigationLink { Name = strB, IsCollection = new bool?(flag) }; this.ValidateNavigationLinkPropertyValue(flag); entryState.DuplicatePropertyNamesChecker.CheckForDuplicatePropertyNamesOnNavigationLinkStart(navigationLink); } } else { this.ReadEntryProperty(entryState, edmProperty); } } else if (entityType.IsOpen) { if (this.ShouldEntryPropertyBeSkipped()) { base.JsonReader.SkipValue(); } else { this.ReadOpenProperty(entryState, strB); } } else { navigationLink = this.ReadUndeclaredProperty(entryState, strB); } } if (navigationLink != null) { return navigationLink; } } return navigationLink; }
private ODataNavigationLink ReadUndeclaredProperty(IODataJsonReaderEntryState entryState, string propertyName) { bool flag = false; bool flag2 = false; if (base.JsonReader.NodeType == JsonNodeType.StartObject) { base.JsonReader.StartBuffering(); base.JsonReader.Read(); if (base.JsonReader.NodeType == JsonNodeType.Property) { string strA = base.JsonReader.ReadPropertyName(); if (string.CompareOrdinal(strA, "__deferred") == 0) { flag2 = true; } else if (string.CompareOrdinal(strA, "__mediaresource") == 0) { flag = true; } base.JsonReader.SkipValue(); if (base.JsonReader.NodeType != JsonNodeType.EndObject) { flag = false; flag2 = false; } } base.JsonReader.StopBuffering(); } if (flag || flag2) { if (!base.MessageReaderSettings.UndeclaredPropertyBehaviorKinds.HasFlag(ODataUndeclaredPropertyBehaviorKinds.ReportUndeclaredLinkProperty)) { throw new ODataException(Microsoft.Data.OData.Strings.ValidationUtils_PropertyDoesNotExistOnType(propertyName, entryState.EntityType.ODataFullName())); } } else if (!base.MessageReaderSettings.UndeclaredPropertyBehaviorKinds.HasFlag(ODataUndeclaredPropertyBehaviorKinds.IgnoreUndeclaredValueProperty)) { throw new ODataException(Microsoft.Data.OData.Strings.ValidationUtils_PropertyDoesNotExistOnType(propertyName, entryState.EntityType.ODataFullName())); } if (flag2) { ODataNavigationLink navigationLink = new ODataNavigationLink { Name = propertyName, IsCollection = null }; entryState.DuplicatePropertyNamesChecker.CheckForDuplicatePropertyNamesOnNavigationLinkStart(navigationLink); return navigationLink; } if (flag) { object propertyValue = this.ReadStreamPropertyValue(); AddEntryProperty(entryState, propertyName, propertyValue); return null; } base.JsonReader.SkipValue(); return null; }
internal void ReadEntryMetadataPropertyValue(IODataJsonReaderEntryState entryState) { ODataEntry entry = entryState.Entry; base.JsonReader.ReadStartObject(); ODataStreamReferenceValue mediaResource = null; ODataJsonReaderUtils.MetadataPropertyBitMask none = ODataJsonReaderUtils.MetadataPropertyBitMask.None; while (base.JsonReader.NodeType == JsonNodeType.Property) { switch (base.JsonReader.ReadPropertyName()) { case "uri": { this.ReadUriMetadataProperty(entry, ref none); continue; } case "id": { this.ReadIdMetadataProperty(entry, ref none); continue; } case "etag": { this.ReadETagMetadataProperty(entry, ref none); continue; } case "type": { base.JsonReader.SkipValue(); continue; } case "media_src": { this.ReadMediaSourceMetadataProperty(ref none, ref mediaResource); continue; } case "edit_media": { this.ReadEditMediaMetadataProperty(ref none, ref mediaResource); continue; } case "content_type": { this.ReadContentTypeMetadataProperty(ref none, ref mediaResource); continue; } case "media_etag": { this.ReadMediaETagMetadataProperty(ref none, ref mediaResource); continue; } case "actions": { this.ReadActionsMetadataProperty(entry, ref none); continue; } case "functions": { this.ReadFunctionsMetadataProperty(entry, ref none); continue; } case "properties": { this.ReadPropertiesMetadataProperty(entryState, ref none); continue; } } base.JsonReader.SkipValue(); } entry.MediaResource = mediaResource; }
internal ODataNavigationLink ReadEntryContent(IODataJsonReaderEntryState entryState, out IEdmNavigationProperty navigationProperty) { ODataNavigationLink navigationLink = null; navigationProperty = null; IEdmEntityType entityType = entryState.EntityType; while (base.JsonReader.NodeType == JsonNodeType.Property) { string strB = base.JsonReader.ReadPropertyName(); if (string.CompareOrdinal("__metadata", strB) == 0) { if (entryState.MetadataPropertyFound) { throw new ODataException(Microsoft.Data.OData.Strings.ODataJsonEntryAndFeedDeserializer_MultipleMetadataPropertiesInEntryValue); } entryState.MetadataPropertyFound = true; base.JsonReader.SkipValue(); } else { if (!ValidationUtils.IsValidPropertyName(strB)) { base.JsonReader.SkipValue(); continue; } IEdmProperty edmProperty = ReaderValidationUtils.FindDefinedProperty(strB, entityType, base.MessageReaderSettings); if (edmProperty != null) { navigationProperty = edmProperty as IEdmNavigationProperty; if (navigationProperty != null) { if (this.ShouldEntryPropertyBeSkipped()) { base.JsonReader.SkipValue(); } else { bool flag = navigationProperty.Type.IsCollection(); navigationLink = new ODataNavigationLink { Name = strB, IsCollection = new bool?(flag) }; this.ValidateNavigationLinkPropertyValue(flag); entryState.DuplicatePropertyNamesChecker.CheckForDuplicatePropertyNamesOnNavigationLinkStart(navigationLink); } } else { this.ReadEntryProperty(entryState, edmProperty); } } else if (entityType.IsOpen) { if (this.ShouldEntryPropertyBeSkipped()) { base.JsonReader.SkipValue(); } else { this.ReadOpenProperty(entryState, strB); } } else { navigationLink = this.ReadUndeclaredProperty(entryState, strB); } } if (navigationLink != null) { return(navigationLink); } } return(navigationLink); }
internal void ValidateEntryMetadata(IODataJsonReaderEntryState entryState) { ODataEntry entry = entryState.Entry; IEdmEntityType entityType = entryState.EntityType; if (base.Model.HasDefaultStream(entityType) && (entry.MediaResource == null)) { ODataStreamReferenceValue instance = null; ODataJsonReaderUtils.EnsureInstance<ODataStreamReferenceValue>(ref instance); entry.MediaResource = instance; } bool useDefaultFormatBehavior = base.UseDefaultFormatBehavior; ValidationUtils.ValidateEntryMetadata(entry, entityType, base.Model, useDefaultFormatBehavior); }