public static ArraySchema GetSchema(ODataCollectionValue colValue) { var enumerator = colValue.Items.GetEnumerator(); enumerator.MoveNext(); var item = enumerator.Current; return Schema.CreateArray(GetSchema(item)); }
public void WriteObject_WritesValueReturnedFrom_CreateODataCollectionValue() { // Arrange MemoryStream stream = new MemoryStream(); IODataResponseMessage message = new ODataMessageWrapper(stream); ODataMessageWriterSettings settings = new ODataMessageWriterSettings(); settings.SetContentType(ODataFormat.Atom); ODataMessageWriter messageWriter = new ODataMessageWriter(message, settings); Mock<ODataCollectionSerializer> serializer = new Mock<ODataCollectionSerializer>(new DefaultODataSerializerProvider()); ODataSerializerContext writeContext = new ODataSerializerContext { RootElementName = "CollectionName", Model = _model }; IEnumerable enumerable = new object[0]; ODataCollectionValue collectionValue = new ODataCollectionValue { TypeName = "NS.Name", Items = new[] { 0, 1, 2 } }; serializer.CallBase = true; serializer .Setup(s => s.CreateODataCollectionValue(enumerable, It.Is<IEdmTypeReference>(e => e.Definition == _edmIntType.Definition), writeContext)) .Returns(collectionValue).Verifiable(); // Act serializer.Object.WriteObject(enumerable, typeof(int[]), messageWriter, writeContext); // Assert serializer.Verify(); stream.Seek(0, SeekOrigin.Begin); XElement element = XElement.Load(stream); Assert.Equal("value", element.Name.LocalName); Assert.Equal(3, element.Descendants().Count()); Assert.Equal(new[] { "0", "1", "2" }, element.Descendants().Select(e => e.Value)); }
public void WriteObject_WritesValueReturnedFrom_CreateODataCollectionValue() { // Arrange MemoryStream stream = new MemoryStream(); IODataResponseMessage message = new ODataMessageWrapper(stream); ODataMessageWriterSettings settings = new ODataMessageWriterSettings() { ODataUri = new ODataUri { ServiceRoot = new Uri("http://any/") } }; settings.SetContentType(ODataFormat.Json); ODataMessageWriter messageWriter = new ODataMessageWriter(message, settings); Mock<ODataCollectionSerializer> serializer = new Mock<ODataCollectionSerializer>(new DefaultODataSerializerProvider()); ODataSerializerContext writeContext = new ODataSerializerContext { RootElementName = "CollectionName", Model = _model }; IEnumerable enumerable = new object[0]; ODataCollectionValue collectionValue = new ODataCollectionValue { TypeName = "NS.Name", Items = new[] { 0, 1, 2 } }; serializer.CallBase = true; serializer .Setup(s => s.CreateODataCollectionValue(enumerable, It.Is<IEdmTypeReference>(e => e.Definition == _edmIntType.Definition), writeContext)) .Returns(collectionValue).Verifiable(); // Act serializer.Object.WriteObject(enumerable, typeof(int[]), messageWriter, writeContext); // Assert serializer.Verify(); stream.Seek(0, SeekOrigin.Begin); string result = new StreamReader(stream).ReadToEnd(); Assert.Equal("{\"@odata.context\":\"http://any/$metadata#Collection(Edm.Int32)\",\"value\":[0,1,2]}", result); }
public void SetlineItems(ODataCollectionValue values) { this.lineItems = new Collection<string>(); foreach (var item in values.Items) { this.lineItems.Add(item.ToString()); } }
public void WritingCollectionValueShouldFailWhenNoTypeSpecified() { var serializer = CreateODataJsonLightValueSerializer(false); var collectionValue = new ODataCollectionValue() { Items = new List<string>() }; Action test = () => serializer.WriteCollectionValue(collectionValue, null, false, false, false); test.ShouldThrow<ODataException>().WithMessage(Strings.ODataJsonLightPropertyAndValueSerializer_NoExpectedTypeOrTypeNameSpecifiedForCollectionValueInRequest); }
public void WritingCollectionValueDifferingFromExpectedTypeShouldFail_WithoutEdmPrefix() { var serializer = CreateODataJsonLightValueSerializer(true); var collectionValue = new ODataCollectionValue() { Items = new List<string>(), TypeName = "Collection(Int32)" }; var stringCollectionTypeRef = EdmCoreModel.GetCollection(EdmCoreModel.Instance.GetString(true)); Action test = () => serializer.WriteCollectionValue(collectionValue, stringCollectionTypeRef, false, false, false); test.ShouldThrow<ODataException>().WithMessage(Strings.ValidationUtils_IncompatibleType("Collection(Edm.Int32)", "Collection(Edm.String)")); }
public void ComplexTypeCollectionRoundtripAtomTest() { ODataComplexValue subject0 = new ODataComplexValue() { TypeName = "NS.Subject", Properties = new[] { new ODataProperty() { Name = "Name", Value = "English" }, new ODataProperty() { Name = "Score", Value = (Int16)98 } } }; ODataComplexValue subject1 = new ODataComplexValue() { TypeName = "NS.Subject", Properties = new[] { new ODataProperty() { Name = "Name", Value = "Math" }, new ODataProperty() { Name = "Score", Value = (Int16)90 } } }; ODataCollectionValue complexCollectionValue = new ODataCollectionValue { TypeName = "Collection(NS.Subject)", Items = new[] { subject0, subject1 } }; ODataFeedAndEntrySerializationInfo info = new ODataFeedAndEntrySerializationInfo() { NavigationSourceEntityTypeName = subject0.TypeName, NavigationSourceName = "Subjects", ExpectedTypeName = subject0.TypeName }; this.VerifyTypeCollectionRoundtrip(complexCollectionValue, "Subjects", info); }
public void PropertyGettersAndSettersTest() { string name1 = "ODataPrimitiveProperty"; object value1 = "Hello world"; ODataProperty primitiveProperty = new ODataProperty() { Name = name1, Value = value1, }; this.Assert.AreEqual(name1, primitiveProperty.Name, "Expected equal name values."); this.Assert.AreSame(value1, primitiveProperty.Value, "Expected reference equal values for property 'Value'."); string name2 = "ODataComplexProperty"; ODataComplexValue value2 = new ODataComplexValue() { Properties = new[] { new ODataProperty() { Name = "One", Value = 1 }, new ODataProperty() { Name = "Two", Value = 2 }, } }; ODataProperty complexProperty = new ODataProperty() { Name = name2, Value = value2, }; this.Assert.AreEqual(name2, complexProperty.Name, "Expected equal name values."); this.Assert.AreSame(value2, complexProperty.Value, "Expected reference equal values for property 'Value'."); string name3 = "ODataCollectionProperty"; ODataCollectionValue value3 = new ODataCollectionValue() { Items = new[] { 1, 2, 3 } }; ODataProperty multiValueProperty = new ODataProperty() { Name = name3, Value = value3, }; this.Assert.AreEqual(name3, multiValueProperty.Name, "Expected equal name values."); this.Assert.AreSame(value3, multiValueProperty.Value, "Expected reference equal values for property 'Value'."); }
static ODataAvroWriterTests() { var type = new EdmEntityType("NS", "SimpleEntry"); type.AddStructuralProperty("TBoolean", EdmPrimitiveTypeKind.Boolean, true); type.AddStructuralProperty("TInt32", EdmPrimitiveTypeKind.Int32, true); type.AddStructuralProperty("TCollection", new EdmCollectionTypeReference(new EdmCollectionType(EdmCoreModel.Instance.GetInt64(false)))); var cpx = new EdmComplexType("NS", "SimpleComplex"); cpx.AddStructuralProperty("TBinary", EdmPrimitiveTypeKind.Binary, true); cpx.AddStructuralProperty("TString", EdmPrimitiveTypeKind.String, true); type.AddStructuralProperty("TComplex", new EdmComplexTypeReference(cpx, true)); TestEntityType = type; binary0 = new byte[] { 4, 7 }; complexValue0 = new ODataComplexValue() { Properties = new[] { new ODataProperty {Name = "TBinary", Value = binary0 ,}, new ODataProperty {Name = "TString", Value = "iamstr",}, }, TypeName = "NS.SimpleComplex" }; longCollection0 = new[] {7L, 9L}; var collectionValue0 = new ODataCollectionValue { Items = longCollection0 }; entry0 = new ODataEntry { Properties = new[] { new ODataProperty {Name = "TBoolean", Value = true,}, new ODataProperty {Name = "TInt32", Value = 32,}, new ODataProperty {Name = "TComplex", Value = complexValue0,}, new ODataProperty {Name = "TCollection", Value = collectionValue0 }, }, TypeName = "NS.SimpleEntry" }; }
private static void AssertODataCollectionValueAreEqual(ODataCollectionValue expectedCollectionValue, ODataCollectionValue actualCollectionValue) { Assert.IsNotNull(expectedCollectionValue); Assert.IsNotNull(actualCollectionValue); Assert.AreEqual(expectedCollectionValue.TypeName, actualCollectionValue.TypeName); var expectedItemsArray = expectedCollectionValue.Items.OfType<object>().ToArray(); var actualItemsArray = actualCollectionValue.Items.OfType<object>().ToArray(); Assert.AreEqual(expectedItemsArray.Length, actualItemsArray.Length); for (int i = 0; i < expectedItemsArray.Length; i++) { var expectedOdataValue = expectedItemsArray[i] as ODataValue; var actualOdataValue = actualItemsArray[i] as ODataValue; if (expectedOdataValue != null && actualOdataValue != null) { AssertODataValueAreEqual(expectedOdataValue, actualOdataValue); } else { Assert.AreEqual(expectedItemsArray[i], actualItemsArray[i]); } } }
private static object ConvertCollectionValue(ODataCollectionValue collection, IEdmTypeReference propertyType, ODataDeserializerProvider deserializerProvider, ODataDeserializerContext readContext) { IEdmCollectionTypeReference collectionType = propertyType as IEdmCollectionTypeReference; Contract.Assert(collectionType != null, "The type for collection must be a IEdmCollectionType."); ODataEdmTypeDeserializer deserializer = deserializerProvider.GetEdmTypeDeserializer(collectionType); return deserializer.ReadInline(collection, collectionType, readContext); }
/// <summary> /// Creates an <see cref="ODataCollectionValue"/> for the enumerable represented by <paramref name="enumerable"/>. /// </summary> /// <param name="enumerable">The value of the collection to be created.</param> /// <param name="elementType">The element EDM type of the collection.</param> /// <param name="writeContext">The serializer context to be used while creating the collection.</param> /// <returns>The created <see cref="ODataCollectionValue"/>.</returns> public virtual ODataCollectionValue CreateODataCollectionValue(IEnumerable enumerable, IEdmTypeReference elementType, ODataSerializerContext writeContext) { if (writeContext == null) { throw Error.ArgumentNull("writeContext"); } if (elementType == null) { throw Error.ArgumentNull("elementType"); } ArrayList valueCollection = new ArrayList(); if (enumerable != null) { ODataEdmTypeSerializer itemSerializer = null; foreach (object item in enumerable) { itemSerializer = itemSerializer ?? SerializerProvider.GetEdmTypeSerializer(elementType); if (itemSerializer == null) { throw new SerializationException( Error.Format(SRResources.TypeCannotBeSerialized, elementType.FullName(), typeof(ODataMediaTypeFormatter).Name)); } // ODataCollectionWriter expects the individual elements in the collection to be the underlying values and not ODataValues. valueCollection.Add(itemSerializer.CreateODataValue(item, elementType, writeContext).GetInnerValue()); } } // Ideally, we'd like to do this: // string typeName = _edmCollectionType.FullName(); // But ODataLib currently doesn't support .FullName() for collections. As a workaround, we construct the // collection type name the hard way. string typeName = "Collection(" + elementType.FullName() + ")"; // ODataCollectionValue is only a V3 property, arrays inside Complex Types or Entity types are only supported in V3 // if a V1 or V2 Client requests a type that has a collection within it ODataLib will throw. ODataCollectionValue value = new ODataCollectionValue { Items = valueCollection, TypeName = typeName }; AddTypeNameAnnotationAsNeeded(value, writeContext.MetadataLevel); return value; }
internal static object ConvertCollection(ODataCollectionValue collectionValue, IEdmTypeReference edmTypeReference, ModelBindingContext bindingContext, ODataDeserializerContext readContext) { Contract.Assert(collectionValue != null); IEdmCollectionTypeReference collectionType = edmTypeReference as IEdmCollectionTypeReference; Contract.Assert(collectionType != null); ODataCollectionDeserializer deserializer = (ODataCollectionDeserializer)DeserializerProvider.GetEdmTypeDeserializer(collectionType); object value = deserializer.ReadInline(collectionValue, collectionType, readContext); if (value == null) { return null; } IEnumerable collection = value as IEnumerable; Contract.Assert(collection != null); Type clrType = bindingContext.ModelType; Type elementType; if (!clrType.IsCollection(out elementType)) { // EdmEntityCollectionObject and EdmComplexCollectionObject are collection types. throw new ODataException(String.Format(CultureInfo.InvariantCulture, SRResources.ParameterTypeIsNotCollection, bindingContext.ModelName, clrType)); } IEnumerable newCollection; if (CollectionDeserializationHelpers.TryCreateInstance(clrType, collectionType, elementType, out newCollection)) { collection.AddToCollection(newCollection, elementType, bindingContext.ModelName, bindingContext.ModelType); if (clrType.IsArray) { newCollection = CollectionDeserializationHelpers.ToArray(newCollection, elementType); } return newCollection; } return null; }
public void CollectionOfPrimitiveCustomInstanceAnnotationOnErrorShouldRoundtrip() { var originalCollectionValue = new ODataCollectionValue { TypeName = "Collection(Edm.String)", Items = new[] { "value1", "value2" } }; var original = new KeyValuePair<string, ODataValue>("sample.error", originalCollectionValue); var error = this.WriteThenReadErrorWithInstanceAnnotation(original); var annotation = RunBasicVerificationAndGetAnnotationValue("sample.error", error); annotation.Should().BeOfType<ODataCollectionValue>(); annotation.As<ODataCollectionValue>().Items.Cast<string>().Count().Should().Be(2); }
public void WritingAPrimitiveCollectionValuedAnnotationWithMismatchedMetadataShouldThrow() { ODataCollectionValue collection = new ODataCollectionValue { Items = new[] { 123.4 } }; var annotation = AtomInstanceAnnotation.CreateFrom(new ODataInstanceAnnotation("custom.primitiveCollection", collection), /*target*/ null); Action test = () => this.serializer.WriteInstanceAnnotation(annotation); test.ShouldThrow<ODataException>().WithMessage(Strings.CollectionWithoutExpectedTypeValidator_IncompatibleItemTypeName("Edm.Double", "Edm.Int32")); }
public void SetCoverColors(ODataCollectionValue values) { this.CoverColors = new Collection<Color>(); foreach (var item in values.Items) { ODataEnumValue enumItem = item as ODataEnumValue; this.CoverColors.Add((Color)Enum.Parse(typeof(Color), enumItem.Value)); } }
public void WriteCollectionValue(ODataCollectionValue collectionValue, IEdmTypeReference metadataTypeReference, bool isTopLevelProperty, bool isInUri, bool isOpenPropertyType) { this.WriteCollectionVerifier.Should().NotBeNull("WriteCollectionValue was called."); this.WriteCollectionVerifier(collectionValue, metadataTypeReference, isTopLevelProperty, isInUri, isOpenPropertyType); }
public void SerializeTopLevelPropertyOfCollectionTypeShouldWork() { EdmModel model = new EdmModel(); EdmComplexType complexType = new EdmComplexType("ns", "complex"); complexType.AddProperty(new EdmStructuralProperty(complexType, "propertyName1", EdmCoreModel.Instance.GetInt32(isNullable: false))); complexType.AddProperty(new EdmStructuralProperty(complexType, "propertyName2", EdmCoreModel.Instance.GetString(isNullable: false))); model.AddElement(complexType); ODataCollectionValue primitiveCollectionValue = new ODataCollectionValue { Items = new[] { "value1", "value2" }}; primitiveCollectionValue.TypeName = "Collection(Edm.String)"; ODataProperty primitiveCollectionProperty = new ODataProperty { Name = "PrimitiveCollectionProperty", Value = primitiveCollectionValue }; string pval = SerializeProperty(model, primitiveCollectionProperty); pval.Should().Be("<?xml version=\"1.0\" encoding=\"utf-8\"?><m:value xmlns:d=\"http://docs.oasis-open.org/odata/ns/data\" xmlns:georss=\"http://www.georss.org/georss\" xmlns:gml=\"http://www.opengis.net/gml\" m:context=\"http://odata.org/$metadata#Collection(Edm.String)\" m:type=\"#Collection(String)\" xmlns:m=\"http://docs.oasis-open.org/odata/ns/metadata\"><m:element>value1</m:element><m:element>value2</m:element></m:value>"); ODataComplexValue complexValue1 = new ODataComplexValue { Properties = new[] { new ODataProperty { Name = "propertyName1", Value = 1 }, new ODataProperty { Name = "propertyName2", Value = "stringValue" } }, TypeName = "ns.complex" }; ODataComplexValue complexValue2 = new ODataComplexValue { Properties = new[] { new ODataProperty { Name = "propertyName1", Value = 1 }, new ODataProperty { Name = "propertyName2", Value = "stringValue" } }, TypeName = "ns.complex" }; ODataCollectionValue complexCollectionValue = new ODataCollectionValue { Items = new[] { complexValue1, complexValue2 }, TypeName = "Collection(ns.complex)" }; ODataProperty complexCollectionProperty = new ODataProperty { Name = "ComplexCollectionProperty", Value = complexCollectionValue }; string cval = SerializeProperty(model, complexCollectionProperty); cval.Should().Be("<?xml version=\"1.0\" encoding=\"utf-8\"?><m:value xmlns:d=\"http://docs.oasis-open.org/odata/ns/data\" xmlns:georss=\"http://www.georss.org/georss\" xmlns:gml=\"http://www.opengis.net/gml\" m:context=\"http://odata.org/$metadata#Collection(ns.complex)\" m:type=\"#Collection(ns.complex)\" xmlns:m=\"http://docs.oasis-open.org/odata/ns/metadata\"><m:element><d:propertyName1 m:type=\"Int32\">1</d:propertyName1><d:propertyName2>stringValue</d:propertyName2></m:element><m:element><d:propertyName1 m:type=\"Int32\">1</d:propertyName1><d:propertyName2>stringValue</d:propertyName2></m:element></m:value>"); }
public static ODataCollectionValue ReadCollectionParameterValue(ODataCollectionReader collectionReader) { List<object> collectionItems = new List<object>(); while (collectionReader.Read()) { if (collectionReader.State == ODataCollectionReaderState.Completed) { break; } if (collectionReader.State == ODataCollectionReaderState.Value) { collectionItems.Add(collectionReader.Item); } } ODataCollectionValue result = new ODataCollectionValue(); result.Items = collectionItems; return result; }
public void WritingNullableCollectionValue() { EdmModel model = new EdmModel(); EdmEntityType entityType = new EdmEntityType("NS", "MyTestEntity"); EdmStructuralProperty key = entityType.AddStructuralProperty("Id", EdmPrimitiveTypeKind.Int32, false); entityType.AddKeys(key); entityType.AddStructuralProperty( "NullableIntNumbers", new EdmCollectionTypeReference(new EdmCollectionType(EdmCoreModel.Instance.GetInt32(true)))); model.AddElement(entityType); var collectionValue = new ODataCollectionValue() { Items = new int?[] { null }, TypeName = "Collection(Edm.Int32)" }; ODataEntry entry = new ODataEntry() { Id = new Uri("http://test/Id"), TypeName = "NS.MyTestEntity", Properties = new[] { new ODataProperty { Name = "NullableIntNumbers", Value = collectionValue }, }, SerializationInfo = MySerializationInfo }; string outputPayload = this.WriterEntry(model, entry, entityType); string expectedPayload = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" + "<entry xmlns=\"http://www.w3.org/2005/Atom\" xmlns:d=\"http://docs.oasis-open.org/odata/ns/data\" " + "xmlns:m=\"http://docs.oasis-open.org/odata/ns/metadata\" xmlns:georss=\"http://www.georss.org/georss\" " + "xmlns:gml=\"http://www.opengis.net/gml\" " + "m:context=\"http://odata.org/$metadata#MyTestEntity/$entity\">" + "<id>http://test/Id</id>" + "<category term=\"#NS.MyTestEntity\" scheme=\"http://docs.oasis-open.org/odata/ns/scheme\" />" + "<title />" + "<author><name /></author>" + "<content type=\"application/xml\">" + "<m:properties>" + "<d:NullableIntNumbers m:type=\"#Collection(Int32)\">" + "<m:element m:null=\"true\" />" + "</d:NullableIntNumbers>" + "</m:properties>" + "</content>" + "</entry>"; outputPayload = Regex.Replace(outputPayload, "<updated>[^<]*</updated>", ""); outputPayload.Should().Be(expectedPayload); }
public void ReadEntry_CanReadDynamicPropertiesForOpenEntityType() { // Arrange ODataConventionModelBuilder builder = new ODataConventionModelBuilder(); builder.EntityType<SimpleOpenCustomer>(); builder.EnumType<SimpleEnum>(); IEdmModel model = builder.GetEdmModel(); IEdmEntityTypeReference customerTypeReference = model.GetEdmTypeReference(typeof(SimpleOpenCustomer)).AsEntity(); var deserializerProvider = new DefaultODataDeserializerProvider(); var deserializer = new ODataEntityDeserializer(deserializerProvider); ODataEnumValue enumValue = new ODataEnumValue("Third", typeof(SimpleEnum).FullName); ODataComplexValue[] complexValues = { new ODataComplexValue { TypeName = typeof(SimpleOpenAddress).FullName, Properties = new[] { // declared properties new ODataProperty { Name = "Street", Value = "Street 1" }, new ODataProperty { Name = "City", Value = "City 1" }, // dynamic properties new ODataProperty { Name = "DateTimeProperty", Value = new DateTimeOffset(new DateTime(2014, 5, 6)) } } }, new ODataComplexValue { TypeName = typeof(SimpleOpenAddress).FullName, Properties = new[] { // declared properties new ODataProperty { Name = "Street", Value = "Street 2" }, new ODataProperty { Name = "City", Value = "City 2" }, // dynamic properties new ODataProperty { Name = "ArrayProperty", Value = new ODataCollectionValue { TypeName = "Collection(Edm.Int32)", Items = new[] {1, 2, 3, 4} } } } } }; ODataCollectionValue collectionValue = new ODataCollectionValue { TypeName = "Collection(" + typeof(SimpleOpenAddress).FullName + ")", Items = complexValues }; ODataEntry odataEntry = new ODataEntry { Properties = new[] { // declared properties new ODataProperty { Name = "CustomerId", Value = 991 }, new ODataProperty { Name = "Name", Value = "Name #991" }, // dynamic properties new ODataProperty { Name = "GuidProperty", Value = new Guid("181D3A20-B41A-489F-9F15-F91F0F6C9ECA") }, new ODataProperty { Name = "EnumValue", Value = enumValue }, new ODataProperty { Name = "CollectionProperty", Value = collectionValue } }, TypeName = typeof(SimpleOpenCustomer).FullName }; ODataDeserializerContext readContext = new ODataDeserializerContext() { Model = model }; ODataEntryWithNavigationLinks entry = new ODataEntryWithNavigationLinks(odataEntry); // Act SimpleOpenCustomer customer = deserializer.ReadEntry(entry, customerTypeReference, readContext) as SimpleOpenCustomer; // Assert Assert.NotNull(customer); // Verify the declared properties Assert.Equal(991, customer.CustomerId); Assert.Equal("Name #991", customer.Name); // Verify the dynamic properties Assert.NotNull(customer.CustomerProperties); Assert.Equal(3, customer.CustomerProperties.Count()); Assert.Equal(new Guid("181D3A20-B41A-489F-9F15-F91F0F6C9ECA"), customer.CustomerProperties["GuidProperty"]); Assert.Equal(SimpleEnum.Third, customer.CustomerProperties["EnumValue"]); // Verify the dynamic collection property var collectionValues = Assert.IsType<List<SimpleOpenAddress>>(customer.CustomerProperties["CollectionProperty"]); Assert.NotNull(collectionValues); Assert.Equal(2, collectionValues.Count()); Assert.Equal(new DateTimeOffset(new DateTime(2014, 5, 6)), collectionValues[0].Properties["DateTimeProperty"]); Assert.Equal(new List<int> { 1, 2, 3, 4 }, collectionValues[1].Properties["ArrayProperty"]); }
public void WritingNonNullableCollectionValueWithNullElementShouldThrow() { EdmModel model = new EdmModel(); EdmEntityType entityType = new EdmEntityType("NS", "MyTestEntity"); EdmStructuralProperty key = entityType.AddStructuralProperty("Id", EdmPrimitiveTypeKind.Int32, false); entityType.AddKeys(key); entityType.AddStructuralProperty( "NonNullableIntNumbers", new EdmCollectionTypeReference(new EdmCollectionType(EdmCoreModel.Instance.GetInt32(false)))); model.AddElement(entityType); var collectionValue = new ODataCollectionValue() { Items = new int?[] { null }, TypeName = "Collection(Edm.Int32)" }; ODataEntry entry = new ODataEntry() { Id = new Uri("http://test/Id"), TypeName = "NS.MyTestEntity", Properties = new[] { new ODataProperty { Name = "NonNullableIntNumbers", Value = collectionValue }, }, SerializationInfo = PropertyAndValueAtomWriterIntegrationTests.MySerializationInfo }; Action test = () => this.WriterEntry(model, entry, entityType); test.ShouldThrow<ODataException>().WithMessage( Strings.ValidationUtils_NonNullableCollectionElementsMustNotBeNull); }
/// <summary> /// Deserializes the given <paramref name="collectionValue"/> under the given <paramref name="readContext"/>. /// </summary> /// <param name="collectionValue">The <see cref="ODataCollectionValue"/> to deserialize.</param> /// <param name="elementType">The element type of the collection to read.</param> /// <param name="readContext">The deserializer context.</param> /// <returns>The deserialized collection.</returns> public virtual IEnumerable ReadCollectionValue(ODataCollectionValue collectionValue, IEdmTypeReference elementType, ODataDeserializerContext readContext) { if (collectionValue == null) { throw Error.ArgumentNull("collectionValue"); } if (elementType == null) { throw Error.ArgumentNull("elementType"); } ODataEdmTypeDeserializer deserializer = DeserializerProvider.GetEdmTypeDeserializer(elementType); if (deserializer == null) { throw new SerializationException( Error.Format(SRResources.TypeCannotBeDeserialized, elementType.FullName(), typeof(ODataMediaTypeFormatter).Name)); } foreach (object entry in collectionValue.Items) { if (elementType.IsPrimitive()) { yield return entry; } else { yield return deserializer.ReadInline(entry, elementType, readContext); } } }
/// <summary> /// Resolve a type name against the provided <paramref name="model"/>. If not payload type name is specified, /// derive the type from the model type (if available). /// </summary> /// <param name="model">The model to use.</param> /// <param name="typeReferenceFromMetadata">The type inferred from the model or null if the model is not a user model.</param> /// <param name="collectionValue">The value in question to resolve the type for.</param> /// <param name="isOpenPropertyType">True if the type name belongs to an open property.</param> /// <param name="writerValidator">The writer validator to use for validation.</param> /// <returns>A type for the <paramref name="collectionValue"/> or null if no type name is specified and no metadata is available.</returns> internal static IEdmTypeReference ResolveAndValidateTypeForCollectionValue(IEdmModel model, IEdmTypeReference typeReferenceFromMetadata, ODataCollectionValue collectionValue, bool isOpenPropertyType, IWriterValidator writerValidator) { Debug.Assert(model != null, "model != null"); var typeName = collectionValue.TypeName; ValidateIfTypeNameMissing(typeName, model, isOpenPropertyType); IEdmType typeFromValue = typeName == null ? null : ResolveAndValidateTypeName(model, typeName, EdmTypeKind.Collection, writerValidator); if (typeReferenceFromMetadata != null) { writerValidator.ValidateTypeKind(EdmTypeKind.Collection, typeReferenceFromMetadata.TypeKind(), typeFromValue); } IEdmTypeReference typeReferenceFromValue = ResolveTypeFromMetadataAndValue(typeReferenceFromMetadata, typeFromValue == null ? null : typeFromValue.ToTypeReference(), writerValidator); if (typeReferenceFromValue != null) { // update nullability from metadata if (typeReferenceFromMetadata != null) { typeReferenceFromValue = typeReferenceFromMetadata; } // validate that the collection type represents a valid Collection type (e.g., is unordered). typeReferenceFromValue = writerValidator.ValidateCollectionType(typeReferenceFromValue); } return typeReferenceFromValue; }
/// <summary> /// Adds the type name annotations required for proper json light serialization. /// </summary> /// <param name="value">The collection value for which the annotations have to be added.</param> /// <param name="metadataLevel">The OData metadata level of the response.</param> protected internal static void AddTypeNameAnnotationAsNeeded(ODataCollectionValue value, ODataMetadataLevel metadataLevel) { // ODataLib normally has the caller decide whether or not to serialize properties by leaving properties // null when values should not be serialized. The TypeName property is different and should always be // provided to ODataLib to enable model validation. A separate annotation is used to decide whether or not // to serialize the type name (a null value prevents serialization). // Note that this annotation should not be used for Atom or JSON verbose formats, as it will interfere with // the correct default behavior for those formats. Contract.Assert(value != null); // Only add an annotation if we want to override ODataLib's default type name serialization behavior. if (ShouldAddTypeNameAnnotation(metadataLevel)) { string typeName; // Provide the type name to serialize (or null to force it not to serialize). if (ShouldSuppressTypeNameSerialization(metadataLevel)) { typeName = null; } else { typeName = value.TypeName; } value.SetAnnotation<SerializationTypeNameAnnotation>(new SerializationTypeNameAnnotation { TypeName = typeName }); } }
public void WriteInstanceAnnotation_ForCollectionShouldUseCollectionCodePath() { var collectionValue = new ODataCollectionValue() { TypeName = "Collection(String)" }; collectionValue.SetAnnotation(new SerializationTypeNameAnnotation() { TypeName = null }); const string term = "some.term"; var verifierCalls = 0; this.jsonWriter.WriteNameVerifier = (name) => { name.Should().Be("@" + term); verifierCalls++; }; this.valueWriter.WriteCollectionVerifier = (value, reference, isTopLevelProperty, isInUri, isOpenProperty) => { value.Should().Be(collectionValue); reference.Should().BeNull(); isOpenProperty.Should().BeTrue(); isTopLevelProperty.Should().BeFalse(); isInUri.Should().BeFalse(); verifierCalls.Should().Be(1); verifierCalls++; }; this.jsonLightInstanceAnnotationWriter.WriteInstanceAnnotation(new ODataInstanceAnnotation(term, collectionValue)); verifierCalls.Should().Be(2); }
public void ReadComplexValue_CanReadDynamicCollectionPropertiesForOpenComplexType() { // Arrange ODataConventionModelBuilder builder = new ODataConventionModelBuilder(); builder.ComplexType<SimpleOpenAddress>(); builder.EnumType<SimpleEnum>(); IEdmModel model = builder.GetEdmModel(); IEdmComplexTypeReference addressTypeReference = model.GetEdmTypeReference(typeof(SimpleOpenAddress)).AsComplex(); var deserializerProvider = new DefaultODataDeserializerProvider(); var deserializer = new ODataComplexTypeDeserializer(deserializerProvider); ODataEnumValue enumValue = new ODataEnumValue("Third", typeof(SimpleEnum).FullName); ODataCollectionValue collectionValue = new ODataCollectionValue { TypeName = "Collection(" + typeof(SimpleEnum).FullName + ")", Items = new[] { enumValue, enumValue } }; ODataComplexValue complexValue = new ODataComplexValue { Properties = new[] { // declared properties new ODataProperty { Name = "Street", Value = "My Way #599" }, // dynamic properties new ODataProperty { Name = "CollectionProperty", Value = collectionValue } }, TypeName = typeof(SimpleOpenAddress).FullName }; ODataDeserializerContext readContext = new ODataDeserializerContext() { Model = model }; // Act SimpleOpenAddress address = deserializer.ReadComplexValue(complexValue, addressTypeReference, readContext) as SimpleOpenAddress; // Assert Assert.NotNull(address); // Verify the declared properties Assert.Equal("My Way #599", address.Street); Assert.Null(address.City); // Verify the dynamic properties Assert.NotNull(address.Properties); Assert.Equal(1, address.Properties.Count()); var collectionValues = Assert.IsType<List<SimpleEnum>>(address.Properties["CollectionProperty"]); Assert.NotNull(collectionValues); Assert.Equal(2, collectionValues.Count()); Assert.Equal(SimpleEnum.Third, collectionValues[0]); Assert.Equal(SimpleEnum.Third, collectionValues[1]); }
public void SetEmails(ODataCollectionValue values) { this.Emails = new Collection<string>(); foreach (var item in values.Items) { this.Emails.Add(item != null ? item.ToString() : null); } }
private static object ConvertCollectionValue(ODataCollectionValue collection, ref IEdmTypeReference propertyType, ODataDeserializerProvider deserializerProvider, ODataDeserializerContext readContext) { IEdmCollectionTypeReference collectionType; if (propertyType == null) { // dynamic collection property Contract.Assert(!String.IsNullOrEmpty(collection.TypeName), "ODataLib should have verified that dynamic collection value has a type name " + "since we provided metadata."); string elementTypeName = GetCollectionElementTypeName(collection.TypeName, isNested: false); IEdmModel model = readContext.Model; IEdmSchemaType elementType = model.FindType(elementTypeName); Contract.Assert(elementType != null); collectionType = new EdmCollectionTypeReference( new EdmCollectionType(elementType.ToEdmTypeReference(isNullable: false))); propertyType = collectionType; } else { collectionType = propertyType as IEdmCollectionTypeReference; Contract.Assert(collectionType != null, "The type for collection must be a IEdmCollectionType."); } ODataEdmTypeDeserializer deserializer = deserializerProvider.GetEdmTypeDeserializer(collectionType); return deserializer.ReadInline(collection, collectionType, readContext); }
public void SetOrderShelfLifes(ODataCollectionValue values) { this.OrderShelfLifes = new Collection<TimeSpan>(); foreach (var item in values.Items) { this.OrderShelfLifes.Add((TimeSpan)item); } }