public void ShouldBeAbleToSetThePropertySerializationInfo()
 {
     ODataProperty property = new ODataProperty();
     ODataPropertySerializationInfo serializationInfo = new ODataPropertySerializationInfo();
     property.SetSerializationInfo(serializationInfo);
     property.SerializationInfo.Should().BeSameAs(serializationInfo);
 }
        /// <summary>
        /// Write an <see cref="ODataProperty" /> to the given stream. This method creates an
        /// async buffered stream and writes the property to it.
        /// </summary>
        /// <param name="property">The property to write.</param>
        internal void WriteTopLevelProperty(ODataProperty property)
        {
            Debug.Assert(property != null, "property != null");
            Debug.Assert(!(property.Value is ODataStreamReferenceValue), "!(property.Value is ODataStreamReferenceValue)");

            this.WriteTopLevelPayload(
                () =>
                {
                    this.JsonWriter.StartObjectScope();
                    ODataPayloadKind kind = this.JsonLightOutputContext.MessageWriterSettings.IsIndividualProperty ? ODataPayloadKind.IndividualProperty : ODataPayloadKind.Property;

                    ODataContextUrlInfo contextInfo = ODataContextUrlInfo.Create(property.ODataValue, this.JsonLightOutputContext.MessageWriterSettings.ODataUri, this.Model);
                    this.WriteContextUriProperty(kind, () => contextInfo);

                    // Note we do not allow named stream properties to be written as top level property.
                    this.JsonLightValueSerializer.AssertRecursionDepthIsZero();
                    this.WriteProperty(
                        property,
                        null /*owningType*/,
                        true /* isTopLevel */,
                        false /* allowStreamProperty */,
                        this.CreateDuplicatePropertyNamesChecker(),
                        null /* projectedProperties */);
                    this.JsonLightValueSerializer.AssertRecursionDepthIsZero();

                    this.JsonWriter.EndObjectScope();
                });
        }
 public void ShouldBeAbleToClearThePropertySerializationInfo()
 {
     ODataProperty property = new ODataProperty();
     ODataPropertySerializationInfo serializationInfo = new ODataPropertySerializationInfo();
     property.SerializationInfo = serializationInfo;
     property.SetSerializationInfo(null);
     property.SerializationInfo.Should().BeNull();
 }
Пример #4
0
        /// <summary>
        /// Creates the value for the stream property's link relation attribute.
        /// </summary>
        /// <param name="streamProperty">The stream property to create the relation for.</param>
        /// <param name="forEditLink">'true' if the relation is computed for an edit link; otherwise 'false'.</param>
        /// <returns>The relation attribute value for the stream property's link relation.</returns>
        internal static string ComputeStreamPropertyRelation(ODataProperty streamProperty, bool forEditLink)
        {
            Debug.Assert(streamProperty != null, "streamProperty != null");
            Debug.Assert(!string.IsNullOrEmpty(streamProperty.Name), "!string.IsNullOrEmpty(streamProperty.Name)");

            string segmentName = forEditLink ? AtomConstants.ODataStreamPropertyEditMediaRelatedLinkRelationPrefix : AtomConstants.ODataStreamPropertyMediaResourceRelatedLinkRelationPrefix;
            return string.Join("", new string[] { segmentName, streamProperty.Name });
        }
        public void ComplexTypeRoundtripAtomTest()
        {
            var age = new ODataProperty() { Name = "Age", Value = (Int16)18 };
            var email = new ODataProperty() { Name = "Email", Value = "*****@*****.**" };
            var tel = new ODataProperty() { Name = "Tel", Value = "0123456789" };
            var id = new ODataProperty() { Name = "ID", Value = Guid.Empty };

            ODataComplexValue complexValue = new ODataComplexValue() { TypeName = "NS.PersonalInfo", Properties = new[] { age, email, tel, id } };

            this.VerifyComplexTypeRoundtrip(complexValue, "NS.PersonalInfo");
        }
 public void ShouldBeAbleToWriteInstanceAnnotationsInResponse()
 {
     ODataProperty property = new ODataProperty()
     {
         Name = "Prop",
         Value = Guid.Empty,
         InstanceAnnotations = new Collection<ODataInstanceAnnotation>
         {
             new ODataInstanceAnnotation("Annotation.1", new ODataPrimitiveValue(true)),
             new ODataInstanceAnnotation("Annotation.2", new ODataPrimitiveValue(123))
         }
     };
     WriteAndValidate(outputContext => outputContext.WriteProperty(property), "{\"@odata.context\":\"http://odata.org/test/$metadata#Edm.Guid\",\"@Annotation.1\":true,\"@Annotation.2\":123,\"value\":\"00000000-0000-0000-0000-000000000000\"}");
 }
 /// <summary>
 /// Writes a single property in ATOM format.
 /// </summary>
 /// <param name="property">The property to write out.</param>
 internal void WriteTopLevelProperty(ODataProperty property)
 {
     this.WritePayloadStart();
     this.AssertRecursionDepthIsZero();
     this.WriteProperty(
         property,
         null /*owningType*/,
         true  /* isTopLevel */,
         false /* isWritingCollection */,
         null  /* beforePropertyAction */,
         this.CreateDuplicatePropertyNamesChecker(),
         null  /* projectedProperties */);
     this.AssertRecursionDepthIsZero();
     this.WritePayloadEnd();
 }
Пример #8
0
        /// <summary>
        /// Validates an <see cref="ODataProperty"/> to ensure all required information is specified.
        /// </summary>
        /// <param name="property">The property to validate.</param>
        internal static void ValidateProperty(ODataProperty property)
        {
            DebugUtils.CheckNoExternalCallers();

            if (property == null)
            {
                throw new ODataException(Strings.ODataWriter_PropertyMustNotBeNull);
            }

            // Properties must have a non-empty name
            if (string.IsNullOrEmpty(property.Name))
            {
                throw new ODataException(Strings.ODataWriter_PropertiesMustHaveNonEmptyName);
            }
        }
        public void CreateProperty_Returns_ODataProperty()
        {
            // Arrange
            IEdmTypeReference edmType = new Mock <IEdmTypeReference>().Object;
            var serializer            = new Mock <ODataEdmTypeSerializer>(ODataPayloadKind.Unsupported);

            serializer
            .Setup(s => s.CreateODataValue(42, edmType, null))
            .Returns(new ODataPrimitiveValue(42));

            // Act
            ODataProperty property = serializer.Object.CreateProperty(graph: 42, expectedType: edmType,
                                                                      elementName: "SomePropertyName", writeContext: null);

            // Assert
            Assert.NotNull(property);
            Assert.Equal("SomePropertyName", property.Name);
            Assert.Equal(42, property.Value);
        }
Пример #10
0
        public DataServiceContextWrapper(Uri serviceRoot, ODataProtocolVersion maxProtocolVersion, Func <Task <string> > accessTokenGetter)
            : base(serviceRoot, maxProtocolVersion)
        {
            _accessTokenGetter = accessTokenGetter;

            IgnoreMissingProperties = true;

            BuildingRequest += (sender, args) => args.Headers.Add("Authorization", "Bearer " + _accessTokenGetter().Result);

            Configurations.RequestPipeline.OnEntryStarting(args =>
            {
                var entity = (EntityBase)args.Entity;

                if ((!entity.ChangedProperties.IsValueCreated || entity.ChangedProperties.Value.Count == 0))
                {
                    args.Entry.Properties = new ODataProperty[0];
                    return;
                }

                if (!_modifiedEntities.Contains(entity))
                {
                    _modifiedEntities.Add(entity);
                }

                IEnumerable <ODataProperty> properties = new ODataProperty[0];

                if (entity.ChangedProperties.IsValueCreated)
                {
                    properties = properties.Concat(args.Entry.Properties.Where(i => entity.ChangedProperties.Value.Contains(i.Name)));
                }

                args.Entry.Properties = properties;
            });

            Configurations.ResponsePipeline.OnEntityMaterialized(args =>
            {
                var entity = (EntityBase)args.Entity;

                entity.ResetChanges();
            });

            OnCreated();
        }
        internal static void ApplyProperty(ODataProperty property, IEdmStructuredTypeReference resourceType, object resource, ODataDeserializerProvider deserializerProvider, ODataDeserializerReadContext readContext)
        {
            IEdmProperty edmProperty = resourceType.FindProperty(property.Name);

            string            propertyName = property.Name;
            IEdmTypeReference propertyType = edmProperty != null ? edmProperty.Type : null; // open properties have null values

            object value = ConvertValue(property.Value, ref propertyType, deserializerProvider, readContext);

            // If we are in patch mode and we are deserializing an entity object then we are updating Delta<T> and not T.
            if (!readContext.IsPatchMode || !resourceType.IsEntity())
            {
                resource.GetType().GetProperty(propertyName).SetValue(resource, value, index: null);
            }
            else
            {
                (resource as IDelta).TrySetPropertyValue(propertyName, value);
            }
        }
        public void CreateODataComplexValue_WritesBaseAndDerivedProperties_ForDerivedComplexType()
        {
            // Arrange
            IEdmModel model = SerializationTestsHelpers.SimpleCustomerOrderModel();

            IEdmComplexType addressType = model.FindDeclaredType("Default.CnAddress") as IEdmComplexType;
            Type            cnAddress   = typeof(CnAddress);

            model.SetAnnotationValue <ClrTypeAnnotation>(addressType, new ClrTypeAnnotation(cnAddress));

            IEdmComplexTypeReference addressTypeRef = addressType.ToEdmTypeReference(isNullable: false).AsComplex();

            ODataSerializerProvider    serializerProvider = new DefaultODataSerializerProvider();
            ODataComplexTypeSerializer serializer         = new ODataComplexTypeSerializer(serializerProvider);
            ODataSerializerContext     context            = new ODataSerializerContext
            {
                Model = model
            };

            Address address = new CnAddress()
            {
                Street  = "One Microsoft Way",
                City    = "Redmond",
                State   = "Washington",
                Country = "United States",
                ZipCode = "98052",
                CnProp  = new Guid("F83FB4CC-84BD-403B-B411-79926800F9A5")
            };

            // Act
            var odataValue = serializer.CreateODataComplexValue(address, addressTypeRef, context);

            // Assert
            ODataComplexValue complexValue = Assert.IsType <ODataComplexValue>(odataValue);

            Assert.Equal(complexValue.TypeName, "Default.CnAddress");
            Assert.Equal(6, complexValue.Properties.Count());

            // Verify the derived property
            ODataProperty street = Assert.Single(complexValue.Properties.Where(p => p.Name == "CnProp"));

            Assert.Equal(new Guid("F83FB4CC-84BD-403B-B411-79926800F9A5"), street.Value);
        }
Пример #13
0
        public void JsonPaddingEnabledWithUserSpecifiedContentType()
        {
            var settings = new ODataMessageWriterSettings {JsonPCallback = "functionName", DisableMessageStreamDisposal = true};
            settings.SetServiceDocumentUri(new Uri("http://stuff"));
            IODataResponseMessage message = new InMemoryMessage {StatusCode = 200, Stream = new MemoryStream()};
            message.SetHeader("Content-Type", "application/json");
            var property = new ODataProperty {Name = "PropertyName", Value = "value"};
            
            using (var writer = new ODataMessageWriter(message, settings))
            {
                writer.WriteProperty(property);
            }

            var responseStream = message.GetStream();
            responseStream.Position = 0;
            var responseString = new StreamReader(responseStream).ReadToEnd();
            responseString.Should().Be("functionName({\"@odata.context\":\"http://stuff/$metadata#Edm.String\",\"value\":\"value\"})");
            message.GetHeader("Content-Type").Should().StartWith("text/javascript");
        }
        private IEnumerable <ODataProperty> CreateStructuralPropertyBag(
            IEnumerable <IEdmStructuralProperty> structuralProperties, EntityInstanceContext entityInstanceContext)
        {
            Contract.Assert(structuralProperties != null);
            Contract.Assert(entityInstanceContext != null);

            List <ODataProperty> properties = new List <ODataProperty>();

            foreach (IEdmStructuralProperty structuralProperty in structuralProperties)
            {
                ODataProperty property = CreateStructuralProperty(structuralProperty, entityInstanceContext);
                if (property != null)
                {
                    properties.Add(property);
                }
            }

            return(properties);
        }
Пример #15
0
        /// <summary>
        /// Gets the property value as the requested type.
        /// </summary>
        /// <typeparam name="T">The expected type of the property value.</typeparam>
        /// <param name="properties">The properties to search.</param>
        /// <param name="propertyName">The name of the property to get the value for.</param>
        /// <param name="propertyValue">The property value as <typeparamref name="T"/> or null if no property
        /// with name <paramref name="propertyName"/> or with the expected type exists.</param>
        /// <returns>true if a property of the expected type was found; otherwise false.</returns>
        private static bool TryGetPropertyValue <T>(IEnumerable <ODataProperty> properties, string propertyName, out T propertyValue) where T : class
        {
            Debug.Assert(properties != null, "properties != null");
            Debug.Assert(!string.IsNullOrEmpty(propertyName), "!string.IsNullOrEmpty(propertyName)");

            propertyValue = null;

            ODataProperty property = properties.Where(p => string.CompareOrdinal(p.Name, propertyName) == 0).FirstOrDefault();

            if (property != null)
            {
                // Ignore cases where we don't get a property of the expected type;
                // we will fail later on with a better error message.
                propertyValue = property.Value as T;
                return(propertyValue != null || property.Value == null);
            }

            return(false);
        }
Пример #16
0
        private OeEntryFactory(IEdmEntitySetBase entitySet, OePropertyAccessor[] accessors)
        {
            _entitySet = entitySet;
            _accessors = accessors;

            _entityType      = entitySet.EntityType();
            _navigationLinks = Array.Empty <OeEntryFactory>();
            _typeName        = EntityType.FullName();

            _odataProperties = new ODataProperty[accessors.Length];
            for (int i = 0; i < accessors.Length; i++)
            {
                _odataProperties[i] = new ODataProperty()
                {
                    Name = accessors[i].Name
                }
            }
            ;
        }
Пример #17
0
        /// <summary>
        /// Creates and adds a new property to the list of properties for an EPM.
        /// </summary>
        /// <param name="properties">The list of properties to add the property to.</param>
        /// <param name="propertyName">The name of the property to add.</param>
        /// <param name="propertyValue">The value of the property to add.</param>
        /// <param name="checkDuplicateEntryPropertyNames">true if the new property should be checked for duplicates against the entry properties; false otherwise.
        /// This should be true if the <paramref name="properties"/> is the list of properties for the entry, and false in all other cases.</param>
        private void AddEpmPropertyValue(ReadOnlyEnumerable <ODataProperty> properties, string propertyName, object propertyValue, bool checkDuplicateEntryPropertyNames)
        {
            Debug.Assert(properties != null, "properties != null");
            Debug.Assert(!string.IsNullOrEmpty(propertyName), "propertyName must not be null or empty.");

            // Create a new property object and add it.
            ODataProperty property = new ODataProperty
            {
                Name  = propertyName,
                Value = propertyValue
            };

            if (checkDuplicateEntryPropertyNames)
            {
                this.entryState.DuplicatePropertyNamesChecker.CheckForDuplicatePropertyNames(property);
            }

            properties.AddToSourceList(property);
        }
 public void FlagsEnumAsCollectionItemAsTopLevelValue_StrAsValue_StrAsTypeName_MinimalMetadata()
 {
     ReadFromMessageReaderAndVerifyPayload(
         payload: "{\"@odata.context\":\"http://odata.org/test/$metadata#Collection(NS.ColorFlags)\",\"value\":[\"Red\",\"Green\"]}",
         contentType: "application/json;odata.metadata=minimal;",
         readerAction: (reader) =>
     {
         ODataProperty expectedProperty = new ODataProperty
         {
             Name  = null,
             Value = new ODataCollectionValue {
                 Items = new[] { new ODataEnumValue(ColorFlags.Red.ToString(), "NS.ColorFlags"), new ODataEnumValue(ColorFlags.Green.ToString(), "NS.ColorFlags") }, TypeName = "Collection(NS.ColorFlags)"
             }
         };
         ODataProperty property = reader.ReadProperty();
         TestUtils.AssertODataPropertyAreEqual(expectedProperty, property);
     }
         );
 }
        public async Task WritePropertyAsync()
        {
            var property = new ODataProperty
            {
                Name  = "Prop",
                Value = 13,
                InstanceAnnotations = new List <ODataInstanceAnnotation>
                {
                    new ODataInstanceAnnotation("Is.LuckyNumber", new ODataPrimitiveValue(true))
                }
            };

            var result = await SetupJsonLightOutputContextAndRunTestAsync(
                (jsonLightOutputContext) => jsonLightOutputContext.WritePropertyAsync(property));

            Assert.Equal(
                "{\"@odata.context\":\"http://tempuri.org/$metadata#Edm.Int32\",\"@Is.LuckyNumber\":true,\"value\":13}",
                result);
        }
        /// <summary>
        /// Converts a value from the data store into an ODataProperty.
        /// </summary>
        /// <param name="instance">The item from the data store.</param>
        /// <param name="propertyName">The name of the property to convert.</param>
        /// <returns>The converted ODataProperty.</returns>
        public static ODataProperty ConvertToODataProperty(object instance, string propertyName)
        {
            object        value    = instance.GetType().GetProperty(propertyName).GetValue(instance, null);
            ODataProperty property = CreateODataProperty(value, propertyName);

            // Add Annotation in property level
            if (((ClrObject)instance).Annotations != null)
            {
                foreach (InstanceAnnotationType annotation in ((ClrObject)instance).Annotations)
                {
                    if (!string.IsNullOrEmpty(annotation.Target) && annotation.Target.Equals(propertyName))
                    {
                        property.InstanceAnnotations.Add(new ODataInstanceAnnotation(annotation.Name, annotation.ConvertValueToODataValue()));
                    }
                }
            }

            return(property);
        }
        /// <summary>
        /// Converts an <see cref="ODataProperty"/> into the corresponding <see cref="IEdmPropertyValue"/>.
        /// </summary>
        /// <param name="property">The non-null <see cref="ODataProperty"/> to convert.</param>
        /// <param name="declaringType">The declaring type of the property.</param>
        /// <returns>An <see cref="IEdmPropertyValue"/> implementation of the <paramref name="property"/> value.</returns>
        internal static IEdmPropertyValue GetEdmPropertyValue(this ODataProperty property, IEdmStructuredTypeReference declaringType)
        {
            Debug.Assert(property != null, "property != null");

            IEdmTypeReference propertyType = null;

            if (declaringType != null)
            {
                IEdmProperty edmProperty = declaringType.FindProperty(property.Name);
                if (edmProperty == null && !declaringType.IsOpen())
                {
                    throw new ODataException(ODataErrorStrings.ODataEdmStructuredValue_UndeclaredProperty(property.Name, declaringType.FullName()));
                }

                propertyType = edmProperty == null ? null : edmProperty.Type;
            }

            return(new EdmPropertyValue(property.Name, ConvertValue(property.Value, propertyType).Value));
        }
        /// <summary>
        /// Writes the metadata properties for a resource which can only occur at the end.
        /// </summary>
        /// <param name="resourceState">The resource state for which to write the metadata properties.</param>
        /// <param name="duplicatePropertyNameChecker">The DuplicatePropertyNameChecker to use.</param>
        internal void WriteResourceEndMetadataProperties(IODataJsonLightWriterResourceState resourceState, IDuplicatePropertyNameChecker duplicatePropertyNameChecker)
        {
            Debug.Assert(resourceState != null, "resourceState != null");

            ODataResourceBase resource = resourceState.Resource;

            // write computed navigation properties
            var navigationLinkInfo = resource.MetadataBuilder.GetNextUnprocessedNavigationLink();

            while (navigationLinkInfo != null)
            {
                Debug.Assert(resource.MetadataBuilder != null, "resource.MetadataBuilder != null");
                navigationLinkInfo.NestedResourceInfo.MetadataBuilder = resource.MetadataBuilder;

                this.WriteNavigationLinkMetadata(navigationLinkInfo.NestedResourceInfo, duplicatePropertyNameChecker);
                navigationLinkInfo = resource.MetadataBuilder.GetNextUnprocessedNavigationLink();
            }

            // write computed stream properties
            ODataProperty streamProperty = resource.MetadataBuilder.GetNextUnprocessedStreamProperty();

            while (streamProperty != null)
            {
                this.WriteProperty(streamProperty, resourceState.ResourceType, /*isTopLevel*/ false, duplicatePropertyNameChecker, null /*metadataBuilder*/);
                streamProperty = resource.MetadataBuilder.GetNextUnprocessedStreamProperty();
            }

            // write "odata.actions" metadata
            IEnumerable <ODataAction> actions = resource.Actions;

            if (actions != null && actions.Any())
            {
                this.WriteOperations(actions.Cast <ODataOperation>(), /*isAction*/ true);
            }

            // write "odata.functions" metadata
            IEnumerable <ODataFunction> functions = resource.Functions;

            if (functions != null && functions.Any())
            {
                this.WriteOperations(functions.Cast <ODataOperation>(), /*isAction*/ false);
            }
        }
Пример #23
0
        /// <summary>
        /// Writes a single property in ATOM format.
        /// </summary>
        /// <param name="property">The property to write out.</param>
        internal void WriteTopLevelProperty(ODataProperty property)
        {
            DebugUtils.CheckNoExternalCallers();

            this.WritePayloadStart();
            this.AssertRecursionDepthIsZero();
            this.WriteProperty(
                property,
                null /* owningType */,
                true /* isTopLevel */,
                false /* isWritingCollection */,
                null /* beforePropertyAction */,
                null /* epmValueCache */,
                null /* epmParentSourcePathSegment */,
                this.CreateDuplicatePropertyNamesChecker(),
                null /* projectedProperties */);
            this.AssertRecursionDepthIsZero();
            this.WritePayloadEnd();
        }
Пример #24
0
        /// <summary>Materializes a primitive value. No op for non-primitive values.</summary>
        /// <param name="type">Type of value to set.</param>
        /// <param name="property">Property holding value.</param>
        internal void MaterializePrimitiveDataValue(Type type, ODataProperty property)
        {
            Debug.Assert(type != null, "type != null");
            Debug.Assert(property != null, "atomProperty != null");

            if (!property.HasMaterializedValue())
            {
                object            value      = property.Value;
                ODataUntypedValue untypedVal = value as ODataUntypedValue;
                if ((untypedVal != null) &&
                    this.MaterializerContext.UndeclaredPropertyBehavior == UndeclaredPropertyBehavior.Support)
                {
                    value = CommonUtil.ParseJsonToPrimitiveValue(untypedVal.RawValue);
                }

                object materializedValue = this.PrimitivePropertyConverter.ConvertPrimitiveValue(value, type);
                property.SetMaterializedValue(materializedValue);
            }
        }
Пример #25
0
        /// <summary>
        /// Creates a new ODataStreamReferenceValue for the named stream and initializes it.
        /// </summary>
        /// <param name="payloadElement">The named stream to process.</param>
        public override void Visit(NamedStreamInstance payloadElement)
        {
            var odataNamedStream = new ODataStreamReferenceValue()
            {
                ETag        = payloadElement.ETag,
                ContentType = payloadElement.EditLink == null ? payloadElement.SourceLinkContentType : payloadElement.EditLinkContentType,
                ReadLink    = payloadElement.SourceLink == null ? null : new Uri(payloadElement.SourceLink),
                EditLink    = payloadElement.EditLink == null ? null : new Uri(payloadElement.EditLink),
            };

            var odataNamedStreamProperty = new ODataProperty()
            {
                Name  = payloadElement.Name,
                Value = odataNamedStream
            };

            this.currentProperties.Add(odataNamedStreamProperty);
            base.Visit(payloadElement);
        }
Пример #26
0
        public static Uri ComputeId(Uri baseUri, IEdmEntitySetBase entitySet, ODataResource entry)
        {
            Uri uri     = AppendSegment(baseUri, entitySet.Name, true);
            var builder = new StringBuilder(uri.IsAbsoluteUri ? uri.AbsoluteUri : uri.OriginalString);

            builder.Append('(');
            bool flag = true;

            IEnumerable <IEdmStructuralProperty> keyProperties = entitySet.EntityType().Key();

            foreach (IEdmStructuralProperty keyProperty in keyProperties)
            {
                ODataProperty property = null;
                foreach (ODataProperty entryProperty in entry.Properties)
                {
                    if (entryProperty.Name == keyProperty.Name)
                    {
                        property = entryProperty;
                        break;
                    }
                }

                if (flag)
                {
                    flag = false;
                }
                else
                {
                    builder.Append(',');
                }
                if (keyProperties.Count() > 1)
                {
                    builder.Append(property.Name);
                    builder.Append('=');
                }

                builder.Append(ODataUriUtils.ConvertToUriLiteral(property.Value, ODataVersion.V4));
            }
            builder.Append(')');

            return(new Uri(builder.ToString(), UriKind.Absolute));
        }
Пример #27
0
        public void ApplyProperty_PassesWithCaseInsensitivePropertyName()
        {
            // Arrange
            ODataProperty property = new ODataProperty {
                Name = "keY1", Value = "Value1"
            };
            EdmEntityType entityType = new EdmEntityType("namespace", "name");

            entityType.AddKeys(entityType.AddStructuralProperty("Key1",
                                                                EdmLibHelpers.GetEdmPrimitiveTypeReferenceOrNull(typeof(string))));

            EdmEntityTypeReference    entityTypeReference = new EdmEntityTypeReference(entityType, isNullable: false);
            ODataDeserializerProvider provider            = ODataDeserializerProviderFactory.Create();

            var  resource     = new Mock <IDelta>(MockBehavior.Strict);
            Type propertyType = typeof(string);

            resource.Setup(r => r.TryGetPropertyType("Key1", out propertyType)).Returns(true).Verifiable();
            resource.Setup(r => r.TrySetPropertyValue("Key1", "Value1")).Returns(true).Verifiable();

#if NETCORE
            IRouteBuilder builder = RoutingConfigurationFactory.Create();

            HttpRequest request = RequestFactory.Create(builder);
#else
            HttpConfiguration  configuration = RoutingConfigurationFactory.CreateWithRootContainer("OData");
            HttpRequestMessage request       = RequestFactory.Create(configuration);
#endif

            ODataDeserializerContext context = new ODataDeserializerContext
            {
                Model   = new EdmModel(),
                Request = request
            };

            // Act
            DeserializationHelpers.ApplyProperty(property, entityTypeReference, resource.Object, provider,
                                                 context);

            // Assert
            resource.Verify();
        }
Пример #28
0
        /// <inheritdoc />
        public override object Read(ODataMessageReader messageReader, Type type, ODataDeserializerContext readContext)
        {
            if (messageReader == null)
            {
                throw new ArgumentNullException(nameof(messageReader));
            }

            if (readContext == null)
            {
                throw new ArgumentNullException(nameof(readContext));
            }

            IEdmTypeReference edmType = readContext.GetEdmType(type);

            Contract.Assert(edmType != null);

            ODataProperty property = messageReader.ReadProperty(edmType);

            return(ReadInline(property, edmType, readContext));
        }
Пример #29
0
        private ODataProperty ReadProperty(IEdmTypeReference expectedPropertyTypeReference, ODataNullValueBehaviorKind nullValueReadBehaviorKind, bool epmPresent)
        {
            ODataProperty property  = new ODataProperty();
            string        localName = base.XmlReader.LocalName;

            ValidationUtils.ValidatePropertyName(localName);
            property.Name = localName;
            object obj2 = this.ReadNonEntityValueImplementation(expectedPropertyTypeReference, null, null, nullValueReadBehaviorKind == ODataNullValueBehaviorKind.Default, epmPresent);

            if ((nullValueReadBehaviorKind == ODataNullValueBehaviorKind.IgnoreValue) && (obj2 == null))
            {
                property = null;
            }
            else
            {
                property.Value = obj2;
            }
            base.XmlReader.Read();
            return(property);
        }
Пример #30
0
        protected static object CreateCollectionInstance(ODataProperty collectionProperty, Type userCollectionType, System.Data.Services.Client.ResponseInfo responseInfo)
        {
            object obj2;
            ODataCollectionValue value2     = collectionProperty.Value as ODataCollectionValue;
            ClientTypeAnnotation annotation = responseInfo.TypeResolver.ResolveEdmTypeName(userCollectionType, value2.TypeName);

            if (IsDataServiceCollection(annotation.ElementType))
            {
                throw System.Data.Services.Client.Error.InvalidOperation(System.Data.Services.Client.Strings.AtomMaterializer_DataServiceCollectionNotSupportedForNonEntities);
            }
            try
            {
                obj2 = annotation.CreateInstance();
            }
            catch (MissingMethodException exception)
            {
                throw System.Data.Services.Client.Error.InvalidOperation(System.Data.Services.Client.Strings.AtomMaterializer_NoParameterlessCtorForCollectionProperty(collectionProperty.Name, annotation.ElementTypeName), exception);
            }
            return(obj2);
        }
Пример #31
0
        /// <inheritdoc />
        public override object Read(ODataMessageReader messageReader, Type type, ODataDeserializerContext readContext)
        {
            if (messageReader == null)
            {
                throw Error.ArgumentNull("messageReader");
            }

            IEdmTypeReference edmType = readContext.GetEdmType(type);

            Contract.Assert(edmType != null);

            if (!edmType.IsComplex())
            {
                throw Error.Argument("type", SRResources.ArgumentMustBeOfType, EdmTypeKind.Complex);
            }

            ODataProperty property = messageReader.ReadProperty();

            return(ReadInline(property, edmType, readContext));
        }
Пример #32
0
        private void EntryStarting(WritingEntryArgs ea)
        {
            var odataProps = ea.Entry.Properties as List <ODataProperty>;

            var entityState = contextWrapper.Context.Entities.First(e => e.Entity == ea.Entity).State;

            // Send up an undeclared property on an Open Type.
            if (entityState == EntityStates.Modified || entityState == EntityStates.Added)
            {
                if (ea.Entity.GetType() == typeof(Row))
                {
                    // In practice, the data from this undeclared property would probably be stored in a transient property of the partial companion class to the client proxy.
                    var undeclaredOdataProperty = new ODataProperty()
                    {
                        Name = "dynamicPropertyKey", Value = "dynamicPropertyValue"
                    };
                    odataProps.Add(undeclaredOdataProperty);
                }
            }
        }
        /// <inheritdoc />
        public override async Task <object> ReadAsync(ODataMessageReader messageReader, Type type, ODataDeserializerContext readContext)
        {
            if (messageReader == null)
            {
                throw new ArgumentNullException(nameof(messageReader));
            }

            if (readContext == null)
            {
                throw new ArgumentNullException(nameof(readContext));
            }

            IEdmTypeReference edmType = readContext.GetEdmType(type);

            Contract.Assert(edmType != null);

            ODataProperty property = await messageReader.ReadPropertyAsync(edmType).ConfigureAwait(false);

            return(ReadInline(property, edmType, readContext));
        }
Пример #34
0
        public override Task WriteObjectAsync(object graph, Type type, ODataMessageWriter messageWriter, ODataSerializerContext writeContext)
        {
            var pageResult = graph as PageResult <object>;
            var results    = pageResult.Items.ToList();

            foreach (var item in results)
            {
                var groupByWrapper = item as GroupByWrapper;
                foreach (var value in groupByWrapper.Values)
                {
                    var oDataProperty = new ODataProperty
                    {
                        Name  = value.Key,
                        Value = value.Value
                    };
                    messageWriter.WriteProperty(oDataProperty);
                }
            }
            return(Task.FromResult <object>(null));
        }
        /// <summary>
        /// Deserializes the primitive from the given <paramref name="primitiveProperty"/> under the given <paramref name="readContext"/>.
        /// </summary>
        /// <param name="primitiveProperty">The primitive property to deserialize.</param>
        /// <param name="readContext">The deserializer context.</param>
        /// <returns>The deserialized OData primitive value.</returns>
        public virtual object ReadPrimitive(ODataProperty primitiveProperty, ODataDeserializerContext readContext)
        {
            if (primitiveProperty == null)
            {
                throw Error.ArgumentNull("primitiveProperty");
            }

            if (readContext == null)
            {
                throw Error.ArgumentNull("readContext");
            }

            //Try and change the value appropriately if type is specified
            if (readContext.ResourceType != null && primitiveProperty.Value != null)
            {
                return(EdmPrimitiveHelper.ConvertPrimitiveValue(primitiveProperty.Value, readContext.ResourceType, readContext.TimeZone));
            }

            return(primitiveProperty.Value);
        }
Пример #36
0
        /// <summary>
        /// Serialize the given property as a non-top-level property in JSON Light.
        /// </summary>
        /// <param name="odataProperty">The property to serialize.</param>
        /// <returns>A string of JSON text, where the given ODataProperty has been serialized and wrapped in a JSON object.</returns>
        private string SerializeProperty(IEdmStructuredType owningType, ODataProperty odataProperty)
        {
            MemoryStream outputStream = new MemoryStream();
            ODataJsonLightOutputContext jsonLightOutputContext = this.CreateJsonLightOutputContext(outputStream);
            var serializer = new ODataJsonLightPropertySerializer(jsonLightOutputContext);

            jsonLightOutputContext.JsonWriter.StartObjectScope();
            serializer.WriteProperties(
                owningType,
                new[] { odataProperty },
                /*isComplexValue*/ false,
                new NullDuplicatePropertyNameChecker());
            jsonLightOutputContext.JsonWriter.EndObjectScope();

            jsonLightOutputContext.Flush();
            outputStream.Position = 0;
            string result = new StreamReader(outputStream).ReadToEnd();

            return(result);
        }
Пример #37
0
        internal static void ApplyProperty(ODataProperty property, IEdmStructuredTypeReference resourceType, object resource,
                                           IODataDeserializerProvider deserializerProvider, ODataDeserializerContext readContext)
        {
            IEdmStructuredType structuredType = resourceType.StructuredDefinition();
            IEdmProperty       edmProperty    = structuredType == null ? null : structuredType.ResolveProperty(property.Name);

            bool   isDynamicProperty = false;
            string propertyName      = property.Name;

            if (edmProperty != null)
            {
                propertyName = readContext.Model.GetClrPropertyName(edmProperty);
            }
            else
            {
                isDynamicProperty = structuredType != null && structuredType.IsOpen;
            }

            if (!isDynamicProperty && edmProperty == null)
            {
                throw new ODataException(
                          Error.Format(SRResources.CannotDeserializeUnknownProperty, property.Name, resourceType.Definition));
            }

            // dynamic properties have null values
            IEdmTypeReference propertyType = edmProperty != null ? edmProperty.Type : null;

            EdmTypeKind propertyKind;
            object      value = ConvertValue(property.Value, ref propertyType, deserializerProvider, readContext,
                                             out propertyKind);

            if (isDynamicProperty)
            {
                SetDynamicProperty(resource, resourceType, propertyKind, propertyName, value, propertyType,
                                   readContext.Model);
            }
            else
            {
                SetDeclaredProperty(resource, propertyKind, propertyName, value, edmProperty, readContext);
            }
        }
Пример #38
0
        public void QueryTopLevelProperies()
        {
            ODataMessageReaderSettings readerSettings = new ODataMessageReaderSettings()
            {
                BaseUri = ServiceBaseUri
            };

            foreach (var mimeType in mimeTypes)
            {
                var requestMessage = new HttpWebRequestMessage(new Uri(ServiceBaseUri.AbsoluteUri + "Orders(7)/ShipDate", UriKind.Absolute));
                requestMessage.SetHeader("Accept", mimeType);
                var responseMessage = requestMessage.GetResponse();
                Assert.AreEqual(200, responseMessage.StatusCode);

                if (!mimeType.Contains(MimeTypes.ODataParameterNoMetadata))
                {
                    using (var messageReader = new ODataMessageReader(responseMessage, readerSettings, Model))
                    {
                        ODataProperty property = messageReader.ReadProperty();
                        Assert.AreEqual(new Date(2014, 8, 31), property.Value);
                    }
                }
            }

            foreach (var mimeType in mimeTypes)
            {
                var requestMessage = new HttpWebRequestMessage(new Uri(ServiceBaseUri.AbsoluteUri + "Orders(7)/ShipTime", UriKind.Absolute));
                requestMessage.SetHeader("Accept", mimeType);
                var responseMessage = requestMessage.GetResponse();
                Assert.AreEqual(200, responseMessage.StatusCode);

                if (!mimeType.Contains(MimeTypes.ODataParameterNoMetadata))
                {
                    using (var messageReader = new ODataMessageReader(responseMessage, readerSettings, Model))
                    {
                        ODataProperty property = messageReader.ReadProperty();
                        Assert.AreEqual(new TimeOfDay(12, 40, 5, 50), property.Value);
                    }
                }
            }
        }
        public async Task WriteSpatialCollectionPropertyAsync()
        {
            var geographyCollection = new object[]
            {
                GeographyFactory.Collection().Point(-19.99, -12.0).Build(),
                GeographyFactory.LineString(33.1, -110.0).LineTo(35.97, -110).Build(),
                GeographyFactory.MultiLineString().LineString(10.2, 11.2).LineTo(11.9, 11.6).LineString(16.2, 17.2).LineTo(18.9, 19.6).Build(),
                GeographyFactory.MultiPoint().Point(10.2, 11.2).Point(11.9, 11.6).Build(),
                GeographyFactory.MultiPolygon().Polygon().Ring(10.2, 11.2).LineTo(11.9, 11.6).LineTo(11.45, 87.75).Ring(16.2, 17.2).LineTo(18.9, 19.6).LineTo(11.45, 87.75).Build(),
                GeographyFactory.Point(33.1, -110.0).Build(),
                GeographyFactory.Polygon().Ring(33.1, -110.0).LineTo(35.97, -110.15).LineTo(11.45, 87.75).Ring(35.97, -110).LineTo(36.97, -110.15).LineTo(45.23, 23.18).Build(),
                GeographyFactory.Point(32.0, -100.0).Build()
            };

            var geographyCollectionProperty = new ODataProperty
            {
                Name  = "GeographyCollectionProperty",
                Value = new ODataCollectionValue
                {
                    TypeName = "Collection(Edm.Geography)",
                    Items    = geographyCollection
                }
            };

            var result = await SetupJsonLightOutputContextAndRunTestAsync(
                (jsonLightOutputContext) => jsonLightOutputContext.WritePropertyAsync(geographyCollectionProperty));

            Assert.Equal(
                "{\"@odata.context\":\"http://tempuri.org/$metadata#Collection(Edm.Geography)\"," +
                "\"value\":[" +
                "{\"type\":\"GeometryCollection\",\"geometries\":[{\"type\":\"Point\",\"coordinates\":[-12.0,-19.99]}],\"crs\":{\"type\":\"name\",\"properties\":{\"name\":\"EPSG:4326\"}}}," +
                "{\"type\":\"LineString\",\"coordinates\":[[-110.0,33.1],[-110.0,35.97]],\"crs\":{\"type\":\"name\",\"properties\":{\"name\":\"EPSG:4326\"}}}," +
                "{\"type\":\"MultiLineString\",\"coordinates\":[[[11.2,10.2],[11.6,11.9]],[[17.2,16.2],[19.6,18.9]]],\"crs\":{\"type\":\"name\",\"properties\":{\"name\":\"EPSG:4326\"}}}," +
                "{\"type\":\"MultiPoint\",\"coordinates\":[[11.2,10.2],[11.6,11.9]],\"crs\":{\"type\":\"name\",\"properties\":{\"name\":\"EPSG:4326\"}}}," +
                "{\"type\":\"MultiPolygon\",\"coordinates\":[[[[11.2,10.2],[11.6,11.9],[87.75,11.45],[11.2,10.2]],[[17.2,16.2],[19.6,18.9],[87.75,11.45],[17.2,16.2]]]],\"crs\":{\"type\":\"name\",\"properties\":{\"name\":\"EPSG:4326\"}}}," +
                "{\"type\":\"Point\",\"coordinates\":[-110.0,33.1],\"crs\":{\"type\":\"name\",\"properties\":{\"name\":\"EPSG:4326\"}}}," +
                "{\"type\":\"Polygon\",\"coordinates\":[[[-110.0,33.1],[-110.15,35.97],[87.75,11.45],[-110.0,33.1]],[[-110.0,35.97],[-110.15,36.97],[23.18,45.23],[-110.0,35.97]]],\"crs\":{\"type\":\"name\",\"properties\":{\"name\":\"EPSG:4326\"}}}," +
                "{\"type\":\"Point\",\"coordinates\":[-100.0,32.0],\"crs\":{\"type\":\"name\",\"properties\":{\"name\":\"EPSG:4326\"}}}" +
                "]}",
                result);
        }
Пример #40
0
 public ODataPropertyTests()
 {
     this.property = new ODataProperty();
 }
        /// <summary>
        /// Returns an existing stream property value if it already exists in the list of OData properties otherwise creates a new 
        /// ODataProperty for the stream property and returns the value of that property.
        /// </summary>
        /// <param name="entryState">The reader entry state for the entry being read.</param>
        /// <param name="streamPropertyName">The name of the stream property to return.</param>
        /// <returns>A new or an existing stream property value.</returns>
        private ODataStreamReferenceValue GetNewOrExistingStreamPropertyValue(IODataAtomReaderEntryState entryState, string streamPropertyName)
        {
            Debug.Assert(entryState != null, "entryState != null");
            Debug.Assert(streamPropertyName != null, "streamPropertyName != null");

            ReadOnlyEnumerable<ODataProperty> properties = entryState.Entry.Properties.ToReadOnlyEnumerable("Properties");

            // Property names are case sensitive, so compare in a case sensitive way.
            ODataProperty streamProperty = properties.FirstOrDefault(p => String.CompareOrdinal(p.Name, streamPropertyName) == 0);

            ODataStreamReferenceValue streamReferenceValue;
            if (streamProperty == null)
            {
                // The ValidateLinkPropertyDefined will fail if a stream property is not defined and the reader settings don't allow
                // reporting undeclared link properties. So if the method returns null, it means report the undeclared property anyway.
                IEdmProperty streamEdmProperty = ReaderValidationUtils.ValidateLinkPropertyDefined(streamPropertyName, entryState.EntityType, this.MessageReaderSettings);

                streamReferenceValue = new ODataStreamReferenceValue();
                streamProperty = new ODataProperty
                {
                    Name = streamPropertyName,
                    Value = streamReferenceValue
                };

                ReaderValidationUtils.ValidateStreamReferenceProperty(streamProperty, entryState.EntityType, streamEdmProperty, this.MessageReaderSettings);
                entryState.DuplicatePropertyNamesChecker.CheckForDuplicatePropertyNames(streamProperty);
                properties.AddToSourceList(streamProperty);
            }
            else
            {
                streamReferenceValue = streamProperty.Value as ODataStreamReferenceValue;
                if (streamReferenceValue == null)
                {
                    throw new ODataException(ODataErrorStrings.ODataAtomEntryAndFeedDeserializer_StreamPropertyDuplicatePropertyName(streamPropertyName));
                }
            }

            return streamReferenceValue;
        }
 public void FlagsEnumAsTopLevelProperty_StrAsValue_StrAsTypeName_FullMetadata()
 {
     ReadFromMessageReaderAndVerifyPayload(
         payload: "<?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/test/$metadata#NS.Color\" m:type=\"#NS.Color\" " +
                     "xmlns:m=\"http://docs.oasis-open.org/odata/ns/metadata\">" +
                     "Red" +
                 "</m:value>",
         readerAction: (reader) =>
         {
             ODataProperty expectedProperty = new ODataProperty()
             {
                 Name = null,
                 Value = new ODataEnumValue(Color.Red.ToString(), "NS.Color")
             };
             ODataProperty property = reader.ReadProperty();
             TestUtils.AssertODataPropertyAreEqual(expectedProperty, property);
         }
     );
 }
        /// <summary>
        /// This method creates an reads the property from the input and 
        /// returns an <see cref="ODataProperty"/> representing the read property.
        /// </summary>
        /// <param name="expectedPropertyTypeReference">The expected type reference of the property to read.</param>
        /// <param name="duplicatePropertyNamesChecker">The duplicate property names checker to use.</param>
        /// <returns>An <see cref="ODataProperty"/> representing the read property.</returns>
        /// <remarks>
        /// The method assumes that the ReadPayloadStart has already been called and it will not call ReadPayloadEnd.
        /// </remarks>
        private ODataProperty ReadTopLevelPropertyImplementation(IEdmTypeReference expectedPropertyTypeReference, DuplicatePropertyNamesChecker duplicatePropertyNamesChecker)
        {
            Debug.Assert(
                expectedPropertyTypeReference == null || !expectedPropertyTypeReference.IsODataEntityTypeKind(),
                "If the expected type is specified it must not be an entity type.");
            Debug.Assert(duplicatePropertyNamesChecker != null, "duplicatePropertyNamesChecker != null");

            expectedPropertyTypeReference = this.UpdateExpectedTypeBasedOnContextUri(expectedPropertyTypeReference);

            object propertyValue = missingPropertyValue;
            var customInstanceAnnotations = new Collection<ODataInstanceAnnotation>();

            // Check for the special top-level null marker
            if (this.IsTopLevelNullValue())
            {
                // NOTE: when reading a null value we will never ask the type resolver (if present) to resolve the
                //       type; we always fall back to the expected type.
                ReaderValidationUtils.ValidateNullValue(
                    this.Model,
                    expectedPropertyTypeReference,
                    this.MessageReaderSettings,
                    /*validateNullValue*/ true,
                    /*propertyName*/ null);

                // We don't allow properties or non-custom annotations in the null payload.
                this.ValidateNoPropertyInNullPayload(duplicatePropertyNamesChecker);

                propertyValue = null;
            }
            else
            {
                string payloadTypeName = null;
                if (this.ReadingComplexProperty(duplicatePropertyNamesChecker, expectedPropertyTypeReference, out payloadTypeName))
                {
                    // Figure out whether we are reading a complex property or not; complex properties are not wrapped while all others are.
                    // Since we don't have metadata in all cases (open properties), we have to detect the type in some cases.
                    this.AssertJsonCondition(JsonNodeType.Property, JsonNodeType.EndObject);

                    // Now read the property value
                    propertyValue = this.ReadNonEntityValue(
                        payloadTypeName,
                        expectedPropertyTypeReference,
                        duplicatePropertyNamesChecker,
                        /*collectionValidator*/ null,
                        /*validateNullValue*/ true,
                        /*isTopLevelPropertyValue*/ true,
                        /*insideComplexValue*/ true,
                        /*propertyName*/ null);
                }
                else
                {
                    bool isReordering = this.JsonReader is ReorderingJsonReader;

                    Func<string, object> propertyAnnotationReaderForTopLevelProperty =
                        annotationName => { throw new ODataException(ODataErrorStrings.ODataJsonLightPropertyAndValueDeserializer_UnexpectedODataPropertyAnnotation(annotationName)); };

                    // Read through all top-level properties, ignore the ones with reserved names (i.e., reserved 
                    // characters in their name) and throw if we find none or more than one properties without reserved name.
                    while (this.JsonReader.NodeType == JsonNodeType.Property)
                    {
                        this.ProcessProperty(
                            duplicatePropertyNamesChecker,
                            propertyAnnotationReaderForTopLevelProperty,
                            (propertyParsingResult, propertyName) =>
                            {
                                switch (propertyParsingResult)
                                {
                                    case PropertyParsingResult.ODataInstanceAnnotation:
                                        if (string.CompareOrdinal(ODataAnnotationNames.ODataType, propertyName) == 0)
                                        {
                                            // When we are not using the reordering reader we have to ensure that the 'odata.type' property appears before
                                            // the 'value' property; otherwise we already scanned ahead and read the type name and have to now
                                            // ignore it (even if it is after the 'value' property).
                                            if (isReordering)
                                            {
                                                this.JsonReader.SkipValue();
                                            }
                                            else
                                            {
                                                if (!object.ReferenceEquals(missingPropertyValue, propertyValue))
                                                {
                                                    throw new ODataException(
                                                        ODataErrorStrings.ODataJsonLightPropertyAndValueDeserializer_TypePropertyAfterValueProperty(ODataAnnotationNames.ODataType, JsonLightConstants.ODataValuePropertyName));
                                                }

                                                payloadTypeName = this.ReadODataTypeAnnotationValue();
                                            }
                                        }
                                        else
                                        {
                                            throw new ODataException(ODataErrorStrings.ODataJsonLightPropertyAndValueDeserializer_UnexpectedAnnotationProperties(propertyName));
                                        }

                                        break;
                                    case PropertyParsingResult.CustomInstanceAnnotation:
                                        ODataAnnotationNames.ValidateIsCustomAnnotationName(propertyName);
                                        Debug.Assert(
                                            !this.MessageReaderSettings.ShouldSkipAnnotation(propertyName),
                                            "!this.MessageReaderSettings.ShouldReadAndValidateAnnotation(annotationName) -- otherwise we should have already skipped the custom annotation and won't see it here.");
                                        var customInstanceAnnotationValue = this.ReadCustomInstanceAnnotationValue(duplicatePropertyNamesChecker, propertyName);
                                        customInstanceAnnotations.Add(new ODataInstanceAnnotation(propertyName, customInstanceAnnotationValue.ToODataValue()));
                                        break;

                                    case PropertyParsingResult.PropertyWithoutValue:
                                        throw new ODataException(ODataErrorStrings.ODataJsonLightPropertyAndValueDeserializer_TopLevelPropertyAnnotationWithoutProperty(propertyName));

                                    case PropertyParsingResult.PropertyWithValue:
                                        if (string.CompareOrdinal(JsonLightConstants.ODataValuePropertyName, propertyName) == 0)
                                        {
                                            // Now read the property value
                                            propertyValue = this.ReadNonEntityValue(
                                                payloadTypeName,
                                                expectedPropertyTypeReference,
                                                /*duplicatePropertyNamesChecker*/ null,
                                                /*collectionValidator*/ null,
                                                /*validateNullValue*/ true,
                                                /*isTopLevelPropertyValue*/ true,
                                                /*insideComplexValue*/ false,
                                                /*propertyName*/ propertyName);
                                        }
                                        else
                                        {
                                            throw new ODataException(
                                                ODataErrorStrings.ODataJsonLightPropertyAndValueDeserializer_InvalidTopLevelPropertyName(propertyName, JsonLightConstants.ODataValuePropertyName));
                                        }

                                        break;

                                    case PropertyParsingResult.EndOfObject:
                                        break;

                                    case PropertyParsingResult.MetadataReferenceProperty:
                                        throw new ODataException(ODataErrorStrings.ODataJsonLightPropertyAndValueDeserializer_UnexpectedMetadataReferenceProperty(propertyName));
                                }
                            });
                    }

                    if (object.ReferenceEquals(missingPropertyValue, propertyValue))
                    {
                        // No property found; there should be exactly one property in the top-level property wrapper that does not have a reserved name.
                        throw new ODataException(ODataErrorStrings.ODataJsonLightPropertyAndValueDeserializer_InvalidTopLevelPropertyPayload);
                    }
                }
            }

            Debug.Assert(!object.ReferenceEquals(missingPropertyValue, propertyValue), "!object.ReferenceEquals(missingPropertyValue, propertyValue)");
            ODataProperty resultProperty = new ODataProperty()
            {
                // The property name is not on the context URI or the payload, we report null.
                Name = null,
                Value = propertyValue,
                InstanceAnnotations = customInstanceAnnotations
            };

            // Read over the end object - note that this might be the last node in the input (in case there's no response wrapper)
            this.JsonReader.Read();
            return resultProperty;
        }
        /// <summary>
        /// Reads a complex value.
        /// </summary>
        /// <param name="complexValueTypeReference">The expected type reference of the value.</param>
        /// <param name="payloadTypeName">The type name read from the payload.</param>
        /// <param name="serializationTypeNameAnnotation">The serialization type name for the collection value (possibly null).</param>
        /// <param name="duplicatePropertyNamesChecker">The duplicate property names checker to use - this is always initialized as necessary, do not clear.</param>
        /// <returns>The value of the complex value.</returns>
        /// <remarks>
        /// Pre-Condition:  JsonNodeType.Property - the first property of the complex value object, or the second one if the first one was odata.type.
        ///                 JsonNodeType.EndObject - the end object of the complex value object.
        /// Post-Condition: almost anything - the node after the complex value (after the EndObject)
        /// </remarks>
        private ODataComplexValue ReadComplexValue(
            IEdmComplexTypeReference complexValueTypeReference,
            string payloadTypeName,
            SerializationTypeNameAnnotation serializationTypeNameAnnotation,
            DuplicatePropertyNamesChecker duplicatePropertyNamesChecker)
        {
            this.AssertJsonCondition(JsonNodeType.Property, JsonNodeType.EndObject);
            Debug.Assert(duplicatePropertyNamesChecker != null, "duplicatePropertyNamesChecker != null");

            this.IncreaseRecursionDepth();

            ODataComplexValue complexValue = new ODataComplexValue();
            complexValue.TypeName = complexValueTypeReference != null ? complexValueTypeReference.FullName() : payloadTypeName;
            if (serializationTypeNameAnnotation != null)
            {
                complexValue.SetAnnotation(serializationTypeNameAnnotation);
            }

            if (complexValueTypeReference != null)
            {
                complexValue.SetAnnotation(new ODataTypeAnnotation(complexValueTypeReference));
            }

            List<ODataProperty> properties = new List<ODataProperty>();
            while (this.JsonReader.NodeType == JsonNodeType.Property)
            {
                this.ReadPropertyCustomAnnotationValue = this.ReadCustomInstanceAnnotationValue;
                this.ProcessProperty(
                    duplicatePropertyNamesChecker,
                    this.ReadTypePropertyAnnotationValue,
                    (propertyParsingResult, propertyName) =>
                    {
                        switch (propertyParsingResult)
                        {
                            case PropertyParsingResult.ODataInstanceAnnotation:
                                if (string.CompareOrdinal(ODataAnnotationNames.ODataType, propertyName) == 0)
                                {
                                    throw new ODataException(ODataErrorStrings.ODataJsonLightPropertyAndValueDeserializer_ComplexTypeAnnotationNotFirst);
                                }
                                else
                                {
                                    throw new ODataException(ODataErrorStrings.ODataJsonLightPropertyAndValueDeserializer_UnexpectedAnnotationProperties(propertyName));
                                }

                            case PropertyParsingResult.CustomInstanceAnnotation:
                                ODataAnnotationNames.ValidateIsCustomAnnotationName(propertyName);
                                Debug.Assert(
                                    !this.MessageReaderSettings.ShouldSkipAnnotation(propertyName),
                                    "!this.MessageReaderSettings.ShouldReadAndValidateAnnotation(annotationName) -- otherwise we should have already skipped the custom annotation and won't see it here.");
                                var customInstanceAnnotationValue = this.ReadCustomInstanceAnnotationValue(duplicatePropertyNamesChecker, propertyName);
                                complexValue.InstanceAnnotations.Add(new ODataInstanceAnnotation(propertyName, customInstanceAnnotationValue.ToODataValue()));
                                break;

                            case PropertyParsingResult.PropertyWithoutValue:
                                throw new ODataException(ODataErrorStrings.ODataJsonLightPropertyAndValueDeserializer_ComplexValuePropertyAnnotationWithoutProperty(propertyName));

                            case PropertyParsingResult.PropertyWithValue:
                                // Any other property is data
                                ODataProperty property = new ODataProperty();
                                property.Name = propertyName;

                                // Lookup the property in metadata
                                IEdmProperty edmProperty = null;
                                bool ignoreProperty = false;
                                if (complexValueTypeReference != null)
                                {
                                    edmProperty = ReaderValidationUtils.ValidateValuePropertyDefined(propertyName, complexValueTypeReference.ComplexDefinition(), this.MessageReaderSettings, out ignoreProperty);
                                }

                                if (ignoreProperty
                                    && (this.JsonReader.NodeType == JsonNodeType.StartObject || this.JsonReader.NodeType == JsonNodeType.StartArray))
                                {
                                    this.JsonReader.SkipValue();
                                }
                                else
                                {
                                    // EdmLib bridge marks all key properties as non-nullable, but Astoria allows them to be nullable.
                                    // If the property has an annotation to ignore null values, we need to omit the property in requests.
                                    ODataNullValueBehaviorKind nullValueReadBehaviorKind = this.ReadingResponse || edmProperty == null
                                        ? ODataNullValueBehaviorKind.Default
                                        : this.Model.NullValueReadBehaviorKind(edmProperty);

                                    // Read the property value
                                    object propertyValue = this.ReadNonEntityValueImplementation(
                                        ValidateDataPropertyTypeNameAnnotation(duplicatePropertyNamesChecker, propertyName),
                                        edmProperty == null ? null : edmProperty.Type,
                                        /*duplicatePropertyNamesChecker*/ null,
                                        /*collectionValidator*/ null,
                                        nullValueReadBehaviorKind == ODataNullValueBehaviorKind.Default,
                                        /*isTopLevelPropertyValue*/ false,
                                        /*insideComplexValue*/ false,
                                        propertyName,
                                        edmProperty == null);

                                    if (nullValueReadBehaviorKind != ODataNullValueBehaviorKind.IgnoreValue || propertyValue != null)
                                    {
                                        duplicatePropertyNamesChecker.CheckForDuplicatePropertyNames(property);
                                        property.Value = propertyValue;
                                        var propertyAnnotations = duplicatePropertyNamesChecker.GetCustomPropertyAnnotations(propertyName);
                                        if (propertyAnnotations != null)
                                        {
                                            foreach (var annotation in propertyAnnotations)
                                            {
                                                if (annotation.Value != null)
                                                {
                                                    // annotation.Value == null indicates that this annotation should be skipped.
                                                    property.InstanceAnnotations.Add(new ODataInstanceAnnotation(annotation.Key, annotation.Value.ToODataValue()));
                                                }
                                            }
                                        }

                                        properties.Add(property);
                                    }
                                }

                                break;

                            case PropertyParsingResult.EndOfObject:
                                break;

                            case PropertyParsingResult.MetadataReferenceProperty:
                                throw new ODataException(ODataErrorStrings.ODataJsonLightPropertyAndValueDeserializer_UnexpectedMetadataReferenceProperty(propertyName));
                        }
                    });
            }

            Debug.Assert(this.JsonReader.NodeType == JsonNodeType.EndObject, "After all the properties of a complex value are read the EndObject node is expected.");
            this.JsonReader.ReadEndObject();

            complexValue.Properties = new ReadOnlyEnumerable<ODataProperty>(properties);

            this.DecreaseRecursionDepth();

            return complexValue;
        }
Пример #45
0
 /// <summary>
 /// Writes an <see cref="ODataProperty"/> as message payload.
 /// </summary>
 /// <param name="property">The property to write</param>
 public void WriteProperty(ODataProperty property)
 {
     this.WriteToStream(this.WritePropertyImplementation(property));
 }
 /// <summary>
 /// Writes the property start element.
 /// </summary>
 /// <param name="beforePropertyCallback">Action called before anything else is written (if it's not null).</param>
 /// <param name="property">The odata property to write.</param>
 /// <param name="isWritingCollection">true if we are writing a collection instead of an entry.</param>
 /// <param name="isTopLevel">true if writing a top-level property payload; otherwise false.</param>
 private void WritePropertyStart(Action beforePropertyCallback, ODataProperty property, bool isWritingCollection, bool isTopLevel)
 {
     this.WritePropertyStart(beforePropertyCallback, property.Name, property.ODataValue, isWritingCollection, isTopLevel);
 }
Пример #47
0
        /// <summary>
        /// Creates the value for the stream property's link relation attribute.
        /// </summary>
        /// <param name="streamProperty">The stream property to create the relation for.</param>
        /// <param name="forEditLink">'true' if the relation is computed for an edit link; otherwise 'false'.</param>
        /// <returns>The relation attribute value for the stream property's link relation.</returns>
        internal static string ComputeStreamPropertyRelation(ODataProperty streamProperty, bool forEditLink)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(streamProperty != null, "streamProperty != null");
            Debug.Assert(!string.IsNullOrEmpty(streamProperty.Name), "!string.IsNullOrEmpty(streamProperty.Name)");

            string segmentName = forEditLink ? AtomConstants.ODataStreamPropertyEditMediaSegmentName : AtomConstants.ODataStreamPropertyMediaResourceSegmentName;
            return string.Join("/", new string[] { AtomConstants.ODataNamespace, segmentName, streamProperty.Name });
        }
        /// <summary>
        /// Gets the CLR value for a primitive property.
        /// </summary>
        /// <param name="entityTypeName">The name of the entity type to get the property value.</param>
        /// <param name="property">The ODataProperty to get the value from.</param>
        /// <param name="isKeyProperty">true if the property is a key property, false otherwise.</param>
        /// <returns>The clr value of the property.</returns>
        private static object GetPrimitivePropertyClrValue(string entityTypeName, ODataProperty property, bool isKeyProperty)
        {
            object propertyValue = property.Value;
            if (propertyValue == null && isKeyProperty)
            {
                throw new ODataException(OData.Core.Strings.ODataEntryMetadataContext_NullKeyValue(property.Name, entityTypeName));
            }

            if (propertyValue is ODataValue)
            {
                throw new ODataException(OData.Core.Strings.ODataEntryMetadataContext_KeyOrETagValuesMustBePrimitiveValues(property.Name, entityTypeName));
            }

            return propertyValue;
        }
 public void FlagsEnumAsTopLevelProperty_StrAsValue_StrAsTypeName()
 {
     WriteToMessageWriterAndVerifyPayload(
         contentType: "application/xml;",
         writerAction: (writer) =>
         {
             ODataProperty property = new ODataProperty()
             {
                 Name = "MyColorPropertyName",
                 Value = new ODataEnumValue(Color.Red.ToString(), "NS.EnumUndefinedTypename")
             };
             writer.WriteProperty(property);
         },
         expectedPayload: "<?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/test/$metadata#NS.EnumUndefinedTypename\" m:type=\"#NS.EnumUndefinedTypename\" " +
                     "xmlns:m=\"http://docs.oasis-open.org/odata/ns/metadata\">" +
                     "Red" +
                 "</m:value>"
     );
 }
Пример #50
0
        /// <summary>
        /// Write an <see cref="ODataProperty" /> to the given stream. This method creates an
        /// async buffered stream, writes the property to it and returns an <see cref="AsyncWriter"/>
        /// that can be used to flush and close/dispose the stream.
        /// </summary>
        /// <param name="stream">The stream to write the property to.</param>
        /// <param name="property">The property to write.</param>
        /// <returns>An <see cref="AsyncWriter"/> that can be used to flush and close/dispose the stream.</returns>
        private AsyncWriter WriteProperty(Stream stream, ODataProperty property)
        {
            Debug.Assert(this.writerPayloadKind != ODataPayloadKind.Unsupported, "Expected payload kind, format and encoding to be set by now.");

            // TODO: how would we get the resource property for validation purposes here?
            return this.WriteTopLevelContent(
                stream, 
                (xmlWriter) => ODataAtomWriterUtils.WriteProperty(xmlWriter, this.metadataProvider, property, null, this.settings.Version, true, false, null, null),
                (jsonWriter) => ODataJsonWriterUtils.WriteTopLevelProperty(jsonWriter, this.metadataProvider, property, null, this.settings.Version, this.writingResponse),
                Strings.ODataMessageWriter_InvalidContentTypeForWritingProperty,
                InternalErrorCodes.ODataMessageWriter_WriteProperty);
        }
Пример #51
0
        /// <summary>
        /// Writes an <see cref="ODataProperty"/> as message payload.
        /// </summary>
        /// <param name="property">The property to write</param>
        /// <returns>A func which performs the actual writing given the stream to write to.</returns>
        private Func<Stream, AsyncWriter> WritePropertyImplementation(ODataProperty property)
        {
            this.VerifyWriterNotUsed();
            ExceptionUtils.CheckArgumentNotNull(property, "property");

            // Set the content type header here since all headers have to be set before getting the stream
            this.SetOrVerifyHeaders(ODataPayloadKind.Property);

            return (stream) => this.WriteProperty(stream, property);
        }
Пример #52
0
 /// <summary>
 /// Asynchronously writes an <see cref="ODataProperty"/> as message payload.
 /// </summary>
 /// <param name="property">The property to write</param>
 /// <returns>A task representing the asynchronous operation of writing the property.</returns>
 public Task WritePropertyAsync(ODataProperty property)
 {
     return this.WriteToStreamAsync(this.WritePropertyImplementation(property));
 }
        /// <summary>
        /// Reads a property.
        /// </summary>
        /// <param name="isTop">whether it is the top level</param>
        /// <param name="expectedPropertyName">The expected property name to be read from the payload (or null if no expected property name was specified).</param>
        /// <param name="expectedPropertyTypeReference">The expected type reference of the property value.</param>
        /// <param name="nullValueReadBehaviorKind">Behavior to use when reading null value for the property.</param>
        /// <returns>The ODataProperty representing the property in question; if null is returned from this method it means that the property is to be ignored.</returns>
        /// <remarks>
        /// Pre-Condition:   XmlNodeType.Element - The XML element representing the property to read.
        ///                                        Note that the method does NOT check for the property name neither it resolves the property against metadata.
        /// Post-Condition:  Any                 - The node after the property.
        /// </remarks>
        private ODataProperty ReadProperty(
            bool isTop,
            string expectedPropertyName, 
            IEdmTypeReference expectedPropertyTypeReference, 
            ODataNullValueBehaviorKind nullValueReadBehaviorKind)
        {
            Debug.Assert(
                expectedPropertyTypeReference == null || expectedPropertyTypeReference.IsODataPrimitiveTypeKind() || expectedPropertyTypeReference.IsODataEnumTypeKind() ||
                expectedPropertyTypeReference.IsODataComplexTypeKind() || expectedPropertyTypeReference.IsNonEntityCollectionType(),
                "Only primitive, Enum, complex and collection types can be read by this method.");
            this.AssertXmlCondition(XmlNodeType.Element);
            this.XmlReader.AssertNotBuffering();

            ODataProperty property = new ODataProperty();
            string propertyName = null;
            if (!isTop)
            {
                propertyName = this.XmlReader.LocalName;
                ValidationUtils.ValidatePropertyName(propertyName);
                ReaderValidationUtils.ValidateExpectedPropertyName(expectedPropertyName, propertyName);
            }

            property.Name = propertyName;

            object propertyValue = this.ReadNonEntityValueImplementation(
                expectedPropertyTypeReference, 
                /*duplicatePropertyNamesChecker*/ null, 
                /*collectionValidator*/ null,
                nullValueReadBehaviorKind == ODataNullValueBehaviorKind.Default,
                propertyName);

            if (nullValueReadBehaviorKind == ODataNullValueBehaviorKind.IgnoreValue && propertyValue == null)
            {
                property = null;
            }
            else
            {
                property.Value = propertyValue;
            }

            // Read past the end tag of the property or the start tag if the element is empty.
            this.XmlReader.Read();

            this.XmlReader.AssertNotBuffering();
            return property;
        }
        /// <summary>
        /// Test to see if <paramref name="property"/> is an open property or not.
        /// </summary>
        /// <param name="property">The property in question.</param>
        /// <param name="owningType">The owning type of the property.</param>
        /// <param name="edmProperty">The metadata of the property.</param>
        /// <returns>true if the property is an open property; false if it is not, or if openness cannot be determined</returns>
        private bool IsOpenProperty(ODataProperty property, IEdmStructuredType owningType, IEdmProperty edmProperty)
        {
            Debug.Assert(property != null, "property != null");
            if (property.SerializationInfo != null)
            {
                return property.SerializationInfo.PropertyKind == ODataPropertyKind.Open;
            }

            return (!this.WritingResponse && owningType == null) // Treat property as dynamic property when writing request and owning type is null
                || (owningType != null && owningType.IsOpen && edmProperty == null);
        }
        /// <summary>
        /// Adds a new property to an entry.
        /// </summary>
        /// <param name="entryState">The entry state for the entry to add the property to.</param>
        /// <param name="propertyName">The name of the property to add.</param>
        /// <param name="propertyValue">The value of the property to add.</param>
        private static void AddEntryProperty(IODataJsonLightReaderEntryState entryState, string propertyName, object propertyValue)
        {
            Debug.Assert(entryState != null, "entryState != null");
            Debug.Assert(!string.IsNullOrEmpty(propertyName), "!string.IsNullOrEmpty(propertyName)");

            ODataProperty property = new ODataProperty { Name = propertyName, Value = propertyValue };
            var propertyAnnotations = entryState.DuplicatePropertyNamesChecker.GetCustomPropertyAnnotations(propertyName);
            if (propertyAnnotations != null)
            {
                foreach (var annotation in propertyAnnotations)
                {
                    if (annotation.Value != null)
                    {
                        // annotation.Value == null indicates that this annotation should be skipped.
                        property.InstanceAnnotations.Add(new ODataInstanceAnnotation(annotation.Key, annotation.Value.ToODataValue()));
                    }
                }
            }

            entryState.DuplicatePropertyNamesChecker.CheckForDuplicatePropertyNames(property);

            ODataEntry entry = entryState.Entry;
            Debug.Assert(entry != null, "entry != null");
            entry.Properties = entry.Properties.ConcatToReadOnlyEnumerable("Properties", property);
        }
        private void WriteProperty(
            ODataProperty property,
            IEdmStructuredType owningType,
            bool isTopLevel,
            bool allowStreamProperty,
            DuplicatePropertyNamesChecker duplicatePropertyNamesChecker,
            ProjectedPropertiesAnnotation projectedProperties)
        {
            WriterValidationUtils.ValidatePropertyNotNull(property);

            string propertyName = property.Name;
            if (projectedProperties.ShouldSkipProperty(propertyName))
            {
                return;
            }

            WriterValidationUtils.ValidatePropertyName(propertyName, bypassValidation);
            duplicatePropertyNamesChecker.CheckForDuplicatePropertyNames(property);

            if (property.InstanceAnnotations.Any())
            {
                if (isTopLevel)
                {
                    this.InstanceAnnotationWriter.WriteInstanceAnnotations(property.InstanceAnnotations);
                }
                else
                {
                    this.InstanceAnnotationWriter.WriteInstanceAnnotations(property.InstanceAnnotations, propertyName);
                }
            }

            IEdmProperty edmProperty = WriterValidationUtils.ValidatePropertyDefined(
                propertyName,
                owningType,
                !this.bypassValidation);
            IEdmTypeReference propertyTypeReference = edmProperty == null ? null : edmProperty.Type;

            ODataValue value = property.ODataValue;

            ODataStreamReferenceValue streamReferenceValue = value as ODataStreamReferenceValue;
            if (streamReferenceValue != null)
            {
                if (!allowStreamProperty)
                {
                    throw new ODataException(ODataErrorStrings.ODataWriter_StreamPropertiesMustBePropertiesOfODataEntry(propertyName));
                }

                Debug.Assert(owningType == null || owningType.IsODataEntityTypeKind(), "The metadata should not allow named stream properties to be defined on a non-entity type.");
                Debug.Assert(!isTopLevel, "Stream properties are not allowed at the top level.");
                WriterValidationUtils.ValidateStreamReferenceProperty(property, edmProperty, this.WritingResponse, this.bypassValidation);
                this.WriteStreamReferenceProperty(propertyName, streamReferenceValue);
                return;
            }

            string wirePropertyName = isTopLevel ? JsonLightConstants.ODataValuePropertyName : propertyName;

            if (value is ODataNullValue || value == null)
            {
                WriterValidationUtils.ValidateNullPropertyValue(propertyTypeReference, propertyName, this.MessageWriterSettings.WriterBehavior, this.Model, this.bypassValidation);

                if (isTopLevel)
                {
                    // Write the special null marker for top-level null properties.
                    this.ODataAnnotationWriter.WriteInstanceAnnotationName(ODataAnnotationNames.ODataNull);
                    this.JsonWriter.WriteValue(true);
                }
                else
                {
                    this.JsonWriter.WriteName(wirePropertyName);
                    this.JsonLightValueSerializer.WriteNullValue();
                }

                return;
            }

            bool isOpenPropertyType = this.IsOpenProperty(property, owningType, edmProperty);
            if (isOpenPropertyType && this.JsonLightOutputContext.MessageWriterSettings.EnableFullValidation)
            {
                ValidationUtils.ValidateOpenPropertyValue(propertyName, value);
            }

            ODataComplexValue complexValue = value as ODataComplexValue;
            if (complexValue != null)
            {
                if (!isTopLevel)
                {
                    this.JsonWriter.WriteName(wirePropertyName);
                }

                this.JsonLightValueSerializer.WriteComplexValue(complexValue, propertyTypeReference, isTopLevel, isOpenPropertyType, this.CreateDuplicatePropertyNamesChecker());
                return;
            }

            IEdmTypeReference typeFromValue = TypeNameOracle.ResolveAndValidateTypeNameForValue(this.Model, propertyTypeReference, value, isOpenPropertyType);
            ODataEnumValue enumValue = value as ODataEnumValue;
            if (enumValue != null)
            {
                // This is a work around, needTypeOnWire always = true for client side: 
                // ClientEdmModel's reflection can't know a property is open type even if it is, so here 
                // make client side always write 'odata.type' for enum.
                bool needTypeOnWire = string.Equals(this.JsonLightOutputContext.Model.GetType().Name, "ClientEdmModel", StringComparison.OrdinalIgnoreCase);
                string typeNameToWrite = this.JsonLightOutputContext.TypeNameOracle.GetValueTypeNameForWriting(
                    enumValue, propertyTypeReference, typeFromValue, needTypeOnWire ? true /* leverage this flag to write 'odata.type' */ : isOpenPropertyType);
                this.WritePropertyTypeName(wirePropertyName, typeNameToWrite, isTopLevel);
                this.JsonWriter.WriteName(wirePropertyName);
                this.JsonLightValueSerializer.WriteEnumValue(enumValue, propertyTypeReference);
                return;
            }

            ODataCollectionValue collectionValue = value as ODataCollectionValue;
            if (collectionValue != null)
            {
                string collectionTypeNameToWrite = this.JsonLightOutputContext.TypeNameOracle.GetValueTypeNameForWriting(collectionValue, propertyTypeReference, typeFromValue, isOpenPropertyType);
                this.WritePropertyTypeName(wirePropertyName, collectionTypeNameToWrite, isTopLevel);
                this.JsonWriter.WriteName(wirePropertyName);

                // passing false for 'isTopLevel' because the outer wrapping object has already been written.
                this.JsonLightValueSerializer.WriteCollectionValue(collectionValue, propertyTypeReference, isTopLevel, false /*isInUri*/, isOpenPropertyType);
            }
            else
            {
                ODataPrimitiveValue primitiveValue = value as ODataPrimitiveValue;
                Debug.Assert(primitiveValue != null, "primitiveValue != null");

                string typeNameToWrite = this.JsonLightOutputContext.TypeNameOracle.GetValueTypeNameForWriting(primitiveValue, propertyTypeReference, typeFromValue, isOpenPropertyType);
                this.WritePropertyTypeName(wirePropertyName, typeNameToWrite, isTopLevel);

                this.JsonWriter.WriteName(wirePropertyName);
                this.JsonLightValueSerializer.WritePrimitiveValue(primitiveValue.Value, propertyTypeReference);
            }
        }
        /// <summary>
        /// Writes a single property in ATOM format.
        /// </summary>
        /// <param name="property">The property to write out.</param>
        /// <param name="owningType">The owning type for the <paramref name="property"/> or null if no metadata is available.</param>
        /// <param name="isTopLevel">true if writing a top-level property payload; otherwise false.</param>
        /// <param name="isWritingCollection">true if we are writing a top-level collection instead of an entry.</param>
        /// <param name="beforePropertyAction">Action which is called before the property is written, if it's going to be written.</param>
        /// <param name="duplicatePropertyNamesChecker">The checker instance for duplicate property names.</param>
        /// <param name="projectedProperties">Set of projected properties, or null if all properties should be written.</param>
        /// <returns>true if the property was actually written, false otherwise.</returns>
        private bool WriteProperty(
            ODataProperty property,
            IEdmStructuredType owningType,
            bool isTopLevel,
            bool isWritingCollection,
            Action beforePropertyAction,
            DuplicatePropertyNamesChecker duplicatePropertyNamesChecker,
            ProjectedPropertiesAnnotation projectedProperties)
        {
            WriterValidationUtils.ValidatePropertyNotNull(property);

            object value = property.Value;
            string propertyName = property.Name;
            //// TODO: If we implement type conversions the value needs to be converted here
            ////       since the next method call needs to know if the value is a string or not in some cases.

            ODataComplexValue complexValue = value as ODataComplexValue;
            ProjectedPropertiesAnnotation complexValueProjectedProperties = null;
            if (!ShouldWritePropertyInContent(projectedProperties, propertyName))
            {
                return false;
            }

            WriterValidationUtils.ValidatePropertyName(propertyName);
            duplicatePropertyNamesChecker.CheckForDuplicatePropertyNames(property);
            IEdmProperty edmProperty = WriterValidationUtils.ValidatePropertyDefined(propertyName, owningType);
            IEdmTypeReference propertyTypeReference = edmProperty == null ? null : edmProperty.Type;

            if (value is ODataStreamReferenceValue)
            {
                throw new ODataException(ODataErrorStrings.ODataWriter_StreamPropertiesMustBePropertiesOfODataEntry(propertyName));
            }

            // Null property value.
            if (value == null)
            {
                this.WriteNullPropertyValue(propertyTypeReference, propertyName, isTopLevel, isWritingCollection, beforePropertyAction);
                return true;
            }

            bool isOpenPropertyType = owningType != null && owningType.IsOpen && propertyTypeReference == null;
            if (isOpenPropertyType)
            {
                ValidationUtils.ValidateOpenPropertyValue(propertyName, value);
            }

            if (complexValue != null)
            {
                return this.WriteComplexValueProperty(
                    complexValue,
                    propertyName,
                    isTopLevel,
                    isWritingCollection,
                    beforePropertyAction,
                    propertyTypeReference,
                    isOpenPropertyType,
                    complexValueProjectedProperties);
            }

            ODataCollectionValue collectionValue = value as ODataCollectionValue;
            if (collectionValue != null)
            {
                this.WriteCollectionValueProperty(
                    collectionValue,
                    propertyName,
                    isTopLevel,
                    isWritingCollection,
                    beforePropertyAction,
                    propertyTypeReference,
                    isOpenPropertyType);

                return true;
            }

            // If the value isn't one of the value types tested for already, it must be a non-null primitive or enum type.
            this.WritePropertyStart(beforePropertyAction, property, isWritingCollection, isTopLevel);
            SerializationTypeNameAnnotation serializationTypeNameAnnotation = property.ODataValue.GetAnnotation<SerializationTypeNameAnnotation>();
            ODataEnumValue enumValue = value as ODataEnumValue;
            if (enumValue != null)
            {
                this.WriteEnumValue(enumValue, /*collectionValidator*/ null, propertyTypeReference, serializationTypeNameAnnotation);
            }
            else
            {
                this.WritePrimitiveValue(value, /*collectionValidator*/ null, propertyTypeReference, serializationTypeNameAnnotation);
            }

            this.WritePropertyEnd();
            return true;
        }
Пример #58
0
        /// <summary>
        /// Writes a single property in ATOM format.
        /// </summary>
        /// <param name="writer">The <see cref="XmlWriter"/> to write to.</param>
        /// <param name="metadata">The metadata provider to use or null if no metadata is available.</param>
        /// <param name="property">The property to write out.</param>
        /// <param name="owningType">The type owning the property (or null if no metadata is available).</param>
        /// <param name="version">The protocol version used for writing.</param>
        /// <param name="isTopLevel">True if writing a top-level property payload; otherwise false.</param>
        /// <param name="isWritingCollection">True if we are writing a collection instead of an entry.</param>
        /// <param name="epmValueCache">Cache of values used in EPM so that we avoid multiple enumerations of properties/items. (can be null)</param>
        /// <param name="epmParentSourcePathSegment">The EPM source path segment which points to the property which sub-property we're writing. (can be null)</param>
        internal static void WriteProperty(
            XmlWriter writer,
            DataServiceMetadataProviderWrapper metadata,
            ODataProperty property,
            ResourceType owningType,
            ODataVersion version, 
            bool isTopLevel,
            bool isWritingCollection,
            EpmValueCache epmValueCache,
            EpmSourcePathSegment epmParentSourcePathSegment)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(writer != null, "writer != null");

            ValidationUtils.ValidateProperty(property);
            ResourceProperty resourceProperty = ValidationUtils.ValidatePropertyDefined(property.Name, owningType);

            EpmSourcePathSegment epmSourcePathSegment = null;
            if (epmParentSourcePathSegment != null)
            {
                epmSourcePathSegment = epmParentSourcePathSegment.SubProperties.Where(subProperty => subProperty.PropertyName == property.Name).FirstOrDefault();
            }

            object value = property.Value;

            // TODO: If we implement validation or type conversions the value needs to be converted here
            //       since the next method call needs to know if the value is a string or not in some cases.

            // If EPM tells us to skip this property in content, then we're done here.
            if (!ShouldWritePropertyInContent(value, epmSourcePathSegment, version))
            {
                return;
            }

            // <d:propertyname>
            writer.WriteStartElement(
                isWritingCollection ? string.Empty : AtomConstants.ODataNamespacePrefix,
                property.Name,
                AtomConstants.ODataNamespace);

            if (isTopLevel)
            {
                WriteDefaultNamespaceAttributes(writer, DefaultNamespaceFlags.OData | DefaultNamespaceFlags.ODataMetadata);
            }

            // Null property value.
            if (value == null)
            {
                // verify that MultiValue properties are not null
                if (resourceProperty != null && resourceProperty.Kind == ResourcePropertyKind.MultiValue)
                {
                    throw new ODataException(Strings.ODataWriter_MultiValuePropertiesMustNotHaveNullValue(resourceProperty.Name));
                }

                ODataAtomWriterUtils.WriteNullAttribute(writer);
            }
            else
            {
                ODataComplexValue complexValue = value as ODataComplexValue;
                ResourceType resourcePropertyType = resourceProperty == null ? null : resourceProperty.ResourceType;
                bool isOpenPropertyType = owningType != null && owningType.IsOpenType && resourceProperty == null;

                // Complex properties are written recursively.
                if (complexValue != null)
                {
                    WriteComplexValue(writer, metadata, complexValue, resourcePropertyType, isOpenPropertyType, isWritingCollection, version, epmValueCache, epmSourcePathSegment);
                }
                else
                {
                    ODataMultiValue multiValue = value as ODataMultiValue;
                    if (multiValue != null)
                    {
                        ODataVersionChecker.CheckMultiValueProperties(version, property.Name);
                        WriteMultiValue(writer, metadata, multiValue, resourcePropertyType, isOpenPropertyType, isWritingCollection, version, epmValueCache, epmSourcePathSegment);
                    }
                    else
                    {
                        WritePrimitiveValue(writer, value, resourcePropertyType);
                    }
                }
            }

            // </d:propertyname>
            writer.WriteEndElement();
        }
        /// <summary>
        /// Writes a stream property to the ATOM payload
        /// </summary>
        /// <param name="streamProperty">The stream property to create the payload for.</param>
        /// <param name="owningType">The <see cref="IEdmEntityType"/> instance for which the stream property defined on.</param>
        /// <param name="duplicatePropertyNamesChecker">The checker instance for duplicate property names.</param>
        /// <param name="projectedProperties">Set of projected properties, or null if all properties should be written.</param>
        internal void WriteStreamProperty(
            ODataProperty streamProperty,
            IEdmEntityType owningType,
            DuplicatePropertyNamesChecker duplicatePropertyNamesChecker,
            ProjectedPropertiesAnnotation projectedProperties)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(streamProperty != null, "Stream property must not be null.");
            Debug.Assert(streamProperty.Value != null, "The media resource of the stream property must not be null.");

            WriterValidationUtils.ValidatePropertyNotNull(streamProperty);
            string propertyName = streamProperty.Name;
            if (projectedProperties.ShouldSkipProperty(propertyName))
            {
                return;
            }

            WriterValidationUtils.ValidateProperty(streamProperty);
            duplicatePropertyNamesChecker.CheckForDuplicatePropertyNames(streamProperty);
            IEdmProperty edmProperty = WriterValidationUtils.ValidatePropertyDefined(streamProperty.Name, owningType);
            WriterValidationUtils.ValidateStreamReferenceProperty(streamProperty, edmProperty, this.Version, this.WritingResponse);
            ODataStreamReferenceValue streamReferenceValue = (ODataStreamReferenceValue)streamProperty.Value;
            if (owningType != null && owningType.IsOpen && edmProperty == null)
            {
                ValidationUtils.ValidateOpenPropertyValue(streamProperty.Name, streamReferenceValue);
            }

            AtomStreamReferenceMetadata streamReferenceMetadata = streamReferenceValue.GetAnnotation<AtomStreamReferenceMetadata>();
            string contentType = streamReferenceValue.ContentType;
            string linkTitle = streamProperty.Name;

            Uri readLink = streamReferenceValue.ReadLink;
            if (readLink != null)
            {
                string readLinkRelation = AtomUtils.ComputeStreamPropertyRelation(streamProperty, false);

                AtomLinkMetadata readLinkMetadata = streamReferenceMetadata == null ? null : streamReferenceMetadata.SelfLink;
                AtomLinkMetadata mergedMetadata = ODataAtomWriterMetadataUtils.MergeLinkMetadata(readLinkMetadata, readLinkRelation, readLink, linkTitle, contentType);
                this.atomEntryMetadataSerializer.WriteAtomLink(mergedMetadata, null /* etag */);
            }

            Uri editLink = streamReferenceValue.EditLink;
            if (editLink != null)
            {
                string editLinkRelation = AtomUtils.ComputeStreamPropertyRelation(streamProperty, true);

                AtomLinkMetadata editLinkMetadata = streamReferenceMetadata == null ? null : streamReferenceMetadata.EditLink;
                AtomLinkMetadata mergedMetadata = ODataAtomWriterMetadataUtils.MergeLinkMetadata(editLinkMetadata, editLinkRelation, editLink, linkTitle, contentType);
                this.atomEntryMetadataSerializer.WriteAtomLink(mergedMetadata, streamReferenceValue.ETag);
            }
        }
 /// <summary>
 /// Writes an <see cref="ODataProperty"/> as message payload.
 /// </summary>
 /// <param name="property">The property to write.</param>
 private void WritePropertyImplementation(ODataProperty property)
 {
     ODataJsonLightPropertySerializer jsonLightPropertySerializer = new ODataJsonLightPropertySerializer(this, /*initContextUriBuilder*/ true);
     jsonLightPropertySerializer.WriteTopLevelProperty(property);
 }