public void WritingSingleComplexProppertyWithAllowedTypeAsPropertyTypeWithOrWithoutDerivedTypeConstraintWorks() { // Add a <Property Name="Location" Type="NS.Address" /> var locationProperty = this.edmCustomerType.AddStructuralProperty("Location", new EdmComplexTypeReference(this.edmAddressType, false)); ODataNestedResourceInfo nestedResourceInfo = new ODataNestedResourceInfo { Name = "Location", IsCollection = false }; Action <ODataMessageWriter> writePropertyAction = (messageWriter) => { ODataWriter writer = messageWriter.CreateODataResourceWriter(this.edmMe, this.edmCustomerType); // singleton writer.WriteStart(this.odataCustomerResource); writer.WriteStart(nestedResourceInfo); writer.WriteStart(this.odataUsAddressResource); // UsAddress writer.WriteEnd(); writer.WriteEnd(); writer.WriteEnd(); }; // Structural property doesn't have the derived type constraint. string actual = GetWriterOutput(this.edmModel, writePropertyAction); Assert.Contains("#Me\",\"Id\":7,\"Location\":{\"@odata.type\":\"#NS.UsAddress\",\"Street\":\"RedWay\",\"ZipCode\":98052}}", actual); // Structural property has the derived type constraint. SetDerivedTypeAnnotation(this.edmModel, locationProperty, "NS.UsAddress"); string actualWithDerivedTypeConstraint = GetWriterOutput(this.edmModel, writePropertyAction); Assert.Equal(actual, actualWithDerivedTypeConstraint); }
private void TestAndMeasure(string propertyType) { var entry = GenerateEntry(propertyType); var entitySet = Model.EntityContainer.FindEntitySet(propertyType); foreach (var iteration in Benchmark.Iterations) { // Reuse the same stream WriteStream.Seek(0, SeekOrigin.Begin); using (iteration.StartMeasurement()) { using (var messageWriter = ODataMessageHelper.CreateMessageWriter(WriteStream, Model, ODataMessageKind.Response, isFullValidation: true)) { ODataWriter writer = messageWriter.CreateODataResourceSetWriter(entitySet, entitySet.EntityType()); writer.WriteStart(new ODataResourceSet { Id = new Uri("http://www.odata.org/Perf.svc") }); for (int i = 0; i < NumberOfEntries; ++i) { writer.WriteStart(entry); writer.WriteEnd(); } writer.WriteEnd(); writer.Flush(); } } } }
public void WritingSingleComplexProppertyWithNotAllowedTypeWorksWithoutDerivedTypeConstraintButFailedWithDerivedTypeConstraint() { // Add a <Property Name="Location" Type="NS.Address" /> var locationProperty = this.edmCustomerType.AddStructuralProperty("Location", new EdmComplexTypeReference(this.edmAddressType, false)); ODataNestedResourceInfo nestedResourceInfo = new ODataNestedResourceInfo { Name = "Location", IsCollection = false }; Action <ODataMessageWriter> writePropertyAction = (messageWriter) => { ODataWriter writer = messageWriter.CreateODataResourceWriter(this.edmCustomers, this.edmCustomerType); // entityset writer.WriteStart(this.odataCustomerResource); writer.WriteStart(nestedResourceInfo); writer.WriteStart(this.odataCnAddressResource); // CnAddress writer.WriteEnd(); writer.WriteEnd(); writer.WriteEnd(); }; // Structural property doesn't have the derived type constraint. string actual = GetWriterOutput(this.edmModel, writePropertyAction); Assert.Contains("#Customers/$entity\",\"Id\":7,\"Location\":{\"@odata.type\":\"#NS.CnAddress\",\"Street\":\"ShaWay\",", actual); // Negative test case --Structural property has the derived type constraint. SetDerivedTypeAnnotation(this.edmModel, locationProperty, "NS.UsAddress"); Action test = () => GetWriterOutput(this.edmModel, writePropertyAction); var exception = Assert.Throws <ODataException>(test); Assert.Equal(Strings.WriterValidationUtils_ValueTypeNotAllowedInDerivedTypeConstraint("NS.CnAddress", "property", "Location"), exception.Message); }
public void WritingResourceWithSameTypeAsEntitySetTypeWithOrWithoutDerivedTypeConstraintWorks() { ODataResource anotherCustomerResource = new ODataResource { TypeName = "NS.Customer", Properties = new[] { new ODataProperty { Name = "Id", Value = 77 } } }; Action <ODataMessageWriter> writeCustomersAction = (messageWriter) => { ODataWriter writer = messageWriter.CreateODataResourceSetWriter(this.edmCustomers, this.edmCustomerType); // entityset writer.WriteStart(new ODataResourceSet()); writer.WriteStart(this.odataCustomerResource); writer.WriteEnd(); writer.WriteStart(anotherCustomerResource); writer.WriteEnd(); writer.WriteEnd(); }; // EntitySet doesn't have the derived type constraint. string customersActual = GetWriterOutput(this.edmModel, writeCustomersAction); Assert.Contains("/$metadata#Customers\",\"value\":[{\"Id\":7},{\"Id\":77}]}", customersActual); // EntitySet has the derived type constraint. SetDerivedTypeAnnotation(this.edmModel, this.edmCustomers, "NS.VipCustomer"); string customersActualWithDerivedTypeConstraint = GetWriterOutput(this.edmModel, writeCustomersAction); Assert.Equal(customersActual, customersActualWithDerivedTypeConstraint); }
public void WritingResourceForEntitySetWithoutDerivedTypeConstraintsWorksButWithConstraintFailed() { Action <ODataMessageWriter> writeCustomersAction = (messageWriter) => { ODataWriter writer = messageWriter.CreateODataResourceSetWriter(this.edmCustomers, this.edmCustomerType); // entityset writer.WriteStart(new ODataResourceSet()); writer.WriteStart(this.odataCustomerResource); writer.WriteEnd(); writer.WriteStart(this.odataNormalResource); writer.WriteEnd(); writer.WriteEnd(); }; // EntitySet doesn't have the derived type constraint. string normalCustomersActual = GetWriterOutput(this.edmModel, writeCustomersAction); Assert.Contains("/$metadata#Customers\",\"value\":[{\"Id\":7},{\"@odata.type\":\"#NS.NormalCustomer\",\"Id\":9,\"Email\":\"[email protected]\"}]}", normalCustomersActual); // Negative test case -- EntitySet has the derived type constraint. SetDerivedTypeAnnotation(this.edmModel, this.edmCustomers, "NS.VipCustomer"); Action test = () => GetWriterOutput(this.edmModel, writeCustomersAction); var exception = Assert.Throws <ODataException>(test); Assert.Equal(Strings.WriterValidationUtils_ValueTypeNotAllowedInDerivedTypeConstraint("NS.NormalCustomer", "navigation source", "Customers"), exception.Message); }
private void WriteDynamicTypeEntry(object graph, ODataWriter writer, IEdmTypeReference expectedType, ODataSerializerContext writeContext) { var navigationProperties = new Dictionary <IEdmTypeReference, object>(); var entityType = expectedType.Definition as EdmEntityType; var entry = new ODataEntry() { TypeName = expectedType.FullName(), Properties = CreateODataPropertiesFromDynamicType(entityType, graph, navigationProperties) }; entry.IsTransient = true; writer.WriteStart(entry); foreach (IEdmTypeReference type in navigationProperties.Keys) { var entityContext = new EntityInstanceContext(writeContext, expectedType.AsEntity(), graph); var navigationProperty = entityType.NavigationProperties().FirstOrDefault(p => p.Type.Equals(type)); var navigationLink = CreateNavigationLink(navigationProperty, entityContext); if (navigationLink != null) { writer.WriteStart(navigationLink); WriteDynamicTypeEntry(navigationProperties[type], writer, type, writeContext); writer.WriteEnd(); } } writer.WriteEnd(); }
public void WritingResourceWithBaseTypeWhileExpectedTypeIsSubTypeThrows() { // Arrange var model = GetGraphModel(); var groups = model.EntityContainer.FindEntitySet("groups"); var group = model.SchemaElements.OfType <IEdmEntityType>().FirstOrDefault(c => c.Name == "group"); ODataResource directoryObject = new ODataResource { TypeName = "microsoft.graph.directoryObject", Properties = new[] { new ODataProperty { Name = "id", Value = "abc" } } }; Action <ODataMessageWriter> writeAction = (messageWriter) => { ODataWriter writer = messageWriter.CreateODataResourceSetWriter(groups, group); // entityset writer.WriteStart(new ODataResourceSet()); writer.WriteStart(directoryObject); writer.WriteEnd(); writer.WriteEnd(); }; // Act & Assert Action test = () => GetWriterOutput(model, writeAction); var exception = Assert.Throws <ODataException>(test); Assert.Equal(Strings.ResourceSetWithoutExpectedTypeValidator_IncompatibleTypes("microsoft.graph.directoryObject", "microsoft.graph.group"), exception.Message); }
public void WritingResourceWithTypeNotInHeritanceTreeWithResourceSetTypeThrows() { // Arrange var model = GetGraphModel(); var directoryObjects = model.EntityContainer.FindEntitySet("directoryObjects"); var directoryObject = model.SchemaElements.OfType <IEdmEntityType>().FirstOrDefault(c => c.Name == "directoryObject"); ODataResource contact = new ODataResource { TypeName = "microsoft.graph.contact", Properties = new[] { new ODataProperty { Name = "id", Value = "abc" }, new ODataProperty { Name = "displayName", Value = "xyz" } } /*open type*/ }; Action <ODataMessageWriter> writeAction = (messageWriter) => { ODataWriter writer = messageWriter.CreateODataResourceSetWriter(directoryObjects, directoryObject); // entityset writer.WriteStart(new ODataResourceSet()); writer.WriteStart(contact); writer.WriteEnd(); writer.WriteEnd(); }; // Act & Assert Action test = () => GetWriterOutput(model, writeAction); var exception = Assert.Throws <ODataException>(test); Assert.Equal(Strings.ResourceSetWithoutExpectedTypeValidator_IncompatibleTypes("microsoft.graph.contact", "microsoft.graph.directoryObject"), exception.Message); }
public void WritingResourceWithTypeInHeritanceTreeWithResourceSetTypeSuccessed() { // Arrange var model = GetGraphModel(); var directoryObjects = model.EntityContainer.FindEntitySet("directoryObjects"); var directoryObject = model.SchemaElements.OfType <IEdmEntityType>().FirstOrDefault(c => c.Name == "directoryObject"); ODataResource group = new ODataResource { TypeName = "microsoft.graph.group", Properties = new[] { new ODataProperty { Name = "id", Value = "abc" }, new ODataProperty { Name = "displayName", Value = "xyz" } } }; Action <ODataMessageWriter> writeAction = (messageWriter) => { ODataWriter writer = messageWriter.CreateODataResourceSetWriter(directoryObjects, directoryObject); // entityset writer.WriteStart(new ODataResourceSet()); writer.WriteStart(group); writer.WriteEnd(); writer.WriteEnd(); }; // Act string actual = GetWriterOutput(model, writeAction); // Assert Assert.Equal("{\"@odata.context\":\"http://example.com/$metadata#directoryObjects\",\"value\":[{\"@odata.type\":\"#microsoft.graph.group\",\"id\":\"abc\",\"displayName\":\"xyz\"}]}", actual); }
public static void WriteResourceSet(IEdmModel model, ODataWriter odataWriter, object value) { Type valueType = value.GetType(); IsCollection(valueType, out Type elementType); IEdmStructuredType structruedType = model.FindDeclaredType(valueType.FullName) as IEdmStructuredType; ODataResourceSet resourceSet = new ODataResourceSet { TypeName = "Collection(" + elementType.FullName + ")" }; odataWriter.WriteStart(resourceSet); IEnumerable items = value as IEnumerable; foreach (object item in items) { if (item == null) { odataWriter.WriteStart(resource: null); odataWriter.WriteEnd(); } else { WriteResource(model, odataWriter, item); } } odataWriter.WriteEnd(); }
private void WriteEntry(ODataWriter odataWriter, int dataSizeKb) { var entry = new ODataResource { Id = new Uri("http://www.odata.org/Perf.svc/Item(1)"), EditLink = new Uri("Item(1)", UriKind.Relative), ReadLink = new Uri("Item(1)", UriKind.Relative), TypeName = "PerformanceServices.Edm.ExchangeAttachment.Item", Properties = new[] { new ODataProperty { Name = "HasAttachments", Value = false }, } }; var attachmentsP = new ODataNestedResourceInfo() { Name = "Attachments", IsCollection = true }; var attachmentsResourceSet = new ODataResourceSet() { TypeName = "Collection(PerformanceServices.Edm.ExchangeAttachment.Attachment)" }; var attachment = dataSizeKb == 0 ? null : new ODataResource() { TypeName = "PerformanceServices.Edm.ExchangeAttachment.Attachment", Properties = new[] { new ODataProperty { Name = "Name", Value = "attachment" }, new ODataProperty { Name = "IsInline", Value = false }, new ODataProperty { Name = "LastModifiedTime", Value = new DateTimeOffset(1987, 6, 5, 4, 3, 21, 0, new TimeSpan(0, 0, 3, 0)) }, new ODataProperty { Name = "Content", Value = new byte[dataSizeKb * 1024] }, } }; odataWriter.WriteStart(entry); odataWriter.WriteStart(attachmentsP); odataWriter.WriteStart(attachmentsResourceSet); if (attachment != null) { odataWriter.WriteStart(attachment); odataWriter.WriteEnd(); } odataWriter.WriteEnd(); odataWriter.WriteEnd(); odataWriter.WriteEnd(); }
private void WriteResourceSet(IEnumerable enumerable, IEdmTypeReference resourceSetType, ODataWriter writer, ODataSerializerContext writeContext) { Contract.Assert(writer != null); Contract.Assert(writeContext != null); Contract.Assert(enumerable != null); Contract.Assert(resourceSetType != null); IEdmStructuredTypeReference elementType = GetResourceType(resourceSetType); ODataEdmTypeSerializer resourceSerializer = SerializerProvider.GetEdmTypeSerializer(elementType); if (resourceSerializer == null) { throw new SerializationException( Error.Format(SRResources.TypeCannotBeSerialized, elementType.FullName())); } ODataResourceSet resourceSet = GetResourceSet(enumerable, resourceSetType, elementType, writeContext); // create the nextLinkGenerator for the current resourceSet and then set the nextpagelink to null to support JSON odata.streaming. Func <object, Uri> nextLinkGenerator = GetNextLinkGenerator(resourceSet, enumerable, writeContext); resourceSet.NextPageLink = null; writer.WriteStart(resourceSet); object lastResource = null; foreach (object item in enumerable) { lastResource = item; if (item == null || item is NullEdmComplexObject) { if (elementType.IsEntity()) { throw new SerializationException(SRResources.NullElementInCollection); } // for null complex element, it can be serialized as "null" in the collection. writer.WriteStart(resource: null); writer.WriteEnd(); } else { resourceSerializer.WriteObjectInline(item, elementType, writer, writeContext); } } // Subtle and surprising behavior: If the NextPageLink property is set before calling WriteStart(resourceSet), // the next page link will be written early in a manner not compatible with odata.streaming=true. Instead, if // the next page link is not set when calling WriteStart(resourceSet) but is instead set later on that resourceSet // object before calling WriteEnd(), the next page link will be written at the end, as required for // odata.streaming=true support. resourceSet.NextPageLink = nextLinkGenerator(lastResource); writer.WriteEnd(); }
private async Task SerializeBuffered(OeEntryFactory entryFactory, Db.OeEntityAsyncEnumerator asyncEnumerator, Stream stream) { var values = new List <Object>(); while (await asyncEnumerator.MoveNextAsync().ConfigureAwait(false)) { values.Add(asyncEnumerator.Current); } var resourceSet = new ODataResourceSet(); resourceSet.Count = values.Count; Writer.WriteStart(resourceSet); foreach (Object value in values) { int? dummy; ODataResource entry = CreateEntry(entryFactory, entryFactory.GetValue(value, out dummy)); Writer.WriteStart(entry); foreach (OeEntryFactory navigationLink in entryFactory.NavigationLinks) { WriteNavigationLink(value, navigationLink); } Writer.WriteEnd(); } Writer.WriteEnd(); }
public static void WriteODataFeed(IEdmModel model, Stream stream) { // Create a ODataEntry var entry = new ODataEntry() { Properties = new List <ODataProperty>() { new ODataProperty { Name = "ProductId", Value = 100 }, new ODataProperty { Name = "Name", Value = "The World" }, new ODataProperty { Name = "SkinColor", Value = new ODataEnumValue("Green", DefaultNamespace + ".Color") }, new ODataProperty { Name = "UserAccess", Value = new ODataEnumValue("ReadWrite, Execute", DefaultNamespace + ".AccessLevel") } } }; ODataMessageWriterSettings writerSettings = new ODataMessageWriterSettings(); writerSettings.ODataUri = new ODataUri() { ServiceRoot = ServiceRootUri }; writerSettings.PayloadBaseUri = ServiceRootUri; writerSettings.SetContentType("application/json;odata.metadata=full", Encoding.UTF8.WebName); writerSettings.AutoComputePayloadMetadataInJson = true; var responseMessage = new ODataResponseMessage(stream); using (var messageWriter = new ODataMessageWriter(responseMessage, writerSettings, model)) { IEdmEntitySet entitySet = model.FindDeclaredEntitySet("Products"); ODataWriter feedWriter = messageWriter.CreateODataFeedWriter(entitySet); var feed = new ODataFeed { Id = new Uri(ServiceRootUri, "Products") }; feedWriter.WriteStart(feed); feedWriter.WriteStart(entry); feedWriter.WriteEnd(); feedWriter.WriteEnd(); feedWriter.Flush(); } }
private void WriteNavigationLinks(EntityInstanceContext context, ODataWriter writer, ODataSerializerWriteContext writeContext) { foreach (IEdmNavigationProperty navProperty in _edmEntityTypeReference.NavigationProperties()) { IEdmTypeReference propertyType = navProperty.Type; object propertyValue = context.EntityInstance.GetType().GetProperty(navProperty.Name).GetValue(context.EntityInstance, index: null); if (writeContext.EntitySet != null) { IEdmEntitySet currentEntitySet = writeContext.EntitySet.FindNavigationTarget(navProperty); IEntitySetLinkBuilder linkBuilder = SerializerProvider.EdmModel.GetEntitySetLinkBuilder(writeContext.EntitySet); ODataNavigationLink navigationLink = new ODataNavigationLink { IsCollection = propertyType.IsCollection(), Name = navProperty.Name, Url = linkBuilder.BuildNavigationLink(context, navProperty) }; ODataQueryProjectionNode expandNode = null; if (writeContext.CurrentProjectionNode != null) { expandNode = writeContext.CurrentProjectionNode.Expands.FirstOrDefault(p => p.Name == navProperty.Name); } if (expandNode != null && propertyValue != null) { writer.WriteStart(navigationLink); ODataSerializer serializer = SerializerProvider.GetEdmTypeSerializer(propertyType); if (serializer == null) { throw Error.NotSupported(SRResources.TypeCannotBeSerialized, navProperty.Type.FullName(), typeof(ODataMediaTypeFormatter).Name); } ODataSerializerWriteContext childWriteContext = new ODataSerializerWriteContext(writeContext.ResponseContext); childWriteContext.UrlHelper = writeContext.UrlHelper; childWriteContext.EntitySet = currentEntitySet; childWriteContext.RootProjectionNode = writeContext.RootProjectionNode; childWriteContext.CurrentProjectionNode = expandNode; serializer.WriteObjectInline(propertyValue, writer, childWriteContext); writer.WriteEnd(); } else if (!writeContext.IsRequest) { // delayed links cannot be written on requests writer.WriteStart(navigationLink); writer.WriteEnd(); } } } }
private void WriteNavigationProperty(ODataWriter writer, Object value, PropertyInfo navigationProperty) { Object navigationValue = navigationProperty.GetValue(value); if (!_stack.Add(navigationValue)) { return; } bool isCollection = OeExpressionHelper.GetCollectionItemType(navigationProperty.PropertyType) != null; var resourceInfo = new ODataNestedResourceInfo() { IsCollection = isCollection, Name = navigationProperty.Name }; writer.WriteStart(resourceInfo); if (navigationValue == null) { if (isCollection) { writer.WriteStart(new ODataResourceSet()); } else { writer.WriteStart((ODataResource)null); } writer.WriteEnd(); } else { var entityPropertiesInfo = default(EntityPropertiesInfo); if (isCollection) { writer.WriteStart(new ODataResourceSet()); foreach (Object entity in (IEnumerable)navigationValue) { WriteEntry(writer, entity, ref entityPropertiesInfo); } writer.WriteEnd(); } else { WriteEntry(writer, navigationValue, ref entityPropertiesInfo); } } writer.WriteEnd(); _stack.Remove(navigationValue); }
public async Task SerializeAsync(OeEntryFactory entryFactory, Db.OeAsyncEnumerator asyncEnumerator, OeQueryContext queryContext) { var resourceSet = new ODataResourceSet() { Count = asyncEnumerator.Count }; _writer.WriteStart(resourceSet); Object buffer = null; int count = 0; var dbEnumerator = entryFactory.IsTuple ? (Db.IOeDbEnumerator) new Db.OeDbEnumerator(asyncEnumerator, entryFactory) : new Db.OeEntityDbEnumerator(asyncEnumerator, entryFactory); while (await dbEnumerator.MoveNextAsync().ConfigureAwait(false)) { Object value = dbEnumerator.Current; await WriteEntry(dbEnumerator, value, _queryContext.NavigationNextLink).ConfigureAwait(false); count++; buffer = dbEnumerator.ClearBuffer(); } if (queryContext.PageSize > 0 && count > 0 && (asyncEnumerator.Count ?? Int32.MaxValue) > count) { resourceSet.NextPageLink = BuildNextPageLink(queryContext, buffer); } _writer.WriteEnd(); }
/// <summary> /// Writes a ReferenceLinks /// </summary> /// <param name="writer">The ODataWriter that will write the ReferenceLinks.</param> public static void WriteReferenceLinks(ODataWriter writer, IEnumerable element, IEdmNavigationSource entitySource, ODataVersion targetVersion, ODataNavigationLink navigationLink) { IEnumerable <ODataEntry> links = ODataObjectModelConverter.ConvertToODataEntityReferenceLinks(element, entitySource, targetVersion); var feed = new ODataFeed { }; writer.WriteStart(feed); foreach (var entry in links) { entry.InstanceAnnotations.Add(new ODataInstanceAnnotation("Link.AnnotationByFeed", new ODataPrimitiveValue(true))); writer.WriteStart(entry); writer.WriteEnd(); } writer.WriteEnd(); }
/// <summary> /// Serializes the open complex type as an <see cref="ODataUntypedValue"/>. /// </summary> /// <param name="graph"></param> /// <param name="expectedType"></param> /// <param name="writer"></param> /// <param name="writeContext"></param> public override void WriteObjectInline( object graph, IEdmTypeReference expectedType, ODataWriter writer, ODataSerializerContext writeContext) { // This cast is safe because the type is checked before using this serializer. var mongoData = (MongoData)graph; var properties = new List <ODataProperty>(); foreach (var item in mongoData.Document) { properties.Add(new ODataProperty { Name = item.Key, Value = new ODataUntypedValue { RawValue = JsonConvert.SerializeObject(item.Value), }, }); } writer.WriteStart(new ODataResource { TypeName = expectedType.FullName(), Properties = properties, }); writer.WriteEnd(); }
private async Task SerializeAsync(ODataWriter writer) { var resourceSet = new ODataResourceSet() { Count = Count }; writer.WriteStart(resourceSet); int count = 0; T entity = default; EntityPropertiesInfo entityPropertiesInfo = default; while (await _entities.MoveNext()) { entity = _entities.Current; _stack.Add(entity); WriteEntry(writer, entity, ref entityPropertiesInfo); _stack.Remove(entity); count++; } if (PageSize > 0 && count > 0 && (Count ?? Int32.MaxValue) > count) { resourceSet.NextPageLink = BuildNextPageLink(OeSkipTokenParser.GetSkipToken(_edmModel, GetKeys(entity))); } writer.WriteEnd(); }
public void WritingEdmPrimitiveProppertyWithNotAllowedTypeWorksWithoutDerivedTypeConstraintButFailedWithDerivedTypeConstraint() { // Add a <Property Name="Data" Type="Edm.PrimitiveType" /> var locationProperty = this.edmCustomerType.AddStructuralProperty("Data", EdmCoreModel.Instance.GetPrimitiveType(false)); ODataResource customer = new ODataResource { TypeName = "NS.Customer", Properties = new[] { new ODataProperty { Name = "Id", Value = 7 }, new ODataProperty { Name = "Data", Value = 8.9 } } }; Action <ODataMessageWriter> writeAction = (messageWriter) => { ODataWriter writer = messageWriter.CreateODataResourceWriter(this.edmCustomers, this.edmCustomerType); // entityset writer.WriteStart(customer); writer.WriteEnd(); }; // EdmPrimitive property doesn't have the derived type constraint. string actual = GetWriterOutput(this.edmModel, writeAction); Assert.Contains("#Customers/$entity\",\"Id\":7,\"[email protected]\":\"#Double\",\"Data\":8.9}", actual); // Negative test case --EdmPrimitive property has the derived type constraint. SetDerivedTypeAnnotation(this.edmModel, locationProperty, "Edm.Boolean", "Edm.Int32"); Action test = () => GetWriterOutput(this.edmModel, writeAction); var exception = Assert.Throws <ODataException>(test); Assert.Equal(Strings.WriterValidationUtils_ValueTypeNotAllowedInDerivedTypeConstraint("Edm.Double", "property", "Data"), exception.Message); }
private void WriteEntity(Stream stream, OeEntityItem entityItem) { var settings = new ODataMessageWriterSettings() { BaseUri = _baseUri, Version = ODataVersion.V4, ODataUri = new ODataUri() { ServiceRoot = _baseUri }, EnableMessageStreamDisposal = false }; IODataResponseMessage responseMessage = new OeInMemoryMessage(stream, null); using (ODataMessageWriter messageWriter = new ODataMessageWriter(responseMessage, settings, _model)) { ODataUtils.SetHeadersForPayload(messageWriter, ODataPayloadKind.Resource); ODataWriter writer = messageWriter.CreateODataResourceWriter(entityItem.EntitySet, entityItem.EntityType); entityItem.RefreshEntry(); writer.WriteStart(entityItem.Entry); writer.WriteEnd(); } }
/// <summary> /// Writes an OData entry. /// </summary> /// <param name="writer">The ODataWriter that will write the entry.</param> /// <param name="element">The item from the data store to write.</param> /// <param name="navigationSource">The navigation source in the model that the entry belongs to.</param> /// <param name="model">The data store model.</param> /// <param name="targetVersion">The OData version this segment is targeting.</param> /// <param name="selectExpandClause">The SelectExpandClause.</param> public static void WriteEntry(ODataWriter writer, object element, IEdmNavigationSource entitySource, ODataVersion targetVersion, SelectExpandClause selectExpandClause, Dictionary <string, string> incomingHeaders = null) { var entry = ODataObjectModelConverter.ConvertToODataEntry(element, entitySource, targetVersion); entry.ETag = Utility.GetETagValue(element); if (selectExpandClause != null && selectExpandClause.SelectedItems.OfType <PathSelectItem>().Any()) { ExpandSelectItemHandler selectItemHandler = new ExpandSelectItemHandler(entry); foreach (var item in selectExpandClause.SelectedItems.OfType <PathSelectItem>()) { item.HandleWith(selectItemHandler); } entry = selectItemHandler.ProjectedEntry; } CustomizeEntry(incomingHeaders, entry); writer.WriteStart(entry); // gets all of the expandedItems, including ExpandedRefernceSelectItem and ExpandedNavigationItem var expandedItems = selectExpandClause == null ? null : selectExpandClause.SelectedItems.OfType <ExpandedReferenceSelectItem>(); WriteNavigationLinks(writer, element, entry.ReadLink, entitySource, targetVersion, expandedItems); writer.WriteEnd(); }
private string WriteAndVerifyCarEntry(StreamResponseMessage responseMessage, ODataWriter odataWriter, bool hasModel, string mimeType) { var carEntry = WritePayloadHelper.CreateCarEntry(hasModel); odataWriter.WriteStart(carEntry); // Finish writing the entry. odataWriter.WriteEnd(); // Some very basic verification for the payload. bool verifyEntryCalled = false; Action <ODataEntry> verifyEntry = (entry) => { Assert.AreEqual(4, entry.Properties.Count(), "entry.Properties.Count"); Assert.IsNotNull(entry.MediaResource, "entry.MediaResource"); Assert.IsTrue(entry.EditLink.AbsoluteUri.Contains("Car(11)"), "entry.EditLink"); Assert.IsTrue(entry.ReadLink == null || entry.ReadLink.AbsoluteUri.Contains("Car(11)"), "entry.ReadLink"); Assert.AreEqual(1, entry.InstanceAnnotations.Count, "entry.InstanceAnnotations.Count"); verifyEntryCalled = true; }; Stream stream = responseMessage.GetStream(); if (!mimeType.Contains(MimeTypes.ODataParameterNoMetadata)) { stream.Seek(0, SeekOrigin.Begin); WritePayloadHelper.ReadAndVerifyFeedEntryMessage(false, responseMessage, WritePayloadHelper.CarSet, WritePayloadHelper.CarType, null, verifyEntry, null); Assert.IsTrue(verifyEntryCalled, "Verification action not called."); } return(WritePayloadHelper.ReadStreamContent(stream)); }
public override void WriteObjectInline( object graph, IEdmTypeReference expectedType, ODataWriter writer, ODataSerializerContext writeContext) { // This cast is safe because the type is checked before using this serializer. var dictionary = (IDictionary <string, object>)graph; var properties = new List <ODataProperty>(); foreach (var(key, value) in dictionary) { properties.Add(new ODataProperty { Name = key, Value = new ODataUntypedValue { RawValue = JsonConvert.SerializeObject(value), }, }); } writer.WriteStart(new ODataResource { TypeName = "Edm.Untyped", Properties = properties, }); writer.WriteEnd(); }
private async Task SerializeAsync(ODataWriter writer, OeMetadataLevel metadataLevel) { ClrPropertiesInfo clrPropertiesInfo = GetClrPropertiesInfo(_edmModel, _odataUri.SelectAndExpand, metadataLevel, typeof(T), null); var resourceSet = new ODataResourceSet() { Count = Count }; writer.WriteStart(resourceSet); int count = 0; T entity = default; while (await _entities.MoveNext()) { entity = _entities.Current; _stack.Add(entity); WriteEntry(writer, entity, clrPropertiesInfo); _stack.Remove(entity); count++; } if (PageSize > 0 && count > 0 && (Count ?? Int32.MaxValue) > count) { resourceSet.NextPageLink = BuildNextPageLink(OeSkipTokenParser.GetSkipToken(_edmModel, GetKeys(entity))); } writer.WriteEnd(); }
private string GetWriterOutputForContentTypeAndKnobValue(ODataEntry entry, EdmModel model, IEdmEntitySetBase entitySet, EdmEntityType entityType) { MemoryStream outputStream = new MemoryStream(); IODataResponseMessage message = new InMemoryMessage() { Stream = outputStream }; message.SetHeader("Content-Type", "application/json;odata.metadata=full"); ODataMessageWriterSettings settings = new ODataMessageWriterSettings() { AutoComputePayloadMetadataInJson = true, }; settings.SetServiceDocumentUri(new Uri("http://example.com")); string output; using (var messageWriter = new ODataMessageWriter(message, settings, model)) { ODataWriter writer = messageWriter.CreateODataEntryWriter(entitySet, entityType); writer.WriteStart(entry); writer.WriteEnd(); outputStream.Seek(0, SeekOrigin.Begin); output = new StreamReader(outputStream).ReadToEnd(); } return(output); }
internal void WriteNavigationLink(EntityDescriptor entityDescriptor, IEnumerable <LinkDescriptor> relatedLinks, ODataWriter odataWriter) { ClientTypeAnnotation clientTypeAnnotation = null; foreach (LinkDescriptor descriptor in relatedLinks) { descriptor.ContentGeneratedForSave = true; if (clientTypeAnnotation == null) { ClientEdmModel model = ClientEdmModel.GetModel(this.requestInfo.MaxProtocolVersion); clientTypeAnnotation = model.GetClientTypeAnnotation(model.GetOrCreateEdmType(entityDescriptor.Entity.GetType())); } ODataNavigationLink navigationLink = new ODataNavigationLink { Url = this.requestInfo.EntityTracker.GetEntityDescriptor(descriptor.Target).GetLatestEditLink(), IsCollection = new bool?(clientTypeAnnotation.GetProperty(descriptor.SourceProperty, false).IsEntityCollection), Name = descriptor.SourceProperty }; odataWriter.WriteStart(navigationLink); ODataEntityReferenceLink entityReferenceLink = new ODataEntityReferenceLink { Url = navigationLink.Url }; odataWriter.WriteEntityReferenceLink(entityReferenceLink); odataWriter.WriteEnd(); } }
private void WriteNavigationLink(ODataWriter writer, ODataNestedResourceInfo link) { writer.WriteStart(link); var expanded = link.GetAnnotation <ODataNavigationLinkExpandedItemObjectModelAnnotation>(); if (expanded != null) { var feed = expanded.ExpandedItem as ODataResourceSet; if (feed != null) { this.WriteFeed(writer, feed); } else { ODataResource entry = expanded.ExpandedItem as ODataResource; if (entry != null || expanded.ExpandedItem == null) { this.WriteEntry(writer, entry); } else { ExceptionUtilities.Assert(expanded.ExpandedItem is ODataEntityReferenceLink, "Content of a nav. link can only be a feed, entry or entity reference link."); writer.WriteEntityReferenceLink((ODataEntityReferenceLink)expanded.ExpandedItem); } } } writer.WriteEnd(); }
/// <summary> /// Writes the given deltaDeletedEntry specified by the parameter graph as a part of an existing OData message using the given /// messageWriter and the writeContext. /// </summary> /// <param name="graph">The object to be written.</param> /// <param name="writer">The <see cref="ODataDeltaWriter" /> to be used for writing.</param> /// <param name="writeContext">The <see cref="ODataSerializerContext"/>.</param> public virtual void WriteDeltaDeletedEntry(object graph, ODataWriter writer, ODataSerializerContext writeContext) { EdmDeltaDeletedEntityObject edmDeltaDeletedEntity = graph as EdmDeltaDeletedEntityObject; if (edmDeltaDeletedEntity == null) { throw new SerializationException(Error.Format(SRResources.CannotWriteType, GetType().Name, graph.GetType().FullName)); } Uri id = StringToUri(edmDeltaDeletedEntity.Id); ODataDeletedResource deletedResource = new ODataDeletedResource(id, edmDeltaDeletedEntity.Reason); if (edmDeltaDeletedEntity.NavigationSource != null) { ODataResourceSerializationInfo serializationInfo = new ODataResourceSerializationInfo { NavigationSourceName = edmDeltaDeletedEntity.NavigationSource.Name }; deletedResource.SetSerializationInfo(serializationInfo); } if (deletedResource != null) { writer.WriteStart(deletedResource); writer.WriteEnd(); } }
private void WriteEntry(ODataWriter writer, ODataItem[] itemsToWrite, ref int currentIdx) { if (currentIdx < itemsToWrite.Length) { ODataEntry entry = (ODataEntry)itemsToWrite[currentIdx++]; writer.WriteStart(entry); while (currentIdx < itemsToWrite.Length) { if (itemsToWrite[currentIdx] is ODataNavigationLink) { this.WriteLink(writer, itemsToWrite, ref currentIdx); } else if (itemsToWrite[currentIdx] is ODataNavigationLinkEnd) { currentIdx++; writer.WriteEnd(); return; } else { break; } } writer.WriteEnd(); } }
private void WriteLink(ODataWriter writer, ODataItem[] itemsToWrite, ref int currentIdx) { if (currentIdx < itemsToWrite.Length) { ODataNavigationLink link = (ODataNavigationLink)itemsToWrite[currentIdx++]; writer.WriteStart(link); if (currentIdx < itemsToWrite.Length) { if (itemsToWrite[currentIdx] is ODataEntry) { this.WriteEntry(writer, itemsToWrite, ref currentIdx); } else if (itemsToWrite[currentIdx] is ODataFeed) { this.WriteFeed(writer, itemsToWrite, ref currentIdx); } } writer.WriteEnd(); } }
private void WriteFeed(ODataWriter writer, ODataItem[] itemsToWrite, ref int currentIdx) { if (currentIdx < itemsToWrite.Length) { ODataFeed feed = (ODataFeed)itemsToWrite[currentIdx++]; writer.WriteStart(feed); while (currentIdx < itemsToWrite.Length && itemsToWrite[currentIdx] is ODataEntry) { this.WriteEntry(writer, itemsToWrite, ref currentIdx); } writer.WriteEnd(); } }