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(); }
/// <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(); }
/// <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); }
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); }
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); }
/// <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); }
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 } } ; }
/// <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); } }
/// <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(); }
/// <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); } }
/// <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); }
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)); }
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(); }
/// <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)); }
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); }
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); }
/// <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)); }
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)); }
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); }
/// <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); }
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); } }
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); }
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; }
/// <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); }
/// <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>" ); }
/// <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); }
/// <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); }
/// <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; }
/// <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); }