예제 #1
0
 /// <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);
 }
예제 #2
0
 protected override void EndResource(ODataResource entry)
 {
     throw new NotImplementedException();
 }
예제 #3
0
 protected override Task EndResourceAsync(ODataResource resource)
 {
     throw new NotImplementedException();
 }
예제 #4
0
 /// <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);
            }
        }
예제 #6
0
        /// <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);
        }
예제 #7
0
        /// <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))
                }
            };
        }
예제 #11
0
 protected virtual Object CreateRootEntity(ODataResource resource, IReadOnlyList <NavigationInfo> navigationProperties, Type entityType)
 {
     return(CreateEntity(resource, navigationProperties));
 }
예제 #12
0
        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;
                }
            }
        }
예제 #13
0
 public void SetupEntryAndEntitySet()
 {
     entry     = GenerateEntry(propertyType);
     entitySet = Model.EntityContainer.FindEntitySet(propertyType);
 }
예제 #14
0
 /// <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));
 }
예제 #15
0
        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);
            }
        }
예제 #16
0
        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);
        }
예제 #18
0
        /// <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));
        }
예제 #19
0
        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);
            }
        }
예제 #20
0
        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);
                    }
                }
            }
        }
예제 #22
0
        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());
            }
        }
예제 #24
0
 private void RegisterRootEntry(ODataResource root)
 {
     _resourceEntries.Add(root, new List <ODataResource>());
 }
예제 #25
0
 public IEdmStructuredType GetEntityType2(ODataResource entry)
 {
     return(this.GetResourceType(entry));
 }
예제 #26
0
        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);
        }
예제 #27
0
 protected override ODataWriterCore.ResourceScope CreateResourceScope(ODataResource entry, IEdmNavigationSource navigationSource, IEdmStructuredType resourceType, bool skipWriting, SelectedPropertiesNode selectedProperties, ODataUri odataUri, bool isUndeclared)
 {
     throw new NotImplementedException();
 }
예제 #28
0
        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);
        }
예제 #29
0
        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);
        }
예제 #30
0
        /// <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
        }