/// <summary> /// Start writing a delta resource. /// </summary> /// <param name="deltaResource">The delta resource to write.</param> public override void WriteStart(ODataResource deltaResource) { this.resourceWriter.WriteStart(deltaResource); }
protected override void EndResource(ODataResource entry) { throw new NotImplementedException(); }
protected override Task EndResourceAsync(ODataResource resource) { throw new NotImplementedException(); }
/// <summary> /// Initializes a new instance of <see cref="ODataResourceWrapper"/>. /// </summary> /// <param name="item">The wrapped item.</param> public ODataResourceWrapper(ODataResource item) : base(item) { NestedResourceInfos = new List <ODataNestedResourceInfoWrapper>(); }
private byte[] ServiceReadReferenceUriBatchRequestAndWriteResponse(byte[] requestPayload) { IODataRequestMessage requestMessage = new InMemoryMessage() { Stream = new MemoryStream(requestPayload) }; requestMessage.SetHeader("Content-Type", batchContentTypeApplicationJson); ODataMessageReaderSettings settings = new ODataMessageReaderSettings(); settings.BaseUri = new Uri(serviceDocumentUri); byte[] responseBytes = null; using (ODataMessageReader messageReader = new ODataMessageReader(requestMessage, settings, this.userModel)) { MemoryStream responseStream = new MemoryStream(); IODataResponseMessage responseMessage = new InMemoryMessage { Stream = responseStream }; // Client is expected to receive the response message in the same format as that is used in the request sent. responseMessage.SetHeader("Content-Type", batchContentTypeApplicationJson); using (ODataMessageWriter messageWriter = new ODataMessageWriter(responseMessage)) { ODataBatchWriter batchWriter = messageWriter.CreateODataBatchWriter(); batchWriter.WriteStartBatch(); ODataBatchReader batchReader = messageReader.CreateODataBatchReader(); while (batchReader.Read()) { switch (batchReader.State) { case ODataBatchReaderState.Operation: // Encountered an operation (either top-level or in a change set) ODataBatchOperationRequestMessage operationMessage = batchReader.CreateOperationRequestMessage(); ODataBatchOperationResponseMessage response = batchWriter.CreateOperationResponseMessage(operationMessage.ContentId); if (operationMessage.Method == "PUT") { using (ODataMessageReader operationMessageReader = new ODataMessageReader( operationMessage, new ODataMessageReaderSettings(), this.userModel)) { ODataReader reader = operationMessageReader.CreateODataResourceReader(); Assert.NotNull(reader); } response.StatusCode = 201; response.SetHeader("Content-Type", "application/json;odata.metadata=none"); } else if (operationMessage.Method == "PATCH") { using (ODataMessageReader operationMessageReader = new ODataMessageReader( operationMessage, new ODataMessageReaderSettings(), this.userModel)) { ODataReader reader = operationMessageReader.CreateODataResourceReader(); Assert.NotNull(reader); } response.StatusCode = 204; } else if (operationMessage.Method == "GET") { response.StatusCode = 200; response.SetHeader("Content-Type", "application/json;"); ODataMessageWriterSettings writerSettings = new ODataMessageWriterSettings(); writerSettings.ODataUri.ServiceRoot = new Uri(serviceDocumentUri); using ( ODataMessageWriter operationMessageWriter = new ODataMessageWriter(response, writerSettings, this.userModel)) { ODataWriter entryWriter = operationMessageWriter.CreateODataResourceWriter(this.singleton, this.webType); ODataResource entry = new ODataResource() { TypeName = "NS.Web", Properties = new[] { new ODataProperty() { Name = "WebId", Value = -1 }, new ODataProperty() { Name = "Name", Value = aVeryLongString } } }; entryWriter.WriteStart(entry); entryWriter.WriteEnd(); } } break; case ODataBatchReaderState.ChangesetStart: // Set the group Id on the writer side to correlate with request. string atomicGroupId = batchReader.CurrentGroupId; batchWriter.WriteStartChangeset(atomicGroupId); break; case ODataBatchReaderState.ChangesetEnd: batchWriter.WriteEndChangeset(); break; } } batchWriter.WriteEndBatch(); responseStream.Position = 0; responseBytes = responseStream.ToArray(); } return(responseBytes); } }
/// <summary> /// Creates the <see cref="ODataResource"/> to be written while writing this resource. /// </summary> /// <param name="selectExpandNode">The <see cref="SelectExpandNode"/> describing the response graph.</param> /// <param name="resourceContext">The context for the resource instance being written.</param> /// <returns>The created <see cref="ODataResource"/>.</returns> public virtual ODataResource CreateResource(SelectExpandNode selectExpandNode, ResourceContext resourceContext) { if (selectExpandNode == null) { throw Error.ArgumentNull("selectExpandNode"); } if (resourceContext == null) { throw Error.ArgumentNull("resourceContext"); } string typeName = resourceContext.StructuredType.FullTypeName(); ODataResource resource = new ODataResource { TypeName = typeName, Properties = CreateStructuralPropertyBag(selectExpandNode.SelectedStructuralProperties, resourceContext), }; // Try to add the dynamic properties if the structural type is open. AppendDynamicProperties(resource, selectExpandNode, resourceContext); IEnumerable <ODataAction> actions = CreateODataActions(selectExpandNode.SelectedActions, resourceContext); foreach (ODataAction action in actions) { resource.AddAction(action); } IEnumerable <ODataFunction> functions = CreateODataFunctions(selectExpandNode.SelectedFunctions, resourceContext); foreach (ODataFunction function in functions) { resource.AddFunction(function); } IEdmStructuredType pathType = GetODataPathType(resourceContext.SerializerContext); if (resourceContext.StructuredType.TypeKind == EdmTypeKind.Complex) { AddTypeNameAnnotationAsNeededForComplex(resource, resourceContext.SerializerContext.MetadataLevel); } else { AddTypeNameAnnotationAsNeeded(resource, pathType, resourceContext.SerializerContext.MetadataLevel); } if (resourceContext.StructuredType.TypeKind == EdmTypeKind.Entity && resourceContext.NavigationSource != null) { if (!(resourceContext.NavigationSource is IEdmContainedEntitySet)) { IEdmModel model = resourceContext.SerializerContext.Model; NavigationSourceLinkBuilderAnnotation linkBuilder = model.GetNavigationSourceLinkBuilder(resourceContext.NavigationSource); EntitySelfLinks selfLinks = linkBuilder.BuildEntitySelfLinks(resourceContext, resourceContext.SerializerContext.MetadataLevel); if (selfLinks.IdLink != null) { resource.Id = selfLinks.IdLink; } if (selfLinks.ReadLink != null) { resource.ReadLink = selfLinks.ReadLink; } if (selfLinks.EditLink != null) { resource.EditLink = selfLinks.EditLink; } } string etag = CreateETag(resourceContext); if (etag != null) { resource.ETag = etag; } } return(resource); }
/// <summary> /// Gets a resource metadata builder for the given resource. /// </summary> /// <param name="resourceState">Resource state to use as reference for information needed by the builder.</param> /// <param name="useKeyAsSegment">true if keys should go in separate segments in auto-generated URIs, false if they should go in parentheses.</param> /// <returns>A resource metadata builder.</returns> public ODataResourceMetadataBuilder GetResourceMetadataBuilderForReader(IODataJsonLightReaderResourceState resourceState, bool useKeyAsSegment) { Debug.Assert(resourceState != null, "resource != null"); // Only apply the conventional template builder on response. On a request we would only report what's on the wire. if (resourceState.MetadataBuilder == null) { ODataResource resource = resourceState.Resource; if (this.isResponse) { ODataTypeAnnotation typeAnnotation = resource.TypeAnnotation; IEdmStructuredType structuredType = null; if (typeAnnotation != null) { if (typeAnnotation.Type != null) { // First try ODataTypeAnnotation.Type (for perf improvement) structuredType = typeAnnotation.Type as IEdmStructuredType; } else if (typeAnnotation.TypeName != null) { // Then try ODataTypeAnnotation.TypeName structuredType = this.model.FindType(typeAnnotation.TypeName) as IEdmStructuredType; } } if (structuredType == null) { // No type name read from the payload. Use resource type from model. structuredType = resourceState.ResourceType; } IEdmNavigationSource navigationSource = resourceState.NavigationSource; IEdmEntityType navigationSourceElementType = this.edmTypeResolver.GetElementType(navigationSource); IODataResourceTypeContext typeContext = ODataResourceTypeContext.Create( /*serializationInfo*/ null, navigationSource, navigationSourceElementType, resourceState.ResourceTypeFromMetadata ?? resourceState.ResourceType, /*throwIfMissingTypeInfo*/ true); IODataResourceMetadataContext resourceMetadataContext = ODataResourceMetadataContext.Create(resource, typeContext, /*serializationInfo*/ null, structuredType, this, resourceState.SelectedProperties); ODataConventionalUriBuilder uriBuilder = new ODataConventionalUriBuilder(this.ServiceBaseUri, useKeyAsSegment ? ODataUrlKeyDelimiter.Slash : ODataUrlKeyDelimiter.Parentheses); if (structuredType.IsODataEntityTypeKind()) { resourceState.MetadataBuilder = new ODataConventionalEntityMetadataBuilder(resourceMetadataContext, this, uriBuilder); } else { resourceState.MetadataBuilder = new ODataConventionalResourceMetadataBuilder(resourceMetadataContext, this, uriBuilder); } } else { resourceState.MetadataBuilder = new NoOpResourceMetadataBuilder(resource); } } return(resourceState.MetadataBuilder); }
public void AssociationLinkOnNavigationLinkTest() { EdmModel model = new EdmModel(); var container = new EdmEntityContainer("TestModel", "Default"); model.AddElement(container); var edmEntityTypeOrderType = new EdmEntityType("TestModel", "OrderType"); model.AddElement(edmEntityTypeOrderType); var edmEntityTypeCustomerType = new EdmEntityType("TestModel", "CustomerType"); var edmNavigationPropertyAssociationLinkOne = edmEntityTypeCustomerType.AddUnidirectionalNavigation( new EdmNavigationPropertyInfo { Name = "NavProp1", Target = edmEntityTypeOrderType, TargetMultiplicity = EdmMultiplicity.One }); var edmNavigationPropertyAssociationLinkTwo = edmEntityTypeCustomerType.AddUnidirectionalNavigation( new EdmNavigationPropertyInfo { Name = "NavProp2", Target = edmEntityTypeOrderType, TargetMultiplicity = EdmMultiplicity.Many }); model.AddElement(edmEntityTypeCustomerType); var customerSet = container.AddEntitySet("Customers", edmEntityTypeCustomerType); var orderSet = container.AddEntitySet("Orders", edmEntityTypeOrderType); customerSet.AddNavigationTarget(edmNavigationPropertyAssociationLinkOne, orderSet); customerSet.AddNavigationTarget(edmNavigationPropertyAssociationLinkTwo, orderSet); var testCases = new[] { // Both nav link URL and association link URL new { NavigationLink = new ODataNestedResourceInfo() { Name = "NavProp1", IsCollection = false, Url = new Uri("http://odata.org/navlink"), AssociationLinkUrl = new Uri("http://odata.org/assoclink") }, PropertyName = "NavProp1", Atom = BuildXmlNavigationLink("NavProp1", "application/atom+xml;type=entry", "http://odata.org/navlink"), JsonLight = "\"" + JsonLightUtils.GetPropertyAnnotationName("NavProp1", JsonLightConstants.ODataNavigationLinkUrlAnnotationName) + "\":\"http://odata.org/navlink\"," + "\"" + JsonLightUtils.GetPropertyAnnotationName("NavProp1", JsonLightConstants.ODataAssociationLinkUrlAnnotationName) + "\":\"http://odata.org/assoclink\"" }, // Just nav link URL new { NavigationLink = new ODataNestedResourceInfo() { Name = "NavProp1", IsCollection = false, Url = new Uri("http://odata.org/navlink"), AssociationLinkUrl = null }, PropertyName = "NavProp1", Atom = BuildXmlNavigationLink("NavProp1", "application/atom+xml;type=entry", "http://odata.org/navlink"), JsonLight = "\"" + JsonLightUtils.GetPropertyAnnotationName("NavProp1", JsonLightConstants.ODataNavigationLinkUrlAnnotationName) + "\":\"http://odata.org/navlink\"" }, // Just association link URL new { NavigationLink = new ODataNestedResourceInfo() { Name = "NavProp1", IsCollection = false, Url = null, AssociationLinkUrl = new Uri("http://odata.org/assoclink") }, PropertyName = "NavProp1", Atom = (string)null, JsonLight = "\"" + JsonLightUtils.GetPropertyAnnotationName("NavProp1", JsonLightConstants.ODataAssociationLinkUrlAnnotationName) + "\":\"http://odata.org/assoclink\"" }, // Navigation link with both URLs null new { NavigationLink = new ODataNestedResourceInfo() { Name = "NavProp1", IsCollection = false, Url = null, AssociationLinkUrl = null }, PropertyName = "NavProp1", Atom = (string)null, JsonLight = string.Empty } }; IEnumerable <PayloadWriterTestDescriptor <ODataItem> > testDescriptors = testCases.Select(testCase => { ODataResource entry = ObjectModelUtils.CreateDefaultEntry(); entry.TypeName = "TestModel.CustomerType"; return(new PayloadWriterTestDescriptor <ODataItem>( this.Settings, new ODataItem[] { entry, testCase.NavigationLink, null }, (testConfiguration) => { if (testConfiguration.Format == ODataFormat.Json) { return new JsonWriterTestExpectedResults(this.Settings.ExpectedResultSettings) { Json = string.Join( "$(NL)", "{", testCase.JsonLight, "}"), FragmentExtractor = (result) => { var links = result.Object().GetPropertyAnnotations(testCase.PropertyName).ToList(); var jsonResult = new JsonObject(); links.ForEach(l => { // NOTE we remove all annoatations here and in particular the text annotations to be able to easily compare // against the expected results. This however means that we do not distinguish between the indented and non-indented case here. l.RemoveAllAnnotations(true); jsonResult.Add(l); }); return jsonResult; } }; } else { this.Settings.Assert.Fail("Unknown format '{0}'.", testConfiguration.Format); return null; } }) { Model = model, PayloadEdmElementContainer = customerSet }); }); // With and without model testDescriptors = testDescriptors.SelectMany(td => new[] { td, new PayloadWriterTestDescriptor <ODataItem>(td) { Model = null, PayloadEdmElementContainer = null } }); this.CombinatorialEngineProvider.RunCombinations( testDescriptors.PayloadCases(WriterPayloads.EntryPayloads), this.WriterTestConfigurationProvider.ExplicitFormatConfigurationsWithIndent.Where(testConfiguration => !testConfiguration.IsRequest), (testDescriptor, testConfiguration) => { testConfiguration = testConfiguration.Clone(); testConfiguration.MessageWriterSettings.SetServiceDocumentUri(ServiceDocumentUri); if (testDescriptor.Model == null && testConfiguration.Format == ODataFormat.Json) { return; } if (testDescriptor.IsGeneratedPayload && testDescriptor.Model != null) { return; } TestWriterUtils.WriteAndVerifyODataPayload(testDescriptor, testConfiguration, this.Assert, this.Logger); }); }
public void AssociationLinkMetadataValidationTest() { EdmModel model = new EdmModel(); var container = new EdmEntityContainer("TestModel", "Default"); model.AddElement(container); var edmEntityTypeOrderType = new EdmEntityType("TestModel", "OrderType"); model.AddElement(edmEntityTypeOrderType); var edmEntityTypeCustomerType = new EdmEntityType("TestModel", "CustomerType"); edmEntityTypeCustomerType.AddKeys(new EdmStructuralProperty(edmEntityTypeCustomerType, "ID", EdmCoreModel.Instance.GetInt32(false))); edmEntityTypeCustomerType.AddStructuralProperty("PrimitiveProperty", EdmCoreModel.Instance.GetString(true)); var edmNavigationPropertyAssociationLinkOne = edmEntityTypeCustomerType.AddUnidirectionalNavigation( new EdmNavigationPropertyInfo { Name = "Orders", Target = edmEntityTypeOrderType, TargetMultiplicity = EdmMultiplicity.Many }); var edmNavigationPropertyAssociationLinkTwo = edmEntityTypeCustomerType.AddUnidirectionalNavigation( new EdmNavigationPropertyInfo { Name = "BestFriend", Target = edmEntityTypeCustomerType, TargetMultiplicity = EdmMultiplicity.One }); model.AddElement(edmEntityTypeCustomerType); var edmEntityTypeOpenCustomerType = new EdmEntityType("TestModel", "OpenCustomerType", edmEntityTypeCustomerType, isAbstract: false, isOpen: true); model.AddElement(edmEntityTypeOpenCustomerType); var customerSet = container.AddEntitySet("Customers", edmEntityTypeCustomerType); var orderSet = container.AddEntitySet("Orders", edmEntityTypeOrderType); customerSet.AddNavigationTarget(edmNavigationPropertyAssociationLinkOne, orderSet); customerSet.AddNavigationTarget(edmNavigationPropertyAssociationLinkTwo, customerSet); Uri associationLinkUrl = new Uri("http://odata.org/associationlink"); var testCases = new[] { // Valid collection new { TypeName = "TestModel.CustomerType", NavigationLink = ObjectModelUtils.CreateDefaultCollectionLink("Orders"), ExpectedException = (ExpectedException)null, }, // Valid singleton new { TypeName = "TestModel.CustomerType", NavigationLink = ObjectModelUtils.CreateDefaultSingletonLink("BestFriend"), ExpectedException = (ExpectedException)null, }, // Undeclared on closed type new { TypeName = "TestModel.CustomerType", NavigationLink = ObjectModelUtils.CreateDefaultCollectionLink("NonExistant"), ExpectedException = ODataExpectedExceptions.ODataException("ValidationUtils_PropertyDoesNotExistOnType", "NonExistant", "TestModel.CustomerType"), }, // Undeclared on open type new { TypeName = "TestModel.OpenCustomerType", NavigationLink = ObjectModelUtils.CreateDefaultCollectionLink("NonExistant"), ExpectedException = ODataExpectedExceptions.ODataException("ValidationUtils_OpenNavigationProperty", "NonExistant", "TestModel.OpenCustomerType"), }, // Declared but of wrong kind new { TypeName = "TestModel.CustomerType", NavigationLink = ObjectModelUtils.CreateDefaultSingletonLink("PrimitiveProperty"), ExpectedException = ODataExpectedExceptions.ODataException("ValidationUtils_NavigationPropertyExpected", "PrimitiveProperty", "TestModel.CustomerType", "Structural"), }, }; var testDescriptors = testCases.Select(testCase => { ODataResource entry = ObjectModelUtils.CreateDefaultEntry(); entry.TypeName = testCase.TypeName; ODataNestedResourceInfo navigationLink = testCase.NavigationLink; navigationLink.AssociationLinkUrl = associationLinkUrl; return(new PayloadWriterTestDescriptor <ODataItem>( this.Settings, new ODataItem[] { entry, navigationLink }, tc => (WriterTestExpectedResults) new JsonWriterTestExpectedResults(this.Settings.ExpectedResultSettings) { ExpectedException2 = testCase.ExpectedException }) { Model = model, PayloadEdmElementContainer = customerSet }); }); this.CombinatorialEngineProvider.RunCombinations( testDescriptors, this.WriterTestConfigurationProvider.AtomFormatConfigurations .Where(testConfiguration => !testConfiguration.IsRequest), (testDescriptor, testConfiguration) => { testConfiguration = testConfiguration.Clone(); testConfiguration.MessageWriterSettings.SetServiceDocumentUri(ServiceDocumentUri); TestWriterUtils.WriteAndVerifyODataPayload(testDescriptor, testConfiguration, this.Assert, this.Logger); }); }
public ODataJsonLightWriterComplexIntegrationTests() { // Initialize open EntityType: EntityType. EdmModel edmModel = new EdmModel(); EdmEntityType edmEntityType = new EdmEntityType("TestNamespace", "EntityType", baseType: null, isAbstract: false, isOpen: true); edmEntityType.AddStructuralProperty("DeclaredProperty", EdmPrimitiveTypeKind.Guid); edmEntityType.AddStructuralProperty("DeclaredGeometryProperty", EdmPrimitiveTypeKind.Geometry); edmEntityType.AddStructuralProperty("DeclaredSingleProperty", EdmPrimitiveTypeKind.Single); edmEntityType.AddStructuralProperty("DeclaredDoubleProperty", EdmPrimitiveTypeKind.Double); edmEntityType.AddStructuralProperty("TimeOfDayProperty", EdmPrimitiveTypeKind.TimeOfDay); edmEntityType.AddStructuralProperty("DateProperty", EdmPrimitiveTypeKind.Date); edmModel.AddElement(edmEntityType); this.model = TestUtils.WrapReferencedModelsToMainModel(edmModel); this.entityType = edmEntityType; // Initialize derived ComplexType: Address and HomeAddress this.addressType = new EdmComplexType("TestNamespace", "Address", baseType: null, isAbstract: false, isOpen: false); this.addressType.AddStructuralProperty("City", EdmPrimitiveTypeKind.String); this.derivedAddressType = new EdmComplexType("TestNamespace", "HomeAddress", baseType: this.addressType, isAbstract: false, isOpen: false); this.derivedAddressType.AddStructuralProperty("FamilyName", EdmPrimitiveTypeKind.String); // Initialize open ComplexType: OpenAddress. this.openAddressType = new EdmComplexType("TestNamespace", "OpenAddress", baseType: null, isAbstract: false, isOpen: true); this.openAddressType.AddStructuralProperty("CountryRegion", EdmPrimitiveTypeKind.String); edmModel.AddElement(this.addressType); edmModel.AddElement(this.derivedAddressType); edmModel.AddElement(this.openAddressType); edmModel.AddEntityContainer("TestNamespace", "Container").AddEntitySet("entitySet", this.entityType); this.address = new ODataResource() { TypeName = "TestNamespace.Address", Properties = new ODataProperty[] { new ODataProperty { Name = "City", Value = "Shanghai" } } }; this.homeAddress = new ODataResource { TypeName = "TestNamespace.HomeAddress", Properties = new ODataProperty[] { new ODataProperty { Name = "FamilyName", Value = "Green" }, new ODataProperty { Name = "City", Value = "Shanghai" } } }; this.addressWithInstanceAnnotation = new ODataResource() { TypeName = "TestNamespace.Address", Properties = new ODataProperty[] { new ODataProperty { Name = "City", Value = "Shanghai" } }, InstanceAnnotations = new Collection <ODataInstanceAnnotation> { new ODataInstanceAnnotation("Is.ReadOnly", new ODataPrimitiveValue(true)) } }; this.homeAddressWithInstanceAnnotations = new ODataResource() { TypeName = "TestNamespace.HomeAddress", Properties = new ODataProperty[] { new ODataProperty { Name = "FamilyName", Value = "Green", InstanceAnnotations = new Collection <ODataInstanceAnnotation> { new ODataInstanceAnnotation("FamilyName.annotation", new ODataPrimitiveValue(true)) } }, new ODataProperty { Name = "City", Value = "Shanghai", InstanceAnnotations = new Collection <ODataInstanceAnnotation> { new ODataInstanceAnnotation("City.annotation1", new ODataPrimitiveValue(true)), new ODataInstanceAnnotation("City.annotation2", new ODataPrimitiveValue(123)) } } }, InstanceAnnotations = new Collection <ODataInstanceAnnotation> { new ODataInstanceAnnotation("Is.AutoComputable", new ODataPrimitiveValue(true)), new ODataInstanceAnnotation("Is.ReadOnly", new ODataPrimitiveValue(false)) } }; }
protected virtual Object CreateRootEntity(ODataResource resource, IReadOnlyList <NavigationInfo> navigationProperties, Type entityType) { return(CreateEntity(resource, navigationProperties)); }
private void ValidateTuples(IEnumerable <Tuple <ODataItem, ODataDeltaReaderState, ODataReaderState> > tuples, Uri nextLink = null, Uri feedDeltaLink = null) { foreach (var tuple in tuples) { switch (tuple.Item2) { case ODataDeltaReaderState.DeltaResourceSetStart: ODataDeltaResourceSet deltaFeed = tuple.Item1 as ODataDeltaResourceSet; Assert.NotNull(deltaFeed); if (deltaFeed.Count.HasValue) { Assert.Equal(deltaFeed.Count, feed.Count); } break; case ODataDeltaReaderState.DeltaResourceSetEnd: Assert.NotNull(tuple.Item1 as ODataDeltaResourceSet); if (nextLink != null) { Assert.Equal(nextLink, ((ODataDeltaResourceSet)tuple.Item1).NextPageLink); } if (feedDeltaLink != null) { Assert.Equal(feedDeltaLink, ((ODataDeltaResourceSet)tuple.Item1).DeltaLink); } break; case ODataDeltaReaderState.DeltaResourceStart: Assert.True(tuple.Item1 is ODataResource); break; case ODataDeltaReaderState.DeltaResourceEnd: var deltaResource = tuple.Item1 as ODataResource; Assert.NotNull(deltaResource); Assert.NotNull(deltaResource.Id); if (this.IdEqual(deltaResource.Id, customerUpdated.Id)) { Assert.True(PropertiesEqual(deltaResource.Properties, customerUpdated.Properties)); } else if (this.IdEqual(deltaResource.Id, order10643.Id)) { Assert.True(this.PropertiesEqual(deltaResource.Properties, order10643.Properties)); } else { Assert.True(this.PropertiesEqual(deltaResource.Properties, complexPropertyInOrder10643.Properties)); } break; case ODataDeltaReaderState.DeltaDeletedEntry: var deltaDeletedEntry = tuple.Item1 as ODataDeltaDeletedEntry; Assert.NotNull(deltaDeletedEntry); Assert.True(deltaDeletedEntry.Id.EndsWith(customerDeleted.Id)); Assert.Equal(deltaDeletedEntry.Reason, customerDeleted.Reason); break; case ODataDeltaReaderState.DeltaLink: var deltaLink = tuple.Item1 as ODataDeltaLink; Assert.NotNull(deltaLink); Assert.True(this.IdEqual(deltaLink.Source, linkToOrder10645.Source)); Assert.Equal(deltaLink.Relationship, linkToOrder10645.Relationship); Assert.True(this.IdEqual(deltaLink.Target, linkToOrder10645.Target)); break; case ODataDeltaReaderState.DeltaDeletedLink: var deltaDeletedLink = tuple.Item1 as ODataDeltaDeletedLink; Assert.NotNull(deltaDeletedLink); Assert.True(this.IdEqual(deltaDeletedLink.Source, linkToOrder10643.Source)); Assert.Equal(deltaDeletedLink.Relationship, linkToOrder10643.Relationship); Assert.True(this.IdEqual(deltaDeletedLink.Target, linkToOrder10643.Target)); break; case ODataDeltaReaderState.NestedResource: switch (tuple.Item3) { case ODataReaderState.Completed: case ODataReaderState.Start: ODataNestedResourceInfo nestedResource = tuple.Item1 as ODataNestedResourceInfo; Assert.NotNull(nestedResource); break; case ODataReaderState.EntityReferenceLink: break; case ODataReaderState.ResourceEnd: ODataResource entry = tuple.Item1 as ODataResource; Assert.NotNull(entry); if (entry.TypeName == "MyNS.Order") { Assert.Equal(10643, entry.Properties.Single(p => p.Name == "Id").Value); } else if (entry.TypeName == "MyNS.Product") { Assert.Equal(1, entry.Properties.Single(p => p.Name == "Id").Value); } else if (entry.TypeName == "MyNS.ProductDetail") { Assert.Equal(1, entry.Properties.Single(p => p.Name == "Id").Value); } else if (entry.TypeName == "MyNS.Address") { Assert.NotNull(entry.Properties.Single(p => p.Name == "Street").Value); } else if (entry.TypeName == "MyNS.City") { Assert.NotNull(entry.Properties.Single(p => p.Name == "CityName").Value); } break; case ODataReaderState.ResourceStart: Assert.NotNull(tuple.Item1 as ODataResource); break; case ODataReaderState.ResourceSetEnd: Assert.NotNull(tuple.Item1 as ODataResourceSet); break; case ODataReaderState.ResourceSetStart: Assert.NotNull(tuple.Item1 as ODataResourceSet); break; case ODataReaderState.NestedResourceInfoEnd: Assert.NotNull(tuple.Item1 as ODataNestedResourceInfo); break; case ODataReaderState.NestedResourceInfoStart: ODataNestedResourceInfo nestedResourceInfo = tuple.Item1 as ODataNestedResourceInfo; Assert.NotNull(nestedResourceInfo); Assert.True(nestedResourceInfo.Name.Equals("Details") || nestedResourceInfo.Name.Equals("Address") || nestedResourceInfo.Name.Equals("City")); break; default: Assert.True(false, "Wrong reader sub state."); break; } break; default: Assert.True(false, "Wrong reader state."); break; } } }
public void SetupEntryAndEntitySet() { entry = GenerateEntry(propertyType); entitySet = Model.EntityContainer.FindEntitySet(propertyType); }
/// <summary> /// Asynchronously start writing a delta resource. /// </summary> /// <param name="deltaResource">The delta resource to write.</param> /// <returns>A task instance that represents the asynchronous write operation.</returns> public override Task WriteStartAsync(ODataResource deltaResource) { return(this.resourceWriter.WriteStartAsync(deltaResource)); }
private object GetPropertyValue(IEdmTypeReference propertyType, object value, ODataResource root) { if (value == null) { return(value); } switch (propertyType.TypeKind()) { case EdmTypeKind.Complex: if (Converter.HasObjectConverter(value.GetType())) { return(Converter.Convert(value, value.GetType())); } return(CreateODataEntry(propertyType.FullName(), value.ToDictionary(TypeCache), root)); case EdmTypeKind.Collection: var collection = propertyType.AsCollection(); return(new ODataCollectionValue { TypeName = propertyType.FullName(), Items = ((IEnumerable)value).Cast <object>().Select(x => GetPropertyValue(collection.ElementType(), x, root)), }); case EdmTypeKind.Primitive: var mappedTypes = _typeMap.Where(x => x.Value == ((IEdmPrimitiveType)propertyType.Definition).PrimitiveKind); if (mappedTypes.Any()) { foreach (var mappedType in mappedTypes) { if (TryConvert(value, mappedType.Key, out var result)) { return(result); } else if (TypeCache.TryConvert(value, mappedType.Key, out result)) { return(result); } } throw new NotSupportedException($"Conversion is not supported from type {value.GetType()} to OData type {propertyType}"); } return(value); case EdmTypeKind.Enum: return(new ODataEnumValue(value.ToString())); case EdmTypeKind.Untyped: return(new ODataUntypedValue { RawValue = value.ToString() }); case EdmTypeKind.None: if (Converter.HasObjectConverter(value.GetType())) { return(Converter.Convert(value, value.GetType())); } throw new NotSupportedException($"Conversion is not supported from type {value.GetType()} to OData type {propertyType}"); default: return(value); } }
public void AssociationLinkTest() { string associationLinkName1 = "AssociationLinkOne"; string linkUrl1 = "http://odata.org/associationlink"; Uri linkUrlUri1 = new Uri(linkUrl1); string associationLinkName2 = "AssociationLinkTwo"; string linkUrl2 = "http://odata.org/associationlink2"; Uri linkUrlUri2 = new Uri(linkUrl2); EdmModel model = new EdmModel(); var edmEntityTypeOrderType = new EdmEntityType("TestModel", "OrderType"); model.AddElement(edmEntityTypeOrderType); var edmEntityTypeCustomerType = new EdmEntityType("TestModel", "CustomerType"); var edmNavigationPropertyAssociationLinkOne = edmEntityTypeCustomerType.AddUnidirectionalNavigation( new EdmNavigationPropertyInfo { Name = associationLinkName1, Target = edmEntityTypeOrderType, TargetMultiplicity = EdmMultiplicity.One }); var edmNavigationPropertyAssociationLinkTwo = edmEntityTypeCustomerType.AddUnidirectionalNavigation( new EdmNavigationPropertyInfo { Name = associationLinkName2, Target = edmEntityTypeOrderType, TargetMultiplicity = EdmMultiplicity.Many }); model.AddElement(edmEntityTypeCustomerType); var container = new EdmEntityContainer("TestModel", "Default"); model.AddElement(container); var customerSet = container.AddEntitySet("Customers", edmEntityTypeCustomerType); var orderSet = container.AddEntitySet("Orders", edmEntityTypeOrderType); customerSet.AddNavigationTarget(edmNavigationPropertyAssociationLinkOne, orderSet); customerSet.AddNavigationTarget(edmNavigationPropertyAssociationLinkTwo, orderSet); var testCases = new[] { new { NavigationLink = ObjectModelUtils.CreateDefaultNavigationLink(associationLinkName1, linkUrlUri1), Atom = BuildXmlAssociationLink(associationLinkName1, "application/xml", linkUrl1), JsonLight = (string)null, }, new { NavigationLink = ObjectModelUtils.CreateDefaultNavigationLink(associationLinkName2, linkUrlUri2), Atom = BuildXmlAssociationLink(associationLinkName2, "application/xml", linkUrl2), JsonLight = (string)null }, }; var testCasesWithMultipleLinks = testCases.Variations() .Select(tcs => new { NavigationLinks = tcs.Select(tc => tc.NavigationLink), Atom = string.Concat(tcs.Select(tc => tc.Atom)), JsonLight = string.Join(",", tcs.Where(tc => tc.JsonLight != null).Select(tc => tc.JsonLight)) }); var testDescriptors = testCasesWithMultipleLinks.Select(testCase => { ODataResource entry = ObjectModelUtils.CreateDefaultEntry(); entry.TypeName = "TestModel.CustomerType"; List <ODataItem> items = new ODataItem[] { entry }.ToList(); foreach (var navLink in testCase.NavigationLinks) { items.Add(navLink); items.Add(null); } return(new PayloadWriterTestDescriptor <ODataItem>( this.Settings, items, (testConfiguration) => { var firstAssocLink = testCase.NavigationLinks == null ? null : testCase.NavigationLinks.FirstOrDefault(); if (testConfiguration.Format == ODataFormat.Json) { return new JsonWriterTestExpectedResults(this.Settings.ExpectedResultSettings) { Json = string.Join( "$(NL)", "{", testCase.JsonLight, "}"), FragmentExtractor = (result) => { var associationLinks = result.Object().GetAnnotationsWithName("@" + JsonLightConstants.ODataAssociationLinkUrlAnnotationName).ToList(); var jsonResult = new JsonObject(); associationLinks.ForEach(l => { // NOTE we remove all annoatations here and in particular the text annotations to be able to easily compare // against the expected results. This however means that we do not distinguish between the indented and non-indented case here. l.RemoveAllAnnotations(true); jsonResult.Add(l); }); return jsonResult; }, }; } else { this.Settings.Assert.Fail("Unknown format '{0}'.", testConfiguration.Format); return null; } }) { Model = model, PayloadEdmElementContainer = customerSet }); }); // With and without model testDescriptors = testDescriptors.SelectMany(td => new[] { td, new PayloadWriterTestDescriptor <ODataItem>(td) { Model = null, PayloadEdmElementContainer = null } }); this.CombinatorialEngineProvider.RunCombinations( testDescriptors.PayloadCases(WriterPayloads.EntryPayloads), this.WriterTestConfigurationProvider.ExplicitFormatConfigurationsWithIndent, (testDescriptor, testConfiguration) => { testConfiguration = testConfiguration.Clone(); testConfiguration.MessageWriterSettings.SetServiceDocumentUri(ServiceDocumentUri); if (testDescriptor.Model == null && testConfiguration.Format == ODataFormat.Json) { return; } if (testDescriptor.IsGeneratedPayload && testDescriptor.Model != null) { return; } TestWriterUtils.WriteAndVerifyODataPayload(testDescriptor, testConfiguration, this.Assert, this.Logger); }); }
public async Task WriteResourceEndMetadataPropertiesAsync_WritesActionsAndFunctionsMetadataProperties(ODataResource resource, string expected) { var jsonLightWriterResourceState = new TestODataJsonLightWriterResourceState( resource, this.categoryEntityType, CreateCategorySerializationInfo(), this.categoriesEntitySet, false); var result = await SetupJsonLightResourceSerializerAndRunTestAsync( (jsonLightResourceSerializer) => { return(jsonLightResourceSerializer.WriteResourceEndMetadataPropertiesAsync( jsonLightWriterResourceState, new NullDuplicatePropertyNameChecker())); }); Assert.Equal(expected, result); }
/// <summary> /// Returns all interesting payloads for a named stream. /// </summary> /// <param name="testDescriptor">Test descriptor which will end up writing a single entry with a single named stream. /// The entry is not going to be used, but the named stream from it will.</param> /// <returns>Enumeration of test descriptors which will include the original named stream in some interesting scenarios.</returns> public static IEnumerable <PayloadWriterTestDescriptor <ODataItem> > NamedStreamPayloads(PayloadWriterTestDescriptor <ODataItem> testDescriptor) { ODataResource tempEntry = testDescriptor.PayloadItems[0] as ODataResource; Debug.Assert(tempEntry != null, "A single entry payload is expected."); ODataProperty namedStreamProperty = tempEntry.Properties.FirstOrDefault(p => p != null && p.Value is ODataStreamReferenceValue); // Note - the named stream can be null - it is a valid test case !!!! var payloadCases = new WriterPayloadCase <ODataItem>[] { new WriterPayloadCase <ODataItem>() // Single named stream on an entry { GetPayloadItems = () => { ODataResource entry = ObjectModelUtils.CreateDefaultEntry(); entry.TypeName = "TestModel.EntityWithStreamProperty"; entry.Properties = new ODataProperty[] { namedStreamProperty }; return(new ODataItem[] { entry }); }, ModelBuilder = (model) => { model = model.Clone(); model.EntityType("EntityWithStreamProperty", "TestModel") .StreamProperty(namedStreamProperty.Name); return(model); }, AtomFragmentExtractor = (testConfiguration, result) => { return(TestAtomUtils.ExtractNamedStreamLinksFromEntry(result, namedStreamProperty.Name)); }, JsonLightFragmentExtractor = (testConfiguration, result) => { return(new JsonObject().AddProperties(result.Object().GetPropertyAnnotationsAndProperty(namedStreamProperty.Name))); }, }, new WriterPayloadCase <ODataItem>() // Single named stream on an entry with other properties before/after it { GetPayloadItems = () => { ODataResource entry = ObjectModelUtils.CreateDefaultEntry(); entry.TypeName = "TestModel.EntityWithStreamPropertyAndOtherProperties"; entry.Properties = new ODataProperty[] { new ODataProperty { Name = "Id", Value = 1 }, new ODataProperty { Name = "Name", Value = "Clemens" }, namedStreamProperty, new ODataProperty { Name = "Address", Value = new ODataComplexValue { TypeName = "TestModel.AddressType", Properties = new ODataProperty[] { new ODataProperty { Name = "Street", Value = "Am Euro Platz" }, new ODataProperty { Name = "City", Value = "Vienna" } } } } }; return(new ODataItem[] { entry }); }, ModelBuilder = (model) => { model = model.Clone(); var addressType = model.ComplexType("AddressType", "TestModel") .Property("Street", EdmPrimitiveTypeKind.String) .Property("City", EdmPrimitiveTypeKind.String); model.EntityType("EntityWithStreamPropertyAndOtherProperties", "TestModel") .KeyProperty("Id", (EdmTypeReference)EdmCoreModel.Instance.GetInt32(false)) .Property("Name", EdmPrimitiveTypeKind.String) .StreamProperty(namedStreamProperty.Name) .Property("Address", new EdmComplexTypeReference(addressType, false)); return(model); }, AtomFragmentExtractor = (testConfiguration, result) => { return(TestAtomUtils.ExtractNamedStreamLinksFromEntry(result, namedStreamProperty.Name)); }, JsonLightFragmentExtractor = (testConfiguration, result) => { return(new JsonObject().AddProperties(result.Object().GetPropertyAnnotationsAndProperty(namedStreamProperty.Name))); }, }, new WriterPayloadCase <ODataItem>() // Multiple named stream properties on an entry { GetPayloadItems = () => { ODataResource entry = ObjectModelUtils.CreateDefaultEntry(); entry.TypeName = "TestModel.EntityWithSeveralStreamProperties"; entry.Properties = new ODataProperty[] { new ODataProperty { Name = "Id", Value = 1 }, new ODataProperty { Name = "__Stream1", Value = new ODataStreamReferenceValue { ReadLink = new Uri("http://odata.org/stream1/readlink") } }, new ODataProperty { Name = "__Stream2", Value = new ODataStreamReferenceValue { EditLink = new Uri("http://odata.org/stream2/editlink") } }, namedStreamProperty, new ODataProperty { Name = "__Stream3", Value = new ODataStreamReferenceValue { ReadLink = new Uri("http://odata.org/stream3/readlink"), ContentType = "stream3:contenttype" } }, }; return(new ODataItem[] { entry }); }, ModelBuilder = (model) => { model = model.Clone(); model.EntityType("EntityWithSeveralStreamProperties", "TestModel") .KeyProperty("Id", (EdmTypeReference)EdmCoreModel.Instance.GetInt32(false)) .StreamProperty("__Stream1") .StreamProperty("__Stream2") .StreamProperty(namedStreamProperty.Name) .StreamProperty("__Stream3"); return(model); }, AtomFragmentExtractor = (testConfiguration, result) => { return(TestAtomUtils.ExtractNamedStreamLinksFromEntry(result, namedStreamProperty.Name)); }, JsonLightFragmentExtractor = (testConfiguration, result) => { return(new JsonObject().AddProperties(result.Object().GetPropertyAnnotationsAndProperty(namedStreamProperty.Name))); }, }, }; return(ApplyPayloadCases <ODataItem>(testDescriptor, payloadCases)); }
public virtual void AppendDynamicProperties(ODataResource resource, SelectExpandNode selectExpandNode, ResourceContext resourceContext) { Contract.Assert(resource != null); Contract.Assert(selectExpandNode != null); Contract.Assert(resourceContext != null); if (!resourceContext.StructuredType.IsOpen || // non-open type (!selectExpandNode.SelectAllDynamicProperties && !selectExpandNode.SelectedDynamicProperties.Any())) { return; } bool nullDynamicPropertyEnabled = false; if (resourceContext.Request != null) { // TODO: /* * HttpConfiguration configuration = resourceContext.Request.GetConfiguration(); * if (configuration != null) * { * nullDynamicPropertyEnabled = configuration.HasEnabledNullDynamicProperty(); * }*/ } IEdmStructuredType structuredType = resourceContext.StructuredType; IEdmStructuredObject structuredObject = resourceContext.EdmObject; object value; IDelta delta = structuredObject as IDelta; if (delta == null) { PropertyInfo dynamicPropertyInfo = EdmLibHelpers.GetDynamicPropertyDictionary(structuredType, resourceContext.EdmModel); if (dynamicPropertyInfo == null || structuredObject == null || !structuredObject.TryGetPropertyValue(dynamicPropertyInfo.Name, out value) || value == null) { return; } } else { value = ((EdmStructuredObject)structuredObject).TryGetDynamicProperties(); } IDictionary <string, object> dynamicPropertyDictionary = (IDictionary <string, object>)value; // Build a HashSet to store the declared property names. // It is used to make sure the dynamic property name is different from all declared property names. HashSet <string> declaredPropertyNameSet = new HashSet <string>(resource.Properties.Select(p => p.Name)); List <ODataProperty> dynamicProperties = new List <ODataProperty>(); IEnumerable <KeyValuePair <string, object> > dynamicPropertiesToSelect = dynamicPropertyDictionary.Where( x => !selectExpandNode.SelectedDynamicProperties.Any() || selectExpandNode.SelectedDynamicProperties.Contains(x.Key)); foreach (KeyValuePair <string, object> dynamicProperty in dynamicPropertiesToSelect) { if (String.IsNullOrEmpty(dynamicProperty.Key)) { continue; } if (dynamicProperty.Value == null) { if (nullDynamicPropertyEnabled) { dynamicProperties.Add(new ODataProperty { Name = dynamicProperty.Key, Value = new ODataNullValue() }); } continue; } if (declaredPropertyNameSet.Contains(dynamicProperty.Key)) { throw Error.InvalidOperation(SRResources.DynamicPropertyNameAlreadyUsedAsDeclaredPropertyName, dynamicProperty.Key, structuredType.FullTypeName()); } IEdmTypeReference edmTypeReference = resourceContext.SerializerContext.GetEdmType(dynamicProperty.Value, dynamicProperty.Value.GetType()); if (edmTypeReference == null) { throw Error.NotSupported(SRResources.TypeOfDynamicPropertyNotSupported, dynamicProperty.Value.GetType().FullName, dynamicProperty.Key); } if (edmTypeReference.IsStructured() || (edmTypeReference.IsCollection() && edmTypeReference.AsCollection().ElementType().IsStructured())) { if (resourceContext.DynamicComplexProperties == null) { resourceContext.DynamicComplexProperties = new ConcurrentDictionary <string, object>(); } resourceContext.DynamicComplexProperties.Add(dynamicProperty); } else { ODataEdmTypeSerializer propertySerializer = SerializerProvider.GetEdmTypeSerializer(resourceContext.Context, edmTypeReference); if (propertySerializer == null) { throw Error.NotSupported(SRResources.DynamicPropertyCannotBeSerialized, dynamicProperty.Key, edmTypeReference.FullName()); } dynamicProperties.Add(propertySerializer.CreateProperty( dynamicProperty.Value, edmTypeReference, dynamicProperty.Key, resourceContext.SerializerContext)); } } if (dynamicProperties.Any()) { resource.Properties = resource.Properties.Concat(dynamicProperties); } }
private byte[] ServiceReadSingletonBatchRequestAndWriterBatchResponse(ODataJsonBatchPayloadTestCase testCase, ODataVersion version) { string requestPayload = testCase.RequestPayload; Action <ODataBatchOperationRequestMessage, IList <string> > requestOpMessageVerifier = testCase.RequestMessageDependsOnIdVerifier; IODataRequestMessage requestMessage = new InMemoryMessage() { Stream = new MemoryStream(Encoding.ASCII.GetBytes(requestPayload)) }; requestMessage.SetHeader("Content-Type", batchContentTypeApplicationJson); MemoryStream responseStream = new MemoryStream(); using (ODataMessageReader messageReader = new ODataMessageReader(requestMessage, new ODataMessageReaderSettings() { MaxProtocolVersion = version }, this.edmModel)) { IODataResponseMessage responseMessage = new InMemoryMessage { Stream = responseStream }; // Client is expected to receive the response message in the same format as that is used in the request sent. responseMessage.SetHeader("Content-Type", batchContentTypeApplicationJson); ODataMessageWriterSettings settings = new ODataMessageWriterSettings() { Version = version }; settings.SetServiceDocumentUri(new Uri(serviceDocumentUri)); ODataMessageWriter messageWriter = new ODataMessageWriter(responseMessage, settings, null); int operationIdx = 0; ODataBatchWriter batchWriter = messageWriter.CreateODataBatchWriter(); batchWriter.WriteStartBatch(); ODataBatchReader batchReader = messageReader.CreateODataBatchReader(); while (batchReader.Read()) { switch (batchReader.State) { case ODataBatchReaderState.Operation: // Encountered an operation (either top-level or in a change set) ODataBatchOperationRequestMessage operationMessage = batchReader.CreateOperationRequestMessage(); // Verify operation message if applicable. requestOpMessageVerifier?.Invoke(operationMessage, testCase.ListOfDependsOnIds.ElementAt(operationIdx)); if (operationMessage.Method == "POST") { ODataBatchOperationResponseMessage response = batchWriter.CreateOperationResponseMessage(operationMessage.ContentId); response.StatusCode = 201; response.SetHeader("Content-Type", batchContentTypeApplicationJson); } else if (operationMessage.Method == "GET") { ODataBatchOperationResponseMessage response = batchWriter.CreateOperationResponseMessage(operationMessage.ContentId); response.StatusCode = 200; response.SetHeader("Content-Type", batchContentTypeApplicationJson); using (ODataMessageWriter operationMessageWriter = new ODataMessageWriter(response, settings, this.edmModel)) { ODataWriter entryWriter = operationMessageWriter.CreateODataResourceWriter(this.singleton, this.userType); ODataResource entry = new ODataResource() { TypeName = "NS.User", Properties = new[] { new ODataProperty() { Name = "UserPrincipalName", Value = "*****@*****.**" }, new ODataProperty() { Name = "GivenName", Value = "Jon" } } }; entryWriter.WriteStart(entry); entryWriter.WriteEnd(); } } operationIdx++; break; case ODataBatchReaderState.ChangesetStart: batchWriter.WriteStartChangeset(); break; case ODataBatchReaderState.ChangesetEnd: batchWriter.WriteEndChangeset(); break; } } batchWriter.WriteEndBatch(); } responseStream.Position = 0; return(responseStream.ToArray()); }
public void ComplexTypeInstanceAnnotation() { ODataMessageReaderSettings readerSettings = new ODataMessageReaderSettings() { BaseUri = ServiceBaseUri }; foreach (var mimeType in TestMimeTypes) { var requestMessage = new HttpWebRequestMessage(new Uri(ServiceBaseUri.AbsoluteUri + "People(1)", UriKind.Absolute)); requestMessage.SetHeader("Accept", mimeType); requestMessage.SetHeader("Prefer", string.Format("{0}={1}", IncludeAnnotation, "*")); var responseMessage = requestMessage.GetResponse(); Assert.Equal(200, responseMessage.StatusCode); if (!mimeType.Contains(MimeTypes.ODataParameterNoMetadata)) { using (var messageReader = new ODataMessageReader(responseMessage, readerSettings, Model)) { var reader = messageReader.CreateODataResourceReader(); ODataResource entry = null; bool startHomeAddress = false; while (reader.Read()) { if (reader.State == ODataReaderState.NestedResourceInfoStart) { ODataNestedResourceInfo navigation = reader.Item as ODataNestedResourceInfo; if (navigation != null && navigation.Name == "HomeAddress") { startHomeAddress = true; } } else if (reader.State == ODataReaderState.NestedResourceInfoEnd) { ODataNestedResourceInfo navigation = reader.Item as ODataNestedResourceInfo; if (navigation != null && navigation.Name == "HomeAddress") { startHomeAddress = false; } } else if (reader.State == ODataReaderState.ResourceEnd) { entry = reader.Item as ODataResource; if (startHomeAddress) { // Verify Annotation on Complex Type ODataInstanceAnnotation annotationOnHomeAddress = entry.InstanceAnnotations.Last(); Assert.Equal(string.Format("{0}.AddressType", TestModelNameSpace), annotationOnHomeAddress.Name); Assert.Equal("Home", (annotationOnHomeAddress.Value as ODataPrimitiveValue).Value); // TODO : Fix #625 //// Verify Annotation on Property in Complex Type //ODataInstanceAnnotation annotationOnCity = entry.Properties.SingleOrDefault(p => p.Name.Equals("City")).InstanceAnnotations.SingleOrDefault(); //Assert.Equal(string.Format("{0}.CityInfo", TestModelNameSpace), annotationOnCity.Name); //Assert.Equal(2, (annotationOnCity.Value as ODataComplexValue).Properties.Count()); } } } // Verify Annotation on Property of Entity ODataInstanceAnnotation annotationonEmails = entry.Properties.SingleOrDefault(p => p.Name.Equals("Emails")).InstanceAnnotations.SingleOrDefault(); Assert.Equal(string.Format("{0}.DisplayName", TestModelNameSpace), annotationonEmails.Name); Assert.Equal("EmailAddresses", (annotationonEmails.Value as ODataPrimitiveValue).Value); Assert.Equal(ODataReaderState.Completed, reader.State); } } } }
private async Task WriteNestedEntryAsync(ODataWriter entryWriter, string entryName, ODataResource entry) { await entryWriter.WriteStartAsync(new ODataNestedResourceInfo() { Name = entryName, IsCollection = false, }).ConfigureAwait(false); await WriteEntryPropertiesAsync(entryWriter, entry, null); await entryWriter.WriteEndAsync().ConfigureAwait(false); }
private byte[] CreateBigBatchRequest(int repeatCount) { MemoryStream stream = new MemoryStream(); IODataRequestMessage requestMessage = new InMemoryMessage { Stream = stream }; requestMessage.SetHeader("Content-Type", batchContentTypeApplicationJson); ODataMessageWriterSettings settings = new ODataMessageWriterSettings(); settings.BaseUri = new Uri(serviceDocumentUri); using (ODataMessageWriter messageWriter = new ODataMessageWriter(requestMessage, settings)) { ODataBatchWriter batchWriter = messageWriter.CreateODataBatchWriter(); batchWriter.WriteStartBatch(); // Each iteration generates a change set with two operations, followed by one top level operation. // Operations count in each iteration is three. for (int idx = 0; idx < repeatCount * 3; idx += 3) { batchWriter.WriteStartChangeset(); ODataBatchOperationRequestMessage createOperationMessage = batchWriter.CreateOperationRequestMessage( "PUT", new Uri(string.Format(CultureInfo.InvariantCulture, "{0}/{1}", serviceDocumentUri, "MySingleton")), idx.ToString()); using (ODataMessageWriter operationMessageWriter = new ODataMessageWriter(createOperationMessage)) { ODataWriter entryWriter = operationMessageWriter.CreateODataResourceWriter(); ODataResource entry = new ODataResource() { TypeName = "NS.Web", Properties = new[] { new ODataProperty() { Name = "WebId", Value = "webid_" + idx }, new ODataProperty() { Name = "Name", Value = this.aVeryLongString } } }; entryWriter.WriteStart(entry); entryWriter.WriteEnd(); } // A PATCH operation that depends on the preceding PUT operation. List <string> dependsOnIds = new List <string> { idx.ToString() }; ODataBatchOperationRequestMessage updateOperationMessage = batchWriter.CreateOperationRequestMessage( "PATCH", new Uri(string.Format(CultureInfo.InvariantCulture, "{0}/{1}", serviceDocumentUri, "$" + idx)), (idx + 1).ToString(), BatchPayloadUriOption.AbsoluteUri, dependsOnIds); // Verify that input values are copied into a new list. Assert.Equal(dependsOnIds, updateOperationMessage.DependsOnIds); Assert.NotSame(dependsOnIds, updateOperationMessage.DependsOnIds); using (ODataMessageWriter operationMessageWriter = new ODataMessageWriter(updateOperationMessage)) { var entryWriter = operationMessageWriter.CreateODataResourceWriter(); var entry = new ODataResource() { TypeName = "NS.Web", Properties = new[] { new ODataProperty() { Name = "WebId", Value = "webid_" + (idx + 1) } } }; entryWriter.WriteStart(entry); entryWriter.WriteEnd(); } Assert.Equal(createOperationMessage.GroupId, updateOperationMessage.GroupId); batchWriter.WriteEndChangeset(); ODataBatchOperationRequestMessage queryOperationMessage = batchWriter.CreateOperationRequestMessage( "GET", new Uri(string.Format(CultureInfo.InvariantCulture, "{0}/{1}", serviceDocumentUri, "MySingleton")), (idx + 2).ToString()); queryOperationMessage.SetHeader("Accept", "application/json;odata.metadata=full"); } batchWriter.WriteEndBatch(); stream.Position = 0; return(stream.ToArray()); } }
private void RegisterRootEntry(ODataResource root) { _resourceEntries.Add(root, new List <ODataResource>()); }
public IEdmStructuredType GetEntityType2(ODataResource entry) { return(this.GetResourceType(entry)); }
private ODataResource CreateODataEntry(string typeName, IDictionary <string, object> properties, ODataResource root) { var entry = new ODataResource { TypeName = typeName }; root = root ?? entry; var entryType = _model.FindDeclaredType(entry.TypeName); var typeProperties = typeof(IEdmEntityType).IsTypeAssignableFrom(entryType.GetType()) ? (entryType as IEdmEntityType).Properties().ToList() : (entryType as IEdmComplexType).Properties().ToList(); string findMatchingPropertyName(string name) { var property = typeProperties.BestMatch(y => y.Name, name, _session.Settings.NameMatchResolver); return(property != null ? property.Name : name); } IEdmTypeReference findMatchingPropertyType(string name) { var property = typeProperties.BestMatch(y => y.Name, name, _session.Settings.NameMatchResolver); return(property?.Type); } bool isStructural(IEdmTypeReference type) => type != null && type.TypeKind() == EdmTypeKind.Complex; bool isStructuralCollection(IEdmTypeReference type) => type != null && type.TypeKind() == EdmTypeKind.Collection && type.AsCollection().ElementType().TypeKind() == EdmTypeKind.Complex; bool isPrimitive(IEdmTypeReference type) => !isStructural(type) && !isStructuralCollection(type); var resourceEntry = new ResourceProperties(entry); entry.Properties = properties .Where(x => isPrimitive(findMatchingPropertyType(x.Key))) .Select(x => new ODataProperty { Name = findMatchingPropertyName(x.Key), Value = GetPropertyValue(typeProperties, x.Key, x.Value, root) }).ToList(); resourceEntry.CollectionProperties = properties .Where(x => isStructuralCollection(findMatchingPropertyType(x.Key))) .Select(x => new KeyValuePair <string, ODataCollectionValue>( findMatchingPropertyName(x.Key), GetPropertyValue(typeProperties, x.Key, x.Value, root) as ODataCollectionValue)) .ToDictionary(); resourceEntry.StructuralProperties = properties .Where(x => isStructural(findMatchingPropertyType(x.Key))) .Select(x => new KeyValuePair <string, ODataResource>( findMatchingPropertyName(x.Key), GetPropertyValue(typeProperties, x.Key, x.Value, root) as ODataResource)) .ToDictionary(); _resourceEntryMap.Add(entry, resourceEntry); if (root != null && _resourceEntries.TryGetValue(root, out var entries)) { entries.Add(entry); } return(entry); }
protected override ODataWriterCore.ResourceScope CreateResourceScope(ODataResource entry, IEdmNavigationSource navigationSource, IEdmStructuredType resourceType, bool skipWriting, SelectedPropertiesNode selectedProperties, ODataUri odataUri, bool isUndeclared) { throw new NotImplementedException(); }
private object GetPropertyValue(IEnumerable <IEdmProperty> properties, string key, object value, ODataResource root) { var property = properties.BestMatch(x => x.Name, key, _session.Settings.NameMatchResolver); return(property != null?GetPropertyValue(property.Type, value, root) : value); }
public ODataJsonLightInheritComplexCollectionWriterTests() { collectionStartWithoutSerializationInfo = new ODataResourceSet(); collectionStartWithSerializationInfo = new ODataResourceSet(); collectionStartWithSerializationInfo.SetSerializationInfo(new ODataResourceSerializationInfo { ExpectedTypeName = "ns.Address" }); address = new ODataResource { Properties = new[] { new ODataProperty { Name = "Street", Value = "1 Microsoft Way" }, new ODataProperty { Name = "Zipcode", Value = 98052 }, new ODataProperty { Name = "State", Value = new ODataEnumValue("WA", "ns.StateEnum") } } }; items = new[] { address }; derivedAddress = new ODataResource { Properties = new[] { new ODataProperty { Name = "Street", Value = "1 Microsoft Way" }, new ODataProperty { Name = "Zipcode", Value = 98052 }, new ODataProperty { Name = "State", Value = new ODataEnumValue("WA", "ns.StateEnum") }, new ODataProperty { Name = "City", Value = "Shanghai" } }, TypeName = "ns.DerivedAddress" }; derivedItems = new[] { derivedAddress }; EdmComplexType addressType = new EdmComplexType("ns", "Address"); addressType.AddProperty(new EdmStructuralProperty(addressType, "Street", EdmCoreModel.Instance.GetString(isNullable: true))); addressType.AddProperty(new EdmStructuralProperty(addressType, "Zipcode", EdmCoreModel.Instance.GetInt32(isNullable: true))); var stateEnumType = new EdmEnumType("ns", "StateEnum", isFlags: true); stateEnumType.AddMember("IL", new EdmEnumMemberValue(1)); stateEnumType.AddMember("WA", new EdmEnumMemberValue(2)); addressType.AddProperty(new EdmStructuralProperty(addressType, "State", new EdmEnumTypeReference(stateEnumType, true))); EdmComplexType derivedAddressType = new EdmComplexType("ns", "DerivedAddress", addressType, false); derivedAddressType.AddProperty(new EdmStructuralProperty(derivedAddressType, "City", EdmCoreModel.Instance.GetString(isNullable: true))); addressTypeReference = new EdmComplexTypeReference(addressType, isNullable: false); derivedAddressTypeReference = new EdmComplexTypeReference(derivedAddressType, isNullable: false); }
/// <summary>Write the entry element.</summary> /// <param name="expanded">Expanded result provider for the specified <paramref name="element"/>.</param> /// <param name="element">Element representing the entry element.</param> /// <param name="resourceInstanceInFeed">true if the resource instance being serialized is inside a feed; false otherwise.</param> /// <param name="expectedType">Expected type of the entry element.</param> private void WriteEntry(IExpandedResult expanded, object element, bool resourceInstanceInFeed, ResourceType expectedType) { Debug.Assert(element != null, "element != null"); Debug.Assert(expectedType != null && expectedType.ResourceTypeKind == ResourceTypeKind.EntityType, "expectedType != null && expectedType.ResourceTypeKind == ResourceTypeKind.EntityType"); this.IncrementSegmentResultCount(); ODataResource entry = new ODataResource(); if (!resourceInstanceInFeed) { entry.SetSerializationInfo(new ODataResourceSerializationInfo { NavigationSourceName = this.CurrentContainer.Name, NavigationSourceEntityTypeName = this.CurrentContainer.ResourceType.FullName, ExpectedTypeName = expectedType.FullName }); } string title = expectedType.Name; ResourceType actualResourceType = WebUtil.GetNonPrimitiveResourceType(this.Provider, element); if (actualResourceType.ResourceTypeKind != ResourceTypeKind.EntityType) { // making sure that the actual resource type is an entity type throw new DataServiceException(500, Microsoft.OData.Service.Strings.BadProvider_InconsistentEntityOrComplexTypeUsage(actualResourceType.FullName)); } EntityToSerialize entityToSerialize = this.WrapEntity(element, actualResourceType); // populate the media resource, if the entity is a MLE. entry.MediaResource = this.GetMediaResource(entityToSerialize, title); // Write the type name this.PayloadMetadataPropertyManager.SetTypeName(entry, this.CurrentContainer.ResourceType.FullName, actualResourceType.FullName); // Write Id element this.PayloadMetadataPropertyManager.SetId(entry, () => entityToSerialize.SerializedKey.Identity); // Write "edit" link this.PayloadMetadataPropertyManager.SetEditLink(entry, () => entityToSerialize.SerializedKey.RelativeEditLink); // Write the etag property, if the type has etag properties this.PayloadMetadataPropertyManager.SetETag(entry, () => this.GetETagValue(element, actualResourceType)); IEnumerable <ProjectionNode> projectionNodes = this.GetProjections(); if (projectionNodes != null) { // Filter the projection nodes for the actual type of the entity // The projection node might refer to the property in a derived type. If the TargetResourceType of // the projection node is not a super type, then we do not want to serialize this property. projectionNodes = projectionNodes.Where(projectionNode => projectionNode.TargetResourceType.IsAssignableFrom(actualResourceType)); // Because we are going to enumerate through these multiple times, create a list. projectionNodes = projectionNodes.ToList(); } // Populate the advertised actions IEnumerable <ODataAction> actions; if (this.TryGetAdvertisedActions(entityToSerialize, resourceInstanceInFeed, out actions)) { foreach (ODataAction action in actions) { entry.AddAction(action); } } // Populate all the normal properties entry.Properties = this.GetEntityProperties(entityToSerialize, projectionNodes); // And start the entry var args = new DataServiceODataWriterEntryArgs(entry, element, this.Service.OperationContext); this.dataServicesODataWriter.WriteStart(args); this.WriteAllNestedComplexProperties(entityToSerialize, projectionNodes); // Now write all the navigation properties this.WriteNavigationProperties(expanded, entityToSerialize, resourceInstanceInFeed, projectionNodes); // And write the end of the entry this.dataServicesODataWriter.WriteEnd(args); #if ASTORIA_FF_CALLBACKS this.Service.InternalOnWriteItem(target, element); #endif }