public void Initialize()
        {
            var model = new EdmModel();
            var type = new EdmEntityType("TestModel", "TestEntity", /* baseType */ null, /* isAbstract */ false, /* isOpen */ true);
            var keyProperty = type.AddStructuralProperty("DeclaredInt16", EdmPrimitiveTypeKind.Int16);
            type.AddKeys(new[] { keyProperty });

            // Note: DerivedPrimitive is declared as a Geography, but its value below will be set to GeographyPoint, which is derived from Geography.
            type.AddStructuralProperty("DerivedPrimitive", EdmPrimitiveTypeKind.Geography);
            var container = new EdmEntityContainer("TestModel", "Container");
            var set = container.AddEntitySet("Set", type);
            model.AddElement(type);
            model.AddElement(container);

            var writerStream = new MemoryStream();
            this.settings = new ODataMessageWriterSettings();
            this.settings.SetServiceDocumentUri(ServiceDocumentUri);

            // Make the message writer and entry writer lazy so that individual tests can tweak the settings before the message writer is created.
            this.messageWriter = new Lazy<ODataMessageWriter>(() =>
                new ODataMessageWriter(
                    (IODataResponseMessage)new InMemoryMessage { Stream = writerStream },
                    this.settings,
                    model));

            var entryWriter = new Lazy<ODataWriter>(() => this.messageWriter.Value.CreateODataEntryWriter(set, type));

            var valueWithAnnotation = new ODataPrimitiveValue(45);
            valueWithAnnotation.SetAnnotation(new SerializationTypeNameAnnotation { TypeName = "TypeNameFromSTNA" });

            var propertiesToWrite = new List<ODataProperty>
            {
                new ODataProperty
                {
                    Name = "DeclaredInt16", Value = (Int16)42
                }, 
                new ODataProperty
                {
                    Name = "UndeclaredDecimal", Value = (Decimal)4.5
                }, 
                new ODataProperty
                {
                    // Note: value is more derived than the declared type.
                    Name = "DerivedPrimitive", Value = Microsoft.Spatial.GeographyPoint.Create(42, 45)
                },
                new ODataProperty()
                {
                    Name = "PropertyWithSTNA", Value = valueWithAnnotation
                }
            };

            this.writerOutput = new Lazy<string>(() =>
            {
                entryWriter.Value.WriteStart(new ODataEntry { Properties = propertiesToWrite });
                entryWriter.Value.WriteEnd();
                entryWriter.Value.Flush();
                writerStream.Seek(0, SeekOrigin.Begin);
                return new StreamReader(writerStream).ReadToEnd();
            });
        }
        public void ConvertEnumValue_Throws_ForNonEnumValue()
        {
            // Arrange
            object value = new ODataPrimitiveValue(0);
            Type type = typeof(Color);

            // Act & Assert
            Assert.Throws<ValidationException>(
                () => EnumDeserializationHelpers.ConvertEnumValue(value, type),
                "The value with type 'ODataPrimitiveValue' must have type 'ODataEnumValue'.");
        }
        /// <summary>
        /// Gets the type name from the given <paramref name="value"/>.
        /// </summary>
        /// <param name="value">The value to get the type name from. This can be an ODataPrimitiveValue, an ODataComplexValue, an ODataCollectionValue or a Clr primitive object.</param>
        /// <returns>The type name for the given <paramref name="value"/>.</returns>
        protected static string GetTypeNameFromValue(object value)
        {
            Debug.Assert(value != null, "value != null");

            ODataPrimitiveValue primitiveValue = value as ODataPrimitiveValue;

            if (primitiveValue != null)
            {
                // primitiveValueTypeReference == null means: the EDM type of the primitive value cannot be determined.
                // This could possibly be due to value being an unsigned int.
                // In this case, simply return null because:
                //   - If the property is regular property, the type is not needed since service model knows its exact type.
                //   - If the property is dynamic property, ODL does not support dynamic property containing unsigned int value
                //     since we don't know its underlying type as well as how to serialize it.
                IEdmPrimitiveTypeReference primitiveValueTypeReference = EdmLibraryExtensions.GetPrimitiveTypeReference(primitiveValue.Value.GetType());
                return(primitiveValueTypeReference == null ? null : primitiveValueTypeReference.ODataFullName());
            }

            ODataComplexValue complexValue = value as ODataComplexValue;

            if (complexValue != null)
            {
                return(complexValue.TypeName);
            }

            ODataEnumValue enumValue = value as ODataEnumValue;

            if (enumValue != null)
            {
                return(enumValue.TypeName);
            }

            ODataCollectionValue collectionValue = value as ODataCollectionValue;

            if (collectionValue != null)
            {
                return(EdmLibraryExtensions.GetCollectionTypeFullName(collectionValue.TypeName));
            }

            IEdmPrimitiveTypeReference primitiveTypeReference = EdmLibraryExtensions.GetPrimitiveTypeReference(value.GetType());

            if (primitiveTypeReference == null)
            {
                throw new ODataException(Strings.ValidationUtils_UnsupportedPrimitiveType(value.GetType().FullName));
            }

            return(primitiveTypeReference.ODataFullName());
        }
Exemple #4
0
        /// <summary>
        /// Gets the type name from the given <paramref name="value"/>.
        /// </summary>
        /// <param name="value">The value to get the type name from. This can be an ODataPrimitiveValue, an ODataComplexValue, an ODataCollectionValue or a Clr primitive object.</param>
        /// <returns>The type name for the given <paramref name="value"/>.</returns>
        protected static string GetTypeNameFromValue(object value)
        {
            Debug.Assert(value != null, "value != null");

            ODataPrimitiveValue primitiveValue = value as ODataPrimitiveValue;

            if (primitiveValue != null)
            {
                return(EdmLibraryExtensions.GetPrimitiveTypeReference(primitiveValue.Value.GetType()).ODataFullName());
            }

            ODataComplexValue complexValue = value as ODataComplexValue;

            if (complexValue != null)
            {
                return(complexValue.TypeName);
            }

            ODataEnumValue enumValue = value as ODataEnumValue;

            if (enumValue != null)
            {
                return(enumValue.TypeName);
            }

            ODataCollectionValue collectionValue = value as ODataCollectionValue;

            if (collectionValue != null)
            {
                return(EdmLibraryExtensions.GetCollectionTypeFullName(collectionValue.TypeName));
            }

            IEdmPrimitiveTypeReference primitiveTypeReference = EdmLibraryExtensions.GetPrimitiveTypeReference(value.GetType());

            if (primitiveTypeReference == null)
            {
                throw new ODataException(Strings.ValidationUtils_UnsupportedPrimitiveType(value.GetType().FullName));
            }

            return(primitiveTypeReference.ODataFullName());
        }
        public void WriteInstanceAnnotation_ForIntegerShouldUsePrimitiveCodePath()
        {
            var integerValue = new ODataPrimitiveValue(123);
            const string term = "some.term";
            var verifierCalls = 0;

            this.jsonWriter.WriteNameVerifier = (name) =>
            {
                name.Should().Be("@" + term);
                verifierCalls++;
            };
            this.valueWriter.WritePrimitiveVerifier = (value, reference) =>
            {
                value.Should().Be(integerValue.Value);
                reference.Should().BeNull();
                verifierCalls.Should().Be(1);
                verifierCalls++;
            };

            this.jsonLightInstanceAnnotationWriter.WriteInstanceAnnotation(new ODataInstanceAnnotation(term, integerValue));
            verifierCalls.Should().Be(2);
        }
        internal static void AddTypeNameAnnotationAsNeeded(ODataPrimitiveValue primitive, IEdmPrimitiveTypeReference primitiveType,
            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(primitive != null);

            object value = primitive.Value;

            // 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(value, metadataLevel))
                {
                    typeName = null;
                }
                else
                {
                    typeName = primitiveType.FullName();
                }

                primitive.SetAnnotation<SerializationTypeNameAnnotation>(new SerializationTypeNameAnnotation
                {
                    TypeName = typeName
                });
            }
        }
        internal static void AddTypeNameAnnotationAsNeeded(ODataPrimitiveValue primitive, IEdmPrimitiveTypeReference primitiveType,
            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).

            Contract.Assert(primitive != null);

            object value = primitive.Value;
            string typeName = null; // Set null to force the type name not to serialize.

            // Provide the type name to serialize.
            if (!ShouldSuppressTypeNameSerialization(value, metadataLevel))
            {
                typeName = primitiveType.FullName();
            }

            primitive.SetAnnotation<SerializationTypeNameAnnotation>(new SerializationTypeNameAnnotation
            {
                TypeName = typeName
            });
        }
        public void WriteInstanceAnnotation_ForDateShouldUsePrimitiveCodePathWithTypeName()
        {
            var date = new ODataPrimitiveValue(new Date(2014, 11, 11));
            const string term = "some.term";
            var verifierCalls = 0;

            this.jsonWriter.WriteNameVerifier = (name) =>
            {
                if (verifierCalls == 0)
                {
                    name.Should().Be(term + "@odata.type");
                    verifierCalls++;
                }
                else if (verifierCalls == 2)
                {
                    name.Should().Be("@" + term);
                    verifierCalls++;
                }
                else throw new Exception("unexpected call to JsonWriter.WriteName");
            };
            this.jsonWriter.WriteValueVerifier = (value) =>
            {
                verifierCalls.Should().Be(1);
                verifierCalls++;
            };
            this.valueWriter.WritePrimitiveVerifier = (value, reference) =>
            {
                value.Should().Be(date.Value);
                reference.Should().BeNull();
                verifierCalls.Should().Be(3);
                verifierCalls++;
            };

            this.jsonLightInstanceAnnotationWriter.WriteInstanceAnnotation(new ODataInstanceAnnotation(term, date));
            verifierCalls.Should().Be(4);
        }
 public void BuildPropertyContextUriForIntegerPropertyValueWithNonNullAnnotation()
 {
     ODataValue value = new ODataPrimitiveValue(1);
     value.SetAnnotation(new SerializationTypeNameAnnotation { TypeName = "FQNS.FromAnnotation" });
     var contextUri = this.CreatePropertyContextUri(value);
     contextUri.OriginalString.Should().Be(BuildExpectedContextUri("#FQNS.FromAnnotation"));
 }
            public override ODataEntry CreateEntry(SelectExpandNode selectExpandNode, EntityInstanceContext entityInstanceContext)
            {
                ODataEntry entry = base.CreateEntry(selectExpandNode, entityInstanceContext);

                // instance annotation on entry
                ODataPrimitiveValue guidValue = new ODataPrimitiveValue(new Guid("A6E07EAC-AD49-4BF7-A06E-203FF4D4B0D8"));
                entry.InstanceAnnotations.Add(new ODataInstanceAnnotation("Entry.GuidAnnotation", guidValue));

                ODataPrimitiveValue strValue = new ODataPrimitiveValue("Hello World.");
                entry.InstanceAnnotations.Add(new ODataInstanceAnnotation("Hello.World", strValue));
                return entry;
            }
        internal static ODataPrimitiveValue CreatePrimitive(object value, IEdmPrimitiveTypeReference primitveType,
            ODataMetadataLevel metadataLevel)
        {
            if (value == null)
            {
                return null;
            }

            object supportedValue = ConvertUnsupportedPrimitives(value);
            ODataPrimitiveValue primitive = new ODataPrimitiveValue(supportedValue);
            AddTypeNameAnnotationAsNeeded(primitive, primitveType, metadataLevel);
            return primitive;
        }
        internal static ODataPrimitiveValue CreatePrimitive(object value, IEdmPrimitiveTypeReference primitveType,
            ODataSerializerContext writeContext)
        {
            if (value == null)
            {
                return null;
            }

            object supportedValue = ConvertUnsupportedPrimitives(value);
            ODataPrimitiveValue primitive = new ODataPrimitiveValue(supportedValue);

            if (writeContext != null)
            {
                AddTypeNameAnnotationAsNeeded(primitive, primitveType, writeContext.MetadataLevel);
            }

            return primitive;
        }
        public void AddTypeNameAnnotationAsNeeded_AddsAnnotation_InJsonLightMetadataMode()
        {
            // Arrange
            IEdmPrimitiveTypeReference edmPrimitiveType = EdmLibHelpers.GetEdmPrimitiveTypeReferenceOrNull(typeof(short));
            ODataPrimitiveValue primitive = new ODataPrimitiveValue((short)1);

            // Act
            ODataPrimitiveSerializer.AddTypeNameAnnotationAsNeeded(primitive, edmPrimitiveType, ODataMetadataLevel.FullMetadata);

            // Assert
            SerializationTypeNameAnnotation annotation = primitive.GetAnnotation<SerializationTypeNameAnnotation>();
            Assert.NotNull(annotation); // Guard
            Assert.Equal("Edm.Int16", annotation.TypeName);
        }
        public void WriteTopLevelErrorWithDateInstanceAnnotation()
        {
            var result = SetupSerializerAndRunTest(null, serializer =>
            {
                ODataError error = new ODataError();
                var instanceAnnotations = new Collection<ODataInstanceAnnotation>();
                var primitiveValue = new ODataPrimitiveValue(new Date(2014, 8, 8));
                ODataInstanceAnnotation annotation = new ODataInstanceAnnotation("sample.primitive", primitiveValue);
                instanceAnnotations.Add(annotation);
                error.InstanceAnnotations = instanceAnnotations;

                serializer.WriteTopLevelError(error, false);
            });

            result.Should().Contain("\"[email protected]\":\"#Date\",\"@sample.primitive\":\"2014-08-08\"");
        }
 public void IfValueIsODataPrimitiveValueThenODataValueShouldBeReferenceEqual()
 {
     ODataPrimitiveValue primitiveValue = new ODataPrimitiveValue(42);
     this.property.Value = primitiveValue;
     this.property.ODataValue.Should().BeSameAs(primitiveValue);
 }
        public void PrimitiveValueSerializationTypeNameAnnotationTest()
        {
            #region test case
            var testCases = new[]
            {
                new
                {
                    DebugDescription = "A null SerializationTypeNameAnnotation should invoke default primitive type name writing behavior.",
                    SerializationTypeNameAnnotation = (SerializationTypeNameAnnotation)null,
                    XmlTypeName = "<typeName>Edm.Int64</typeName>",
                    JsonLightTypeName = MissingTypeNameSentinelTextJson,   // Since this is a declared property, its type name isn't written by default in JSON light.
                },
                new
                {
                    DebugDescription = "A SerializationTypeNameAnnotation with a null TypeName should force primitive type names to not be written, regardless of format.",
                    SerializationTypeNameAnnotation = new SerializationTypeNameAnnotation() { TypeName = null },
                    XmlTypeName = MissingTypeNameSentinelTextAtom,
                    JsonLightTypeName = MissingTypeNameSentinelTextJson,
                },
                new
                {
                    DebugDescription = "A SerializationTypeNameAnnotation with a TypeName of \"DifferentType\" should cause that type name to be written for primitive values, except in JSON verbose, where the format doesn't allow explicit type names for primitives.",
                    SerializationTypeNameAnnotation = new SerializationTypeNameAnnotation() { TypeName = "DifferentType" },
                    XmlTypeName = "<typeName>DifferentType</typeName>",
                    JsonLightTypeName = "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataTypeAnnotationName + "\":\"DifferentType\"",
                },
                new
                {
                    DebugDescription = "A SerializationTypeNameAnnotation with an empty string TypeName should cause an empty type name to be written for primitive values, except in JSON verbose, where the format doesn't allow explicit type names for primitives.",
                    SerializationTypeNameAnnotation = new SerializationTypeNameAnnotation() { TypeName = string.Empty },
                    XmlTypeName = "<typeName></typeName>",
                    JsonLightTypeName = "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataTypeAnnotationName + "\":\"\"",
                }
            };
            #endregion test cases

            var testDescriptors = testCases.Select(tc =>
            {
                EdmModel model = new EdmModel();

                var owningEntityType = new EdmEntityType("TestNS", "OwningEntityType");
                owningEntityType.AddStructuralProperty("PropertyName", EdmCoreModel.Instance.GetInt64(isNullable: false));
                model.AddElement(owningEntityType);

                var container = new EdmEntityContainer("TestNS", "TestContainer");
                model.AddElement(container);

                ODataPrimitiveValue primitiveValue = new ODataPrimitiveValue((Int64) 42);
                if (tc.SerializationTypeNameAnnotation != null)
                {
                    primitiveValue.SetAnnotation(tc.SerializationTypeNameAnnotation);
                }

                return new PayloadWriterTestDescriptor<ODataProperty>(
                    this.Settings,
                    new ODataProperty { Name = "PropertyName", Value = primitiveValue },
                    (testConfiguration) =>
                    {
                        if (testConfiguration.Format == ODataFormat.Atom)
                        {
                            return new AtomWriterTestExpectedResults(this.Settings.ExpectedResultSettings)
                            {
                                FragmentExtractor = (result) =>
                                {
                                    string typeName = (string)result.Attribute(TestAtomConstants.ODataMetadataXNamespace + TestAtomConstants.AtomTypeAttributeName);
                                    return typeName == null ? MissingTypeNameSentinelXElement : new XElement("typeName", typeName);
                                },
                                Xml = tc.XmlTypeName
                            };
                        }

                        if (testConfiguration.Format == ODataFormat.Json)
                        {
                            return new JsonWriterTestExpectedResults(this.Settings.ExpectedResultSettings)
                            {
                                FragmentExtractor = (result) =>
                                {
                                    var jsonObject = JsonLightWriterUtils.TrimWhitespace(result).Object();
                                    JsonProperty typeProperty = null;
                                    if (jsonObject != null)
                                    {
                                        typeProperty = jsonObject.Property(JsonLightConstants.ODataTypeAnnotationName);
                                    }

                                    return typeProperty == null ? MissingTypeNameSentinelJsonProperty : typeProperty.RemoveAllAnnotations(true);
                                },
                                Json = tc.JsonLightTypeName
                            };
                        }

                        throw new NotSupportedException("Format " + testConfiguration.Format.GetType().Name + " is not supported.");
                    })
                {
                    Model = model,
                    PayloadEdmElementContainer = owningEntityType
                };
            });

            this.CombinatorialEngineProvider.RunCombinations(
                testDescriptors,
                // We exclude Verbose JSON from this test because it has no way of writing type names on primitive values.
                this.WriterTestConfigurationProvider.ExplicitFormatConfigurationsWithIndent,
                (testDescriptor, testConfiguration) =>
                {
                    testConfiguration = testConfiguration.Clone();
                    testConfiguration.MessageWriterSettings.SetServiceDocumentUri(ServiceDocumentUri);
                    testDescriptor.RunTopLevelPropertyPayload(testConfiguration, baselineLogger: this.Logger);
                });
        }
Exemple #17
0
 private static void AssertODataPrimitiveValueAreEqual(ODataPrimitiveValue primitiveValue1, ODataPrimitiveValue primitiveValue2)
 {
     Assert.IsNotNull(primitiveValue1);
     Assert.IsNotNull(primitiveValue2);
     Assert.AreEqual(primitiveValue1.Value, primitiveValue2.Value);
 }
            public override ODataFeed CreateODataFeed(IEnumerable feedInstance, IEdmCollectionTypeReference feedType,
                ODataSerializerContext writeContext)
            {
                ODataFeed feed = base.CreateODataFeed(feedInstance, feedType, writeContext);

                // Int32
                ODataPrimitiveValue intValue = new ODataPrimitiveValue(321);
                feed.InstanceAnnotations.Add(new ODataInstanceAnnotation("Custom.Int32Annotation", intValue));

                // String
                ODataPrimitiveValue stringValue = new ODataPrimitiveValue("My amazing feed");
                feed.InstanceAnnotations.Add(new ODataInstanceAnnotation("Custom.StringAnnotation", stringValue));
                return feed;
            }
Exemple #19
0
 /// <summary>
 /// Resolve a primitive value type name
 /// </summary>
 /// <param name="primitiveValue">The value to get the type name from.</param>
 /// <returns>A type for primitive value</returns>
 internal static IEdmTypeReference ResolveAndValidateTypeForPrimitiveValue(ODataPrimitiveValue primitiveValue)
 {
     return(EdmLibraryExtensions.GetPrimitiveTypeReference(primitiveValue.Value.GetType()));
 }
            public override ODataProperty CreateStructuralProperty(IEdmStructuralProperty structuralProperty, EntityInstanceContext entityInstanceContext)
            {
                ODataProperty property = base.CreateStructuralProperty(structuralProperty, entityInstanceContext);

                // instance annotation on property
                if (property.Name == "Age")
                {
                    ODataPrimitiveValue dateValue = new ODataPrimitiveValue(new Date(2010, 1, 2));
                    property.InstanceAnnotations.Add(new ODataInstanceAnnotation("Property.BirthdayAnnotation",
                        dateValue));
                }

                return property;
            }
        public void WriteTopLevelErrorWithStringInstanceAnnotationWithTypeNameAttribute()
        {
            var result = SetupSerializerAndRunTest(null, serializer =>
            {
                ODataError error = new ODataError();
                var instanceAnnotations = new Collection<ODataInstanceAnnotation>();
                var primitiveValue = new ODataPrimitiveValue("stringValue");
                primitiveValue.SetAnnotation(new SerializationTypeNameAnnotation() { TypeName = "Custom.Type" });
                ODataInstanceAnnotation annotation = new ODataInstanceAnnotation("sample.primitive", primitiveValue);
                instanceAnnotations.Add(annotation);
                error.InstanceAnnotations = instanceAnnotations;

                serializer.WriteTopLevelError(error, false);
            });

            result.Should().Contain("\"[email protected]\":\"#Custom.Type\",\"@sample.primitive\":\"stringValue\"");
        }
        public void WriteTopLevelErrorWithTimeOfDayInstanceAnnotation()
        {
            var result = SetupSerializerAndRunTest(null, serializer =>
            {
                ODataError error = new ODataError();
                var instanceAnnotations = new Collection<ODataInstanceAnnotation>();
                var primitiveValue = new ODataPrimitiveValue(new TimeOfDay(12, 30, 5, 90));
                ODataInstanceAnnotation annotation = new ODataInstanceAnnotation("sample.primitive", primitiveValue);
                instanceAnnotations.Add(annotation);
                error.InstanceAnnotations = instanceAnnotations;

                serializer.WriteTopLevelError(error, false);
            });

            result.Should().Contain("\"[email protected]\":\"#TimeOfDay\",\"@sample.primitive\":\"12:30:05.0900000\"");
        }
 public void PrimitiveValueShouldSupportUInt32()
 {
     ODataPrimitiveValue valueUInt32 = new ODataPrimitiveValue((UInt32)123);
     this.property.Value = valueUInt32;
     this.property.ODataValue.Should().BeSameAs(valueUInt32);
 }
        public void AddTypeNameAnnotationAsNeeded_DoesNotAddAnnotation_InDefaultMetadataMode()
        {
            // Arrange
            IEdmPrimitiveTypeReference edmPrimitiveType = EdmLibHelpers.GetEdmPrimitiveTypeReferenceOrNull(typeof(int));
            ODataPrimitiveValue primitive = new ODataPrimitiveValue(0);

            // Act
            ODataPrimitiveSerializer.AddTypeNameAnnotationAsNeeded(primitive, edmPrimitiveType, ODataMetadataLevel.Default);

            // Assert
            Assert.Null(primitive.GetAnnotation<SerializationTypeNameAnnotation>());
        }
        public void WriteTopLevelErrorWithDateTimeInstanceAnnotation()
        {
            var result = SetupSerializerAndRunTest(null, serializer =>
            {
                ODataError error = new ODataError();
                var instanceAnnotations = new Collection<ODataInstanceAnnotation>();
                var primitiveValue = new ODataPrimitiveValue(new DateTimeOffset(2000, 1, 1, 12, 30, 0, new TimeSpan()));
                ODataInstanceAnnotation annotation = new ODataInstanceAnnotation("sample.primitive", primitiveValue);
                instanceAnnotations.Add(annotation);
                error.InstanceAnnotations = instanceAnnotations;

                serializer.WriteTopLevelError(error, false);
            });

            result.Should().Contain("\"[email protected]\":\"#DateTimeOffset\",\"@sample.primitive\":\"2000-01-01T12:30:00Z\"");
        }
        /// <summary>
        /// Gets the type name based on the given odata value.
        /// </summary>
        /// <param name="value">The value.</param>
        /// <param name="model">The model used to handle unsigned int conversions.</param>
        /// <returns>The type name for the context URI.</returns>
        private static string GetTypeNameForValue(ODataValue value, IEdmModel model)
        {
            if (value == null)
            {
                return(null);
            }

            // special identifier for null values.
            if (value.IsNullValue)
            {
                return(ODataConstants.ContextUriFragmentNull);
            }

            var typeAnnotation = value.GetAnnotation <SerializationTypeNameAnnotation>();

            if (typeAnnotation != null && !string.IsNullOrEmpty(typeAnnotation.TypeName))
            {
                return(typeAnnotation.TypeName);
            }

            var complexValue = value as ODataComplexValue;

            if (complexValue != null)
            {
                return(complexValue.TypeName);
            }

            var collectionValue = value as ODataCollectionValue;

            if (collectionValue != null)
            {
                return(EdmLibraryExtensions.GetCollectionTypeFullName(collectionValue.TypeName));
            }

            var enumValue = value as ODataEnumValue;

            if (enumValue != null)
            {
                return(enumValue.TypeName);
            }

            ODataPrimitiveValue primitive = value as ODataPrimitiveValue;

            if (primitive == null)
            {
                Debug.Assert(value is ODataStreamReferenceValue, "value is ODataStreamReferenceValue");
                throw new ODataException(Strings.ODataContextUriBuilder_StreamValueMustBePropertiesOfODataEntry);
            }

            // Try convert to underlying type if the primitive value is unsigned int.
            IEdmTypeDefinitionReference typeDefinitionReference = model.ResolveUIntTypeDefinition(primitive.Value);

            if (typeDefinitionReference != null)
            {
                return(typeDefinitionReference.ODataFullName());
            }

            IEdmPrimitiveTypeReference primitiveValueTypeReference = EdmLibraryExtensions.GetPrimitiveTypeReference(primitive.Value.GetType());

            return(primitiveValueTypeReference == null ? null : primitiveValueTypeReference.ODataFullName());
        }
Exemple #27
0
        /// <summary>
        /// Writes an instance annotation.
        /// </summary>
        /// <param name="instanceAnnotation">The instance annotation to write.</param>
        /// <param name="ignoreFilter">Whether to ingore the filter in settings.</param>
        /// <param name="propertyName">The name of the property this instance annotation applies to</param>
        internal void WriteInstanceAnnotation(ODataInstanceAnnotation instanceAnnotation, bool ignoreFilter = false, string propertyName = null)
        {
            string     name  = instanceAnnotation.Name;
            ODataValue value = instanceAnnotation.Value;

            Debug.Assert(!string.IsNullOrEmpty(name), "name should not be null or empty");
            Debug.Assert(!ODataAnnotationNames.IsODataAnnotationName(name), "A reserved name cannot be used as instance annotation key");
            Debug.Assert(value != null, "value should not be null because we use ODataNullValue for null instead");
            Debug.Assert(!(value is ODataStreamReferenceValue), "!(value is ODataStreamReferenceValue) -- ODataInstanceAnnotation and InstanceAnnotationCollection will throw if the value is a stream value.");
            Debug.Assert(this.valueSerializer.Model != null, "this.valueSerializer.Model != null");

            if (!ignoreFilter && this.valueSerializer.Settings.ShouldSkipAnnotation(name))
            {
                return;
            }

            IEdmTypeReference expectedType = MetadataUtils.LookupTypeOfValueTerm(name, this.valueSerializer.Model);

            if (value is ODataNullValue)
            {
                if (expectedType != null && !expectedType.IsNullable)
                {
                    throw new ODataException(ODataErrorStrings.ODataAtomPropertyAndValueSerializer_NullValueNotAllowedForInstanceAnnotation(instanceAnnotation.Name, expectedType.ODataFullName()));
                }

                this.WriteInstanceAnnotationName(propertyName, name);
                this.valueSerializer.WriteNullValue();
                return;
            }

            // If we didn't find an expected type from looking up the term in the model, treat this value the same way we would for open property values.
            // That is, write the type name (unless its a primitive value with a JSON-native type).  If we did find an expected type, treat the annotation value like a
            // declared property with an expected type. This will still write out the type if the value type is more derived than the declared type, for example.
            bool treatLikeOpenProperty = expectedType == null;

            ODataComplexValue complexValue = value as ODataComplexValue;

            if (complexValue != null)
            {
                this.WriteInstanceAnnotationName(propertyName, name);
                this.valueSerializer.WriteComplexValue(complexValue, expectedType, false /*isTopLevel*/, treatLikeOpenProperty, this.valueSerializer.CreateDuplicatePropertyNamesChecker());
                return;
            }

            IEdmTypeReference    typeFromValue   = TypeNameOracle.ResolveAndValidateTypeNameForValue(this.valueSerializer.Model, expectedType, value, treatLikeOpenProperty);
            ODataCollectionValue collectionValue = value as ODataCollectionValue;

            if (collectionValue != null)
            {
                string collectionTypeNameToWrite = this.typeNameOracle.GetValueTypeNameForWriting(collectionValue, expectedType, typeFromValue, treatLikeOpenProperty);
                if (collectionTypeNameToWrite != null)
                {
                    ODataJsonLightWriterUtils.WriteODataTypePropertyAnnotation(this.JsonWriter, name, collectionTypeNameToWrite);
                }

                this.WriteInstanceAnnotationName(propertyName, name);
                this.valueSerializer.WriteCollectionValue(collectionValue, expectedType, false /*isTopLevelProperty*/, false /*isInUri*/, treatLikeOpenProperty);
                return;
            }

            ODataPrimitiveValue primitiveValue = value as ODataPrimitiveValue;

            Debug.Assert(primitiveValue != null, "Did we add a new subclass of ODataValue?");

            string primitiveTypeNameToWrite = this.typeNameOracle.GetValueTypeNameForWriting(primitiveValue, expectedType, typeFromValue, treatLikeOpenProperty);

            if (primitiveTypeNameToWrite != null)
            {
                ODataJsonLightWriterUtils.WriteODataTypePropertyAnnotation(this.JsonWriter, name, primitiveTypeNameToWrite);
            }

            this.WriteInstanceAnnotationName(propertyName, name);
            this.valueSerializer.WritePrimitiveValue(primitiveValue.Value, expectedType);
        }
 public void CreatingNestedODataPrimitiveValueShouldFail()
 {
     ODataPrimitiveValue innerPrimitiveValue = new ODataPrimitiveValue(42);
     Action testSubject = () => new ODataPrimitiveValue(innerPrimitiveValue);
     testSubject.ShouldThrow<ODataException>().WithMessage(ErrorStrings.ODataPrimitiveValue_CannotCreateODataPrimitiveValueFromUnsupportedValueType("Microsoft.OData.Core.ODataPrimitiveValue"));
 }
Exemple #29
0
 /// <summary>
 /// Resolve a primitive value type name 
 /// </summary>
 /// <param name="primitiveValue">The value to get the type name from.</param>
 /// <returns>A type for primitive value</returns>
 internal static IEdmTypeReference ResolveAndValidateTypeForPrimitiveValue(ODataPrimitiveValue primitiveValue)
 {
     return EdmLibraryExtensions.GetPrimitiveTypeReference(primitiveValue.Value.GetType());
 }
 public void TypeNameShouldComeFromSerializationTypeNameAnnotationForPrimitiveValue()
 {
     var stna = new SerializationTypeNameAnnotation() {TypeName = "FromSTNA"};
     var value = new ODataPrimitiveValue(42);
     value.SetAnnotation(stna);
     this.typeNameOracle.GetValueTypeNameForWriting(value,
         EdmCoreModel.Instance.GetInt32(true),
         EdmCoreModel.Instance.GetInt32(false),
         /* isOpenProperty*/ false).Should().Be("FromSTNA");
 }
 private static void AssertODataPrimitiveValueAreEqual(ODataPrimitiveValue expectedPrimitiveValue, ODataPrimitiveValue actualPrimitiveValue)
 {
     Assert.IsNotNull(expectedPrimitiveValue);
     Assert.IsNotNull(actualPrimitiveValue);
     Assert.AreEqual(expectedPrimitiveValue.Value, actualPrimitiveValue.Value);
 }