/// <summary> /// Creates a new instance of ODataAction or ODataFunction for the <paramref name="metadataReferencePropertyName"/>. /// </summary> /// <param name="readerContext">The Json operation deserializer context.</param> /// <param name="metadataReferencePropertyName">The name of the metadata reference property being read.</param> /// <returns>A new instance of ODataAction or ODataFunction for the <paramref name="metadataReferencePropertyName"/>.</returns> private ODataOperation CreateODataOperationAndAddToEntry(IODataJsonOperationsDeserializerContext readerContext, string metadataReferencePropertyName) { string fullyQualifiedOperationName = ODataJsonLightUtils.GetUriFragmentFromMetadataReferencePropertyName(this.ContextUriParseResult.MetadataDocumentUri, metadataReferencePropertyName); IEdmOperation firstActionOrFunction = this.JsonLightInputContext.Model.ResolveOperations(fullyQualifiedOperationName).FirstOrDefault(); bool isAction; if (firstActionOrFunction == null) { // Ignore the unknown function/action. return null; } var operation = ODataJsonLightUtils.CreateODataOperation(this.ContextUriParseResult.MetadataDocumentUri, metadataReferencePropertyName, firstActionOrFunction, out isAction); if (isAction) { readerContext.AddActionToEntry((ODataAction)operation); } else { readerContext.AddFunctionToEntry((ODataFunction)operation); } return operation; }
/// <summary> /// Reads one operation for the entry being read. /// </summary> /// <param name="readerContext">The Json operation deserializer context.</param> /// <param name="entryState">The state of the reader for entry to read.</param> /// <param name="metadataReferencePropertyName">The name of the metadata reference property being read.</param> /// <param name="insideArray">true if the operation value is inside an array, i.e. multiple targets for the operation; false otherwise.</param> /// <remarks> /// Pre-Condition: JsonNodeType.StartObject: first node of the operation value. /// Post-Condition: JsonNodeType.Property: the property after the current operation being read when there is one target for the operation. /// JsonNodeType.StartObject: the first node of the next operation value when there are multiple targets for the operation. /// JsonNodeType.EndArray: the end-array of the operation values when there are multiple target for the operation. /// </remarks> private void ReadSingleOperationValue(IODataJsonOperationsDeserializerContext readerContext, IODataJsonLightReaderEntryState entryState, string metadataReferencePropertyName, bool insideArray) { Debug.Assert(readerContext != null, "readerContext != null"); Debug.Assert(!string.IsNullOrEmpty(metadataReferencePropertyName), "!string.IsNullOrEmpty(metadataReferencePropertyName)"); Debug.Assert(ODataJsonLightUtils.IsMetadataReferenceProperty(metadataReferencePropertyName), "ODataJsonLightReaderUtils.IsMetadataReferenceProperty(metadataReferencePropertyName)"); if (readerContext.JsonReader.NodeType != JsonNodeType.StartObject) { throw new ODataException(ODataErrorStrings.ODataJsonOperationsDeserializerUtils_OperationsPropertyMustHaveObjectValue(metadataReferencePropertyName, readerContext.JsonReader.NodeType)); } // read over the start-object node of the metadata object for the operations readerContext.JsonReader.ReadStartObject(); var operation = this.CreateODataOperationAndAddToEntry(readerContext, metadataReferencePropertyName); // Ignore the unrecognized operation. if (operation == null) { while (readerContext.JsonReader.NodeType == JsonNodeType.Property) { readerContext.JsonReader.ReadPropertyName(); readerContext.JsonReader.SkipValue(); } readerContext.JsonReader.ReadEndObject(); return; } Debug.Assert(operation.Metadata != null, "operation.Metadata != null"); while (readerContext.JsonReader.NodeType == JsonNodeType.Property) { string operationPropertyName = ODataAnnotationNames.RemoveAnnotationPrefix(readerContext.JsonReader.ReadPropertyName()); switch (operationPropertyName) { case JsonConstants.ODataOperationTitleName: if (operation.Title != null) { throw new ODataException(ODataErrorStrings.ODataJsonLightEntryAndFeedDeserializer_MultipleOptionalPropertiesInOperation(operationPropertyName, metadataReferencePropertyName)); } string titleString = readerContext.JsonReader.ReadStringValue(JsonConstants.ODataOperationTitleName); ODataJsonLightValidationUtils.ValidateOperationPropertyValueIsNotNull(titleString, operationPropertyName, metadataReferencePropertyName); operation.Title = titleString; break; case JsonConstants.ODataOperationTargetName: if (operation.Target != null) { throw new ODataException(ODataErrorStrings.ODataJsonLightEntryAndFeedDeserializer_MultipleOptionalPropertiesInOperation(operationPropertyName, metadataReferencePropertyName)); } string targetString = readerContext.JsonReader.ReadStringValue(JsonConstants.ODataOperationTargetName); ODataJsonLightValidationUtils.ValidateOperationPropertyValueIsNotNull(targetString, operationPropertyName, metadataReferencePropertyName); operation.Target = readerContext.ProcessUriFromPayload(targetString); break; default: // skip over all unknown properties and read the next property or // the end of the metadata for the current propertyName readerContext.JsonReader.SkipValue(); break; } } if (operation.Target == null && insideArray) { throw new ODataException(ODataErrorStrings.ODataJsonLightEntryAndFeedDeserializer_OperationMissingTargetProperty(metadataReferencePropertyName)); } // read the end-object node of the target / title pair readerContext.JsonReader.ReadEndObject(); // Sets the metadata builder to evaluate by convention any operation property that's not on the wire. // Note we must only set this after the operation is read from the wire since we lose the ability to tell // what was on the wire and what is being dynamically computed. this.SetMetadataBuilder(entryState, operation); }