public void SetCollectionStartSerializationInfoShouldThrowOnNullCollectionStart() { ODataCollectionStart collectionStart = null; Action action = () => collectionStart.SetSerializationInfo(null); action.ShouldThrow <ArgumentNullException>().Where(e => e.Message.Contains("collectionStart")); }
/// <summary> /// Writes the start of a collection. /// </summary> /// <param name="collectionStart">The collection start to write.</param> /// <param name="itemTypeReference">The item type of the collection or null if no metadata is available.</param> internal void WriteCollectionStart(ODataCollectionStart collectionStart, IEdmTypeReference itemTypeReference) { Debug.Assert(collectionStart != null, "collectionStart != null"); if (this.writingTopLevelCollection) { // "{" this.JsonWriter.StartObjectScope(); // "@odata.context":... this.WriteContextUriProperty(ODataPayloadKind.Collection, () => ODataContextUrlInfo.Create(collectionStart.SerializationInfo, itemTypeReference)); // "@odata.count":... if (collectionStart.Count.HasValue) { this.ODataAnnotationWriter.WriteInstanceAnnotationName(ODataAnnotationNames.ODataCount); this.JsonWriter.WriteValue(collectionStart.Count.Value); } // "@odata.nextlink":... if (collectionStart.NextPageLink != null) { this.ODataAnnotationWriter.WriteInstanceAnnotationName(ODataAnnotationNames.ODataNextLink); this.JsonWriter.WriteValue(this.UriToString(collectionStart.NextPageLink)); } // "value": this.JsonWriter.WriteValuePropertyName(); } // Write the start of the array for the collection items // "[" this.JsonWriter.StartArrayScope(); }
public void SetCollectionStartSerializationInfoShouldThrowOnNullCollectionStart() { ODataCollectionStart collectionStart = null; Action action = () => collectionStart.SetSerializationInfo(null); action.ShouldThrow <ArgumentNullException>().WithMessage("collectionStart", ComparisonMode.Substring); }
/// <summary> /// Asynchronous implementation of the collection reader logic when in state 'Start'. /// </summary> /// <param name="propertyAndAnnotationCollector">The duplicate property names checker for the top-level scope.</param> /// <returns> /// A task that represents the asynchronous read operation. /// The value of the TResult parameter contains true if more items can be read from the reader; otherwise false. /// </returns> /// <remarks> /// Pre-Condition: JsonNodeType.None: assumes that the JSON reader has not been used yet when not reading a nested payload. /// Post-Condition: The reader is positioned on the first node of the first item or the EndArray node of an empty item array /// </remarks> private async Task <bool> ReadAtStartImplementationAsynchronously(PropertyAndAnnotationCollector propertyAndAnnotationCollector) { Debug.Assert(propertyAndAnnotationCollector != null, "propertyAndAnnotationCollector != null"); IEdmTypeReference actualItemTypeReference; this.ExpectedItemTypeReference = ReaderValidationUtils.ValidateCollectionContextUriAndGetPayloadItemTypeReference( this.jsonLightCollectionDeserializer.ContextUriParseResult, this.ExpectedItemTypeReference); // Read the start of the collection until we find the content array for top-level collections Tuple <ODataCollectionStart, IEdmTypeReference> readCollectionStartResult = await this.jsonLightCollectionDeserializer.ReadCollectionStartAsync( propertyAndAnnotationCollector, this.IsReadingNestedPayload, this.ExpectedItemTypeReference).ConfigureAwait(false); ODataCollectionStart collectionStart = readCollectionStartResult.Item1; actualItemTypeReference = readCollectionStartResult.Item2; if (actualItemTypeReference != null) { this.ExpectedItemTypeReference = actualItemTypeReference; } await this.jsonLightCollectionDeserializer.JsonReader.ReadStartArrayAsync() .ConfigureAwait(false); this.EnterScope(ODataCollectionReaderState.CollectionStart, collectionStart); return(true); }
private void WriteParameters(ODataMessageWriterTestWrapper messageWriter, ODataParameters parameters, IEdmOperationImport functionImport) { ODataParameterWriter parameterWriter = messageWriter.CreateODataParameterWriter(functionImport); parameterWriter.WriteStart(); foreach (var parameter in parameters) { ODataCollectionStart collectionStart = parameter.Value as ODataCollectionStart; ODataResourceSet feed; ODataResource entry; if (collectionStart != null) { ODataCollectionWriter collectionWriter = parameterWriter.CreateCollectionWriter(parameter.Key); this.WriteCollection(collectionWriter, collectionStart); collectionWriter.Flush(); } else if ((feed = parameter.Value as ODataResourceSet) != null) { this.WriteFeed(parameterWriter.CreateResourceSetWriter(parameter.Key), feed); } else if ((entry = parameter.Value as ODataResource) != null) { this.WriteEntry(parameterWriter.CreateResourceWriter(parameter.Key), entry); } else { parameterWriter.WriteValue(parameter.Key, parameter.Value); } } parameterWriter.WriteEnd(); parameterWriter.Flush(); }
internal ODataCollectionStart ReadCollectionStart(out bool isCollectionElementEmpty) { if (!base.XmlReader.NamespaceEquals(base.XmlReader.ODataNamespace)) { throw new ODataException(Microsoft.Data.OData.Strings.ODataAtomCollectionDeserializer_TopLevelCollectionElementWrongNamespace(base.XmlReader.NamespaceURI, base.XmlReader.ODataNamespace)); } while (base.XmlReader.MoveToNextAttribute()) { if (base.XmlReader.NamespaceEquals(base.XmlReader.ODataMetadataNamespace) && (base.XmlReader.LocalNameEquals(base.AtomTypeAttributeName) || base.XmlReader.LocalNameEquals(base.ODataNullAttributeName))) { throw new ODataException(Microsoft.Data.OData.Strings.ODataAtomCollectionDeserializer_TypeOrNullAttributeNotAllowed); } } base.XmlReader.MoveToElement(); ODataCollectionStart start = new ODataCollectionStart { Name = base.XmlReader.LocalName }; isCollectionElementEmpty = base.XmlReader.IsEmptyElement; if (!isCollectionElementEmpty) { base.XmlReader.Read(); } return(start); }
public async Task WriteCollectionAsync() { var result = await SetupJsonLightOutputContextAndRunTestAsync( async (jsonLightOutputContext) => { var collectionWriter = await jsonLightOutputContext.CreateODataCollectionWriterAsync(EdmCoreModel.Instance.GetString(false)); var collectionStart = new ODataCollectionStart { SerializationInfo = new ODataCollectionStartSerializationInfo { CollectionTypeName = "Collection(Edm.String)" } }; await collectionWriter.WriteStartAsync(collectionStart); await collectionWriter.WriteItemAsync("Violet"); await collectionWriter.WriteItemAsync("Indigo"); await collectionWriter.WriteItemAsync("Blue"); await collectionWriter.WriteEndAsync(); }); Assert.Equal( "{\"@odata.context\":\"http://tempuri.org/$metadata#Collection(Edm.String)\",\"value\":[\"Violet\",\"Indigo\",\"Blue\"]}", result); }
protected override void WriteTopLevelElements(IExpandedResult expanded, IEnumerator elements, bool hasMoved) { if (base.RequestDescription.LinkUri) { bool needPop = base.PushSegmentForRoot(); this.WriteLinkCollection(elements, hasMoved); base.PopSegmentName(needPop); } else { this.collectionWriter = this.writer.CreateODataCollectionWriter(); ODataCollectionStart collectionStart = new ODataCollectionStart { Name = this.ComputeContainerName() }; this.collectionWriter.WriteStart(collectionStart); while (hasMoved) { object current = elements.Current; ResourceType propertyResourceType = (current == null) ? base.RequestDescription.TargetResourceType : WebUtil.GetResourceType(base.Provider, current); if (propertyResourceType == null) { throw new InvalidOperationException(System.Data.Services.Strings.Serializer_UnsupportedTopLevelType(current.GetType())); } this.collectionWriter.WriteItem(base.GetPropertyValue("element", propertyResourceType, current, false)); hasMoved = elements.MoveNext(); } this.collectionWriter.WriteEnd(); this.collectionWriter.Flush(); } }
/// <summary> /// Start writing a collection. /// </summary> /// <param name="collectionStart">The <see cref="ODataCollectionStart"/> representing the collection.</param> protected override void StartCollection(ODataCollectionStart collectionStart) { Debug.Assert(collectionStart != null, "collection != null"); string collectionName = collectionStart.Name; if (collectionName == null) { // null collection names are not allowed in ATOM throw new ODataException(ODataErrorStrings.ODataAtomCollectionWriter_CollectionNameMustNotBeNull); } // Note that we don't perform metadata validation of the name of the collection. // This is because there are multiple possibilities (service operation, action, function, top-level property) // and without more information we can't know which one to look for. // <collectionName> this.atomOutputContext.XmlWriter.WriteStartElement(collectionName, this.atomCollectionSerializer.MessageWriterSettings.WriterBehavior.ODataNamespace); // xmlns:="ODataNamespace" this.atomOutputContext.XmlWriter.WriteAttributeString( AtomConstants.XmlnsNamespacePrefix, AtomConstants.XmlNamespacesNamespace, this.atomCollectionSerializer.MessageWriterSettings.WriterBehavior.ODataNamespace); this.atomCollectionSerializer.WriteDefaultNamespaceAttributes( ODataAtomSerializer.DefaultNamespaceFlags.ODataMetadata | ODataAtomSerializer.DefaultNamespaceFlags.Gml | ODataAtomSerializer.DefaultNamespaceFlags.GeoRss); }
public ODataJsonLightCollectionWriterTests() { collectionStartWithoutSerializationInfo = new ODataCollectionStart(); collectionStartWithSerializationInfo = new ODataCollectionStart(); collectionStartWithSerializationInfo.SetSerializationInfo(new ODataCollectionStartSerializationInfo { CollectionTypeName = "Collection(ns.Address)" }); address = new ODataComplexValue { Properties = new[] { new ODataProperty { Name = "Street", Value = "1 Microsoft Way" }, new ODataProperty { Name = "Zipcode", Value = 98052 }, new ODataProperty { Name = "State", Value = new ODataEnumValue("WA", "ns.StateEnum") } } }; items = new[] { address }; EdmComplexType addressType = new EdmComplexType("ns", "Address"); addressType.AddProperty(new EdmStructuralProperty(addressType, "Street", EdmCoreModel.Instance.GetString(isNullable: true))); addressType.AddProperty(new EdmStructuralProperty(addressType, "Zipcode", EdmCoreModel.Instance.GetInt32(isNullable: true))); var stateEnumType = new EdmEnumType("ns", "StateEnum", isFlags: true); stateEnumType.AddMember("IL", new EdmIntegerConstant(1)); stateEnumType.AddMember("WA", new EdmIntegerConstant(2)); addressType.AddProperty(new EdmStructuralProperty(addressType, "State", new EdmEnumTypeReference(stateEnumType, true))); addressTypeReference = new EdmComplexTypeReference(addressType, isNullable: false); }
public async Task WriteCollectionEndAsync_ForTopLevelCollection() { var collectionStart = new ODataCollectionStart { Name = "Products", SerializationInfo = new ODataCollectionStartSerializationInfo { CollectionTypeName = "Collection(Product)" }, NextPageLink = new Uri("http://tempuri.org/Products?$skiptoken=Id-5"), Count = 10 }; var itemTypeReference = new EdmEntityTypeReference(this.entityType, false); var result = await SetupODataJsonLightCollectionSerializerAndRunTestAsync( async (jsonLightCollectionSerializer) => { await jsonLightCollectionSerializer.WriteCollectionStartAsync(collectionStart, itemTypeReference); await jsonLightCollectionSerializer.WriteCollectionEndAsync(); }, /* container */ null, /* writeTopLevelCollection */ true); Assert.Equal( "{\"@odata.context\":\"http://tempuri.org/$metadata#Collection(Product)\"," + "\"@odata.count\":10," + "\"@odata.nextLink\":\"http://tempuri.org/Products?$skiptoken=Id-5\"," + "\"value\":[]}", result); }
/// <summary> /// Writes the start of a collection. /// </summary> /// <param name="collectionStart">The collection start to write.</param> /// <param name="itemTypeReference">The item type of the collection or null if no metadata is available.</param> internal void WriteCollectionStart(ODataCollectionStart collectionStart, IEdmTypeReference itemTypeReference) { Debug.Assert(collectionStart != null, "collectionStart != null"); if (this.writingTopLevelCollection) { // "{" this.JsonWriter.StartObjectScope(); // "@odata.context":... this.WriteContextUriProperty(ODataPayloadKind.Collection, () => ODataContextUrlInfo.Create(collectionStart.SerializationInfo, itemTypeReference)); // "@odata.count":... if (collectionStart.Count.HasValue) { this.JsonWriter.WriteInstanceAnnotationName(ODataAnnotationNames.ODataCount); this.JsonWriter.WriteValue(collectionStart.Count.Value); } // "@odata.nextlink":... if (collectionStart.NextPageLink != null) { this.JsonWriter.WriteInstanceAnnotationName(ODataAnnotationNames.ODataNextLink); this.JsonWriter.WriteValue(this.UriToString(collectionStart.NextPageLink)); } // "value": this.JsonWriter.WriteValuePropertyName(); } // Write the start of the array for the collection items // "[" this.JsonWriter.StartArrayScope(); }
/// <summary> /// Implementation of the collection reader logic when in state 'Start'. /// </summary> /// <returns>true if more items can be read from the reader; otherwise false.</returns> /// <remarks> /// Pre-Condition: JsonNodeType.None: assumes that the JSON reader has not been used yet when not reading a nested payload. /// Post-Condition: The reader is positioned on the first node of the first item or the EndArray node of an empty item array /// </remarks> protected override bool ReadAtStartImplementation() { Debug.Assert(this.State == ODataCollectionReaderState.Start, "this.State == ODataCollectionReaderState.Start"); Debug.Assert(this.IsReadingNestedPayload || this.jsonCollectionDeserializer.JsonReader.NodeType == JsonNodeType.None, "Pre-Condition: expected JsonNodeType.None when not reading a nested payload."); // read the data wrapper depending on whether we are reading a request or response this.jsonCollectionDeserializer.ReadPayloadStart(this.IsReadingNestedPayload); if (this.IsResultsWrapperExpected && this.jsonCollectionDeserializer.JsonReader.NodeType != JsonNodeType.StartObject) { throw new ODataException(o.Strings.ODataJsonCollectionReader_CannotReadWrappedCollectionStart(this.jsonCollectionDeserializer.JsonReader.NodeType)); } if (!this.IsResultsWrapperExpected && this.jsonCollectionDeserializer.JsonReader.NodeType != JsonNodeType.StartArray) { throw new ODataException(o.Strings.ODataJsonCollectionReader_CannotReadCollectionStart(this.jsonCollectionDeserializer.JsonReader.NodeType)); } // read the start of the collection until we find the content array ODataCollectionStart collectionStart = this.jsonCollectionDeserializer.ReadCollectionStart(this.IsResultsWrapperExpected); this.jsonCollectionDeserializer.JsonReader.ReadStartArray(); this.EnterScope(ODataCollectionReaderState.CollectionStart, collectionStart); return(true); }
private static ODataCollectionStart GetCollectionStart(ODataSerializerContext writeContext) { ODataCollectionStart collectionStart = new ODataCollectionStart { Name = writeContext.RootElementName }; if (writeContext.Request != null) { if (writeContext.InternalRequest.Context.NextLink != null) { collectionStart.NextPageLink = writeContext.InternalRequest.Context.NextLink; } else if (writeContext.InternalRequest.Context.QueryOptions != null) { // Collection serializer is called only for collection of primitive values - A null object will be supplied since it is a non-entity value SkipTokenHandler skipTokenHandler = writeContext.QueryOptions.Context.GetSkipTokenHandler(); collectionStart.NextPageLink = skipTokenHandler.GenerateNextPageLink(writeContext.InternalRequest.RequestUri, writeContext.InternalRequest.Context.PageSize, null, writeContext); } if (writeContext.InternalRequest.Context.TotalCount != null) { collectionStart.Count = writeContext.InternalRequest.Context.TotalCount; } } return(collectionStart); }
/// <summary> /// Implementation of the collection reader logic when in state 'Start'. /// </summary> /// <param name="duplicatePropertyNamesChecker">The duplicate property names checker for the top-level scope.</param> /// <returns>true if more items can be read from the reader; otherwise false.</returns> /// <remarks> /// Pre-Condition: JsonNodeType.None: assumes that the JSON reader has not been used yet when not reading a nested payload. /// Post-Condition: The reader is positioned on the first node of the first item or the EndArray node of an empty item array /// </remarks> private bool ReadAtStartImplementationSynchronously(DuplicatePropertyNamesChecker duplicatePropertyNamesChecker) { Debug.Assert(duplicatePropertyNamesChecker != null, "duplicatePropertyNamesChecker != null"); IEdmTypeReference actualItemTypeReference; this.ExpectedItemTypeReference = ReaderValidationUtils.ValidateCollectionContextUriAndGetPayloadItemTypeReference( this.jsonLightCollectionDeserializer.ContextUriParseResult, this.ExpectedItemTypeReference); // read the start of the collection until we find the content array for top-level collections ODataCollectionStart collectionStart = this.jsonLightCollectionDeserializer.ReadCollectionStart( duplicatePropertyNamesChecker, this.IsReadingNestedPayload, this.ExpectedItemTypeReference, out actualItemTypeReference); if (actualItemTypeReference != null) { this.ExpectedItemTypeReference = actualItemTypeReference; } this.jsonLightCollectionDeserializer.JsonReader.ReadStartArray(); this.EnterScope(ODataCollectionReaderState.CollectionStart, collectionStart); return(true); }
public async Task WriteCollectionStartAsync_ForTopLevelCollectionWithItemCount() { var collectionStart = new ODataCollectionStart { SerializationInfo = new ODataCollectionStartSerializationInfo { CollectionTypeName = "Collection(Product)" }, Count = 10 }; var itemTypeReference = new EdmEntityTypeReference(this.entityType, false); var result = await SetupODataJsonLightCollectionSerializerAndRunTestAsync( (jsonLightCollectionSerializer) => { return(jsonLightCollectionSerializer.WriteCollectionStartAsync(collectionStart, itemTypeReference)); }, /* container */ null, /* writeTopLevelCollection */ true); Assert.Equal( "{\"@odata.context\":\"http://tempuri.org/$metadata#Collection(Product)\"," + "\"@odata.count\":10," + "\"value\":[", result); }
/// <summary> /// Writes the given <paramref name="graph"/> using the given <paramref name="writer"/>. /// </summary> /// <param name="writer">The <see cref="ODataCollectionWriter"/> to use.</param> /// <param name="graph">The collection to write.</param> /// <param name="collectionType">The EDM type of the collection.</param> /// <param name="writeContext">The serializer context.</param> public async Task WriteCollectionAsync(ODataCollectionWriter writer, object graph, IEdmTypeReference collectionType, ODataSerializerContext writeContext) { if (writer == null) { throw Error.ArgumentNull("writer"); } ODataCollectionStart collectionStart = GetCollectionStart(writeContext); await writer.WriteStartAsync(collectionStart); if (graph != null) { ODataCollectionValue collectionValue = CreateODataValue(graph, collectionType, writeContext) as ODataCollectionValue; if (collectionValue != null) { foreach (object item in collectionValue.Items) { await writer.WriteItemAsync(item); } } } await writer.WriteEndAsync(); }
public async Task WriteStartAsync_WritesCollectionStart() { var model = new EdmModel(); var productEntityType = new EdmEntityType("NS", "Product"); productEntityType.AddKeys(productEntityType.AddStructuralProperty("Id", EdmPrimitiveTypeKind.Int32)); productEntityType.AddStructuralProperty("Name", EdmPrimitiveTypeKind.String); model.AddElement(productEntityType); var collectionStart = new ODataCollectionStart { SerializationInfo = new ODataCollectionStartSerializationInfo { CollectionTypeName = "Collection(NS.Product)" } }; var itemTypeReference = new EdmEntityTypeReference(productEntityType, true); var result = await SetupJsonLightCollectionWriterAndRunTestAsync( async (jsonLightCollectionWriter) => { await jsonLightCollectionWriter.WriteStartAsync(collectionStart); await jsonLightCollectionWriter.FlushAsync(); }, model, itemTypeReference); Assert.Equal("{\"@odata.context\":\"http://odata.org/test/$metadata#Collection(NS.Product)\"," + "\"value\":[", result); }
public async Task WriteItemAsync_WritesEnumCollectionItem(string enumValue, string expected) { var model = new EdmModel(); var colorEnumType = new EdmEnumType("NS", "Color"); colorEnumType.AddMember(new EdmEnumMember(colorEnumType, "Black", new EdmEnumMemberValue(0))); colorEnumType.AddMember(new EdmEnumMember(colorEnumType, "White", new EdmEnumMemberValue(0))); model.AddElement(colorEnumType); var collectionStart = new ODataCollectionStart { SerializationInfo = new ODataCollectionStartSerializationInfo { CollectionTypeName = "Collection(NS.Color)" } }; var itemTypeReference = new EdmEnumTypeReference(colorEnumType, true); var result = await SetupJsonLightCollectionWriterAndRunTestAsync( async (jsonLightCollectionWriter) => { await jsonLightCollectionWriter.WriteStartAsync(collectionStart); await jsonLightCollectionWriter.WriteItemAsync(new ODataEnumValue(enumValue)); await jsonLightCollectionWriter.WriteEndAsync(); }, model, itemTypeReference); Assert.Equal("{\"@odata.context\":\"http://odata.org/test/$metadata#Collection(NS.Color)\"," + $"\"value\":[{expected}]}}", result); }
public void SetCollectionStartSerializationInfoShouldThrowOnNullCollectionStart() { ODataCollectionStart collectionStart = null; Action action = () => collectionStart.SetSerializationInfo(null); Assert.Throws <ArgumentNullException>("collectionStart", action); }
public ODataJsonLightInheritComplexCollectionWriterTests() { collectionStartWithoutSerializationInfo = new ODataCollectionStart(); collectionStartWithSerializationInfo = new ODataCollectionStart(); collectionStartWithSerializationInfo.SetSerializationInfo(new ODataCollectionStartSerializationInfo { CollectionTypeName = "Collection(ns.Address)" }); address = new ODataComplexValue { Properties = new[] { new ODataProperty { Name = "Street", Value = "1 Microsoft Way" }, new ODataProperty { Name = "Zipcode", Value = 98052 }, new ODataProperty { Name = "State", Value = new ODataEnumValue("WA", "ns.StateEnum") }, new ODataProperty { Name = "City", Value = "Shanghai" } }, TypeName = "TestNamespace.DerivedAddress" }; items = new[] { address }; EdmComplexType addressType = new EdmComplexType("ns", "Address"); addressType.AddProperty(new EdmStructuralProperty(addressType, "Street", EdmCoreModel.Instance.GetString(isNullable: true))); addressType.AddProperty(new EdmStructuralProperty(addressType, "Zipcode", EdmCoreModel.Instance.GetInt32(isNullable: true))); var stateEnumType = new EdmEnumType("ns", "StateEnum", isFlags: true); stateEnumType.AddMember("IL", new EdmIntegerConstant(1)); stateEnumType.AddMember("WA", new EdmIntegerConstant(2)); addressType.AddProperty(new EdmStructuralProperty(addressType, "State", new EdmEnumTypeReference(stateEnumType, true))); EdmComplexType derivedAddressType = new EdmComplexType("ns", "DerivedAddress", addressType, false); derivedAddressType.AddProperty(new EdmStructuralProperty(derivedAddressType, "City", EdmCoreModel.Instance.GetString(isNullable: true))); addressTypeReference = new EdmComplexTypeReference(addressType, isNullable: false); derivedAddressTypeReference = new EdmComplexTypeReference(derivedAddressType, isNullable: false); }
/// <summary> /// Writes the start of a collection. /// </summary> /// <param name="collectionStart">The collection start to write.</param> /// <param name="itemTypeReference">The item type of the collection or null if no metadata is available.</param> internal void WriteCollectionStart(ODataCollectionStart collectionStart, IEdmTypeReference itemTypeReference) { DebugUtils.CheckNoExternalCallers(); Debug.Assert(collectionStart != null, "collectionStart != null"); if (this.writingTopLevelCollection) { // "{" this.JsonWriter.StartObjectScope(); // "odata.metadata":... Uri metadataUri; if (this.metadataUriBuilder.TryBuildCollectionMetadataUri(collectionStart.SerializationInfo, itemTypeReference, out metadataUri)) { this.WriteMetadataUriProperty(metadataUri); } // "value": this.JsonWriter.WriteValuePropertyName(); } // Write the start of the array for the collection items // "[" this.JsonWriter.StartArrayScope(); }
private void WriteCollection(ODataMessageWriterTestWrapper messageWriter, ODataCollectionStart collection) { ODataCollectionWriter collectionWriter = messageWriter.CreateODataCollectionWriter(); this.WriteCollection(collectionWriter, collection); collectionWriter.Flush(); }
/// <summary> /// Writes the given <paramref name="graph"/> using the given <paramref name="writer"/>. /// </summary> /// <param name="writer">The <see cref="ODataCollectionWriter"/> to use.</param> /// <param name="graph">The collection to write.</param> /// <param name="collectionType">The EDM type of the collection.</param> /// <param name="writeContext">The serializer context.</param> public void WriteCollection(ODataCollectionWriter writer, object graph, IEdmTypeReference collectionType, ODataSerializerContext writeContext) { if (writer == null) { throw Error.ArgumentNull("writer"); } ODataCollectionStart collectionStart = new ODataCollectionStart { Name = writeContext.RootElementName }; if (writeContext.Request != null) { if (writeContext.Request.ODataProperties().NextLink != null) { collectionStart.NextPageLink = writeContext.Request.ODataProperties().NextLink; } if (writeContext.Request.ODataProperties().TotalCount != null) { collectionStart.Count = writeContext.Request.ODataProperties().TotalCount; } } bool doNotSerializeIfNull = false; bool serializeAsEmptyIfNull = false; if (writeContext.Request != null) { var config = writeContext.Request.GetConfiguration(); if (config != null) { doNotSerializeIfNull = config.GetDoNotSerializeNullCollections(); serializeAsEmptyIfNull = config.GetSerializeNullCollectionsAsEmpty(); } } if (graph == null && doNotSerializeIfNull) { return; } writer.WriteStart(collectionStart); if (graph != null || !serializeAsEmptyIfNull) { ODataCollectionValue collectionValue = CreateODataValue(graph, collectionType, writeContext) as ODataCollectionValue; if (collectionValue != null) { foreach (object item in collectionValue.Items) { writer.WriteItem(item); } } } writer.WriteEnd(); }
public void ShouldWriteContextUriBasedOnSerializationInfoForComplexCollectionRequestWithoutUserModelWhenBothItemTypeAndSerializationInfoAreGiven() { ODataCollectionStart collectionStart = new ODataCollectionStart(); collectionStart.SetSerializationInfo(new ODataCollectionStartSerializationInfo { CollectionTypeName = "Collection(foo.bar)" }); WriteAndValidate(collectionStart, this.items, "{\"@odata.context\":\"http://odata.org/test/$metadata#Collection(foo.bar)\",\"value\":[{\"Street\":\"1 Microsoft Way\",\"Zipcode\":98052,\"State\":\"WA\",\"City\":\"Shanghai\"}]}", writingResponse: false, itemTypeReference: this.derivedAddressTypeReference); }
protected override bool ReadAtStartImplementation() { bool flag; this.atomCollectionDeserializer.ReadPayloadStart(); ODataCollectionStart item = this.atomCollectionDeserializer.ReadCollectionStart(out flag); base.EnterScope(ODataCollectionReaderState.CollectionStart, item, flag); return(true); }
public void ShouldBeAbleToSetTheCollectionStartSerializationInfo() { ODataCollectionStart collectionStart = new ODataCollectionStart(); ODataCollectionStartSerializationInfo serializationInfo = new ODataCollectionStartSerializationInfo { CollectionTypeName = "Collection(Edm.String)" }; collectionStart.SetSerializationInfo(serializationInfo); Assert.Same(serializationInfo, collectionStart.SerializationInfo); }
public void PropertySettersNullTest() { ODataCollectionStart odataCollectionStart = new ODataCollectionStart() { Name = "DummyName" }; odataCollectionStart.Name = null; this.Assert.IsNull(odataCollectionStart.Name, "Expected null value for property 'Name'."); }
public void ShouldBeAbleToClearTheCollectionStartSerializationInfo() { ODataCollectionStart collectionStart = new ODataCollectionStart(); ODataCollectionStartSerializationInfo serializationInfo = new ODataCollectionStartSerializationInfo { CollectionTypeName = "Collection(Edm.String)" }; collectionStart.SerializationInfo = serializationInfo; collectionStart.SetSerializationInfo(null); Assert.Null(collectionStart.SerializationInfo); }
/// <summary> /// Start writing a collection. /// </summary> /// <param name="collection">The <see cref="ODataCollectionStart"/> representing the collection.</param> public override void WriteStart(ODataCollectionStart collection) { if (this.testConfiguration.Synchronous) { this.collectionWriter.WriteStart(collection); } else { this.collectionWriter.WriteStartAsync(collection).Wait(); } }
/// <summary> /// Visits a collection start. /// </summary> /// <param name="collection">The collection start to visit.</param> protected virtual void VisitCollectionStart(ODataCollectionStart collectionStart) { ODataCollectionItemsObjectModelAnnotation items = collectionStart.GetAnnotation <ODataCollectionItemsObjectModelAnnotation>(); if (items != null) { foreach (object item in items) { this.Visit(item); } } }
/// <summary> /// Writes the given <paramref name="graph"/> using the given <paramref name="writer"/>. /// </summary> /// <param name="writer">The <see cref="ODataCollectionWriter"/> to use.</param> /// <param name="graph">The collection to write.</param> /// <param name="collectionType">The EDM type of the collection.</param> /// <param name="writeContext">The serializer context.</param> public virtual void WriteCollection(ODataCollectionWriter writer, object graph, IEdmTypeReference collectionType, ODataSerializerContext writeContext) { if (writer == null) { throw Error.ArgumentNull(nameof(writer)); } if (writeContext == null) { throw Error.ArgumentNull(nameof(writeContext)); } ODataCollectionStart collectionStart = new ODataCollectionStart { Name = writeContext.RootElementName }; if (writeContext.Request != null) { ODataFeature odataFeature = writeContext.Request.ODataFeature() as ODataFeature; if (odataFeature.NextLink != null) { collectionStart.NextPageLink = odataFeature.NextLink; } else if (odataFeature.QueryOptions != null) { // Collection serializer is called only for collection of primitive values - A null object will be supplied since it is a non-entity value SkipTokenHandler skipTokenHandler = writeContext.QueryOptions.Context.GetSkipTokenHandler(); collectionStart.NextPageLink = skipTokenHandler.GenerateNextPageLink(new Uri(writeContext.Request.GetEncodedUrl()), odataFeature.PageSize, null, writeContext); } if (odataFeature.TotalCount != null) { collectionStart.Count = odataFeature.TotalCount; } } writer.WriteStart(collectionStart); if (graph != null) { ODataCollectionValue collectionValue = CreateODataValue(graph, collectionType, writeContext) as ODataCollectionValue; if (collectionValue != null) { foreach (object item in collectionValue.Items) { writer.WriteItem(item); } } } writer.WriteEnd(); }
/// <summary> /// Reads the start element of a collection. /// </summary> /// <param name="isCollectionElementEmpty">true, if the collection element is empty; false otherwise.</param> /// <returns>An <see cref="ODataCollectionStart"/> representing the collection-level information. Currently this only contains /// the name of the collection.</returns> /// <remarks> /// Pre-Condition: XmlNodeType.Element - The start element of the collection. /// Post-Condition: Any - The next node after the start element node of the collection or the /// empty collection element node. /// </remarks> internal ODataCollectionStart ReadCollectionStart(out bool isCollectionElementEmpty) { this.XmlReader.AssertNotBuffering(); this.AssertXmlCondition(XmlNodeType.Element); if (!this.XmlReader.NamespaceEquals(this.XmlReader.ODataMetadataNamespace)) { throw new ODataException(ODataErrorStrings.ODataAtomCollectionDeserializer_TopLevelCollectionElementWrongNamespace(this.XmlReader.NamespaceURI, this.XmlReader.ODataMetadataNamespace)); } while (this.XmlReader.MoveToNextAttribute()) { if (this.XmlReader.NamespaceEquals(this.XmlReader.ODataMetadataNamespace) && (this.XmlReader.LocalNameEquals(this.AtomTypeAttributeName) || (this.XmlReader.LocalNameEquals(this.ODataNullAttributeName)))) { // make sure that m:type or m:null attributes are not present in the root element of the collection. throw new ODataException(ODataErrorStrings.ODataAtomCollectionDeserializer_TypeOrNullAttributeNotAllowed); } } // ignore all other attributes. this.XmlReader.MoveToElement(); ODataCollectionStart collectionStart = new ODataCollectionStart(); isCollectionElementEmpty = this.XmlReader.IsEmptyElement; if (!isCollectionElementEmpty) { // if the collection start element is not an empty element than read over the // start element. this.XmlReader.Read(); } return collectionStart; }
public void ShouldWriteCountAndNextLinkAnnotationOfComplexCollectionPropertyIfSpecified() { ODataCollectionStart collectionStart = new ODataCollectionStart() { Count = 3, NextPageLink = new Uri("http://next-link") }; collectionStart.SetSerializationInfo(new ODataCollectionStartSerializationInfo { CollectionTypeName = "Collection(foo.bar)" }); WriteAndValidate(collectionStart, this.items, "{\"@odata.context\":\"http://odata.org/test/$metadata#Collection(foo.bar)\",\"@odata.count\":3,\"@odata.nextLink\":\"http://next-link/\",\"value\":[{\"Street\":\"1 Microsoft Way\",\"Zipcode\":98052,\"State\":\"WA\"}]}", writingResponse: true, itemTypeReference: this.addressTypeReference); }
public void ShouldWriteCollectionOfTypeDefinitionItemType() { ODataCollectionStart collectionStart = new ODataCollectionStart(); WriteAndValidate(collectionStart, new object[] { 123 }, "{\"@odata.context\":\"http://odata.org/test/$metadata#Collection(NS.Test)\",\"value\":[123]}", true, new EdmTypeDefinitionReference(new EdmTypeDefinition("NS", "Test", EdmPrimitiveTypeKind.Int32), false)); }
/// <summary> /// Start writing a collection. /// </summary> /// <param name="collectionStart">The <see cref="ODataCollectionStart"/> representing the collection.</param> protected override void StartCollection(ODataCollectionStart collectionStart) { this.atomCollectionSerializer.WriteCollectionStart(); }
private static void WriteAndValidateAsync(IEdmTypeReference itemTypeReference, ODataCollectionStart collectionStart, IEnumerable<object> items, string expectedPayload, bool writingResponse) { MemoryStream stream = new MemoryStream(); var outputContext = CreateJsonLightOutputContext(stream, writingResponse, synchronous: false); var collectionWriter = new ODataJsonLightCollectionWriter(outputContext, itemTypeReference); collectionWriter.WriteStartAsync(collectionStart).Wait(); foreach (object item in items) { collectionWriter.WriteItemAsync(item).Wait(); } collectionWriter.WriteEndAsync().Wait(); ValidateWrittenPayload(stream, expectedPayload); }
public void ShouldWriteContextUriBasedOnSerializationInfoForComplexCollectionResponseWithoutUserModelWhenBothItemTypeAndSerializationInfoAreGiven() { ODataCollectionStart collectionStart = new ODataCollectionStart(); collectionStart.SetSerializationInfo(new ODataCollectionStartSerializationInfo { CollectionTypeName = "Collection(foo.bar)" }); WriteAndValidate(collectionStart, this.items, "{\"@odata.context\":\"http://odata.org/test/$metadata#Collection(foo.bar)\",\"value\":[{\"Street\":\"1 Microsoft Way\",\"Zipcode\":98052,\"State\":\"WA\"}]}", writingResponse: true, itemTypeReference: this.addressTypeReference); }
/// <summary> /// Start writing a collection. /// </summary> /// <param name="collectionStart">The <see cref="ODataCollectionStart"/> representing the collection.</param> protected override void StartCollection(ODataCollectionStart collectionStart) { this.jsonLightCollectionSerializer.WriteCollectionStart(collectionStart, this.ItemTypeReference); }
public void ShouldBeAbleToSetTheCollectionStartSerializationInfo() { ODataCollectionStart collectionStart = new ODataCollectionStart(); ODataCollectionStartSerializationInfo serializationInfo = new ODataCollectionStartSerializationInfo { CollectionTypeName = "Collection(Edm.String)" }; collectionStart.SetSerializationInfo(serializationInfo); collectionStart.SerializationInfo.Should().BeSameAs(serializationInfo); }
private static void WriteAndValidate(ODataCollectionStart collectionStart, IEnumerable<object> items, string expectedPayload, bool writingResponse = true, IEdmTypeReference itemTypeReference = null) { WriteAndValidateSync(itemTypeReference, collectionStart, items, expectedPayload, writingResponse); WriteAndValidateAsync(itemTypeReference, collectionStart, items, expectedPayload, writingResponse); }
public void FlagsEnumAsCollectionItemAsTopLevelValue_StrAsValue_StrAsTypeName_MinimalMetadata_CollecionWriter() { ODataCollectionStart collectionStart = new ODataCollectionStart(); collectionStart.SetSerializationInfo(new ODataCollectionStartSerializationInfo { CollectionTypeName = "Collection(NS.ColorFlags)" }); ODataEnumValue[] items = new ODataEnumValue[] { new ODataEnumValue(ColorFlags.Red.ToString(), "NS.ColorFlags"), new ODataEnumValue(null, "NS.ColorFlags_Undefined"), new ODataEnumValue("Red,Green", "NS.ColorFlags"), new ODataEnumValue("Red|Green", "NS.ColorFlags"), new ODataEnumValue(ColorFlags.Green.ToString(), "NS.ColorFlags") }; EdmEnumTypeReference enumRef = new EdmEnumTypeReference((IEdmEnumType)this.userModel.FindType("NS.ColorFlags"), true); WriteToMessageWriterAndVerifyPayload( contentType: "application/json;odata.metadata=minimal;", writerAction: (writer) => { ODataCollectionWriter collectionWriter = writer.CreateODataCollectionWriter(enumRef); collectionWriter.WriteStart(collectionStart); foreach (object item in items) { collectionWriter.WriteItem(item); } collectionWriter.WriteEnd(); }, expectedPayload: "{\"@odata.context\":\"http://odata.org/test/$metadata#Collection(NS.ColorFlags)\",\"value\":[\"Red\",null,\"Red,Green\",\"Red|Green\",\"Green\"]}" ); }
public void ShouldBeAbleToClearTheCollectionStartSerializationInfo() { ODataCollectionStart collectionStart = new ODataCollectionStart(); ODataCollectionStartSerializationInfo serializationInfo = new ODataCollectionStartSerializationInfo { CollectionTypeName = "Collection(Edm.String)" }; collectionStart.SerializationInfo = serializationInfo; collectionStart.SetSerializationInfo(null); collectionStart.SerializationInfo.Should().BeNull(); }
/// <summary> /// Reads the start of a collection; this includes collection-level properties (e.g., the 'results' property) if the version permits it. /// </summary> /// <param name="collectionStartDuplicatePropertyNamesChecker">The duplicate property names checker used to keep track of the properties and annotations /// in the collection wrapper object.</param> /// <param name="isReadingNestedPayload">true if we are reading a nested collection inside a paramter payload; otherwise false.</param> /// <param name="expectedItemTypeReference">The expected item type reference or null if none is expected.</param> /// <param name="actualItemTypeReference">The validated actual item type reference (if specified in the payload) or the expected item type reference.</param> /// <returns>An <see cref="ODataCollectionStart"/> representing the collection-level information. Currently this is only the name of the collection in ATOM.</returns> /// <remarks> /// Pre-Condition: Any: the start of a nested collection value; if this is not a 'StartArray' node this method will fail. /// JsonNodeType.Property: the first property of the collection wrapper object after the context URI. /// JsonNodeType.EndObject: when the collection wrapper object has no properties (other than the context URI). /// Post-Condition: JsonNodeType.StartArray: the start of the array of the collection items. /// </remarks> internal ODataCollectionStart ReadCollectionStart( DuplicatePropertyNamesChecker collectionStartDuplicatePropertyNamesChecker, bool isReadingNestedPayload, IEdmTypeReference expectedItemTypeReference, out IEdmTypeReference actualItemTypeReference) { this.JsonReader.AssertNotBuffering(); actualItemTypeReference = expectedItemTypeReference; ODataCollectionStart collectionStart = null; if (isReadingNestedPayload) { Debug.Assert(!this.JsonLightInputContext.ReadingResponse, "Nested collections are only supported in parameter payloads in requests."); collectionStart = new ODataCollectionStart { Name = null }; } else { while (this.JsonReader.NodeType == JsonNodeType.Property) { IEdmTypeReference actualItemTypeRef = expectedItemTypeReference; this.ProcessProperty( collectionStartDuplicatePropertyNamesChecker, this.ReadTypePropertyAnnotationValue, (propertyParsingResult, propertyName) => { switch (propertyParsingResult) { case PropertyParsingResult.ODataInstanceAnnotation: if (!IsValidODataAnnotationOfCollection(propertyName)) { throw new ODataException(ODataErrorStrings.ODataJsonLightPropertyAndValueDeserializer_UnexpectedAnnotationProperties(propertyName)); } this.JsonReader.SkipValue(); break; case PropertyParsingResult.CustomInstanceAnnotation: this.JsonReader.SkipValue(); break; case PropertyParsingResult.PropertyWithoutValue: throw new ODataException(ODataErrorStrings.ODataJsonLightPropertyAndValueDeserializer_TopLevelPropertyAnnotationWithoutProperty(propertyName)); case PropertyParsingResult.PropertyWithValue: if (string.CompareOrdinal(JsonLightConstants.ODataValuePropertyName, propertyName) != 0) { throw new ODataException( ODataErrorStrings.ODataJsonLightPropertyAndValueDeserializer_InvalidTopLevelPropertyName(propertyName, JsonLightConstants.ODataValuePropertyName)); } string payloadTypeName = ValidateDataPropertyTypeNameAnnotation(collectionStartDuplicatePropertyNamesChecker, propertyName); if (payloadTypeName != null) { string itemTypeName = EdmLibraryExtensions.GetCollectionItemTypeName(payloadTypeName); if (itemTypeName == null) { throw new ODataException(ODataErrorStrings.ODataJsonLightCollectionDeserializer_InvalidCollectionTypeName(payloadTypeName)); } EdmTypeKind targetTypeKind; SerializationTypeNameAnnotation serializationTypeNameAnnotation; Func<EdmTypeKind> typeKindFromPayloadFunc = () => { throw new ODataException(ODataErrorStrings.General_InternalError(InternalErrorCodes.ODataJsonLightCollectionDeserializer_ReadCollectionStart_TypeKindFromPayloadFunc)); }; actualItemTypeRef = ReaderValidationUtils.ResolvePayloadTypeNameAndComputeTargetType( EdmTypeKind.None, /*defaultPrimitivePayloadType*/ null, expectedItemTypeReference, itemTypeName, this.Model, this.MessageReaderSettings, typeKindFromPayloadFunc, out targetTypeKind, out serializationTypeNameAnnotation); } collectionStart = new ODataCollectionStart { Name = null }; break; case PropertyParsingResult.EndOfObject: break; case PropertyParsingResult.MetadataReferenceProperty: throw new ODataException(ODataErrorStrings.ODataJsonLightPropertyAndValueDeserializer_UnexpectedMetadataReferenceProperty(propertyName)); default: throw new ODataException(ODataErrorStrings.General_InternalError(InternalErrorCodes.ODataJsonLightCollectionDeserializer_ReadCollectionStart)); } }); actualItemTypeReference = actualItemTypeRef; } if (collectionStart == null) { // No collection property found; there should be exactly one property in the collection wrapper that does not have a reserved name. throw new ODataException(ODataErrorStrings.ODataJsonLightCollectionDeserializer_ExpectedCollectionPropertyNotFound(JsonLightConstants.ODataValuePropertyName)); } } // at this point the reader is positioned on the start array node for the collection contents if (this.JsonReader.NodeType != JsonNodeType.StartArray) { throw new ODataException(ODataErrorStrings.ODataJsonLightCollectionDeserializer_CannotReadCollectionContentStart(this.JsonReader.NodeType)); } this.JsonReader.AssertNotBuffering(); return collectionStart; }
public ODataCollectionStartTests() { this.collectionStart = new ODataCollectionStart(); }