/// <summary>
            /// Returns the entity set for the given payload element (only for entries and feeds).
            /// </summary>
            /// <param name="expectedTypeAnnotation">The expected type annotation.</param>
            /// <param name="model">The model to get the type from.</param>
            /// <param name="payloadElement">The payload element to get the expected type for.</param>
            /// <returns>The expected type for the specified payload element.</returns>
            private static IEdmEntitySet GetExpectedEntitySet(ExpectedTypeODataPayloadElementAnnotation expectedTypeAnnotation, IEdmModel model, ODataPayloadElement payloadElement)
            {
                ExceptionUtilities.Assert(model != null, "model != null");
                ExceptionUtilities.Assert(payloadElement != null, "payloadElement != null");

                if (payloadElement.GetAnnotation <IgnoreEntitySetAnnotation>() != null)
                {
                    // Entity set information is explicitly ignored
                    return(null);
                }

                if (expectedTypeAnnotation != null)
                {
                    if (expectedTypeAnnotation.EdmEntitySet != null)
                    {
                        return(expectedTypeAnnotation.EdmEntitySet);
                    }
                    EntitySet entitySet = expectedTypeAnnotation.EntitySet;
                    if (entitySet != null)
                    {
                        return(model.EntityContainersAcrossModels().Select(m => m.FindEntitySet(entitySet.Name)).FirstOrDefault(s => s != null));
                    }
                }

                EntityModelTypeAnnotation typeAnnotation = payloadElement.GetAnnotation <EntityModelTypeAnnotation>();

                if (typeAnnotation != null)
                {
                    var edmEntityType = typeAnnotation.EdmModelType;
                    return(model.EntityContainersAcrossModels().First().EntitySets().SingleOrDefault(es => es.EntityType().FullName() == edmEntityType.FullName()));
                }

                return(null);
            }
Пример #2
0
        /// <summary>
        /// Returns the type from the entity model type annotation for this payload element.
        /// </summary>
        /// <param name="payloadElement">The payload element to return the type for.</param>
        /// <returns>The type from the annotation or null if none was present.</returns>
        private static IEdmTypeReference GetEdmTypeFromEntityModelTypeAnnotation(ODataPayloadElement payloadElement)
        {
            Debug.Assert(payloadElement != null, "payloadElement != null");

            EntityModelTypeAnnotation typeAnnotation = payloadElement.GetAnnotation <EntityModelTypeAnnotation>();

            return(typeAnnotation == null ? null : typeAnnotation.EdmModelType);
        }
 private void ReplaceExpectedTypeAnnotationIfRootElement(ODataPayloadElement payloadElement)
 {
     if (this.payloadElementStack.Count == 2)
     {
         var expectedTypeAnnotation = payloadElement.GetAnnotation <ExpectedTypeODataPayloadElementAnnotation>();
         if (expectedTypeAnnotation != null)
         {
             payloadElement.WithContextUri(JsonLightODataPayloadElementExtensions.BuildContextUri(payloadElement.ElementType, JsonLightConstants.DefaultMetadataDocumentUri.OriginalString, expectedTypeAnnotation));
             payloadElement.RemoveAnnotations(typeof(ExpectedTypeODataPayloadElementAnnotation));
         }
     }
 }
        /// <summary>
        /// Gets or adds the expected type annotation.
        /// </summary>
        /// <param name="payloadElement">The payload element to get or add the annotation to.</param>
        /// <returns>The expected type annotation to use.</returns>
        public static ExpectedTypeODataPayloadElementAnnotation AddExpectedTypeAnnotation(this ODataPayloadElement payloadElement)
        {
            Debug.Assert(payloadElement != null, "payloadElement != null");

            var expectedTypeAnnotation = payloadElement.GetAnnotation <ExpectedTypeODataPayloadElementAnnotation>();

            if (expectedTypeAnnotation == null)
            {
                expectedTypeAnnotation = new ExpectedTypeODataPayloadElementAnnotation();
                payloadElement.SetAnnotation(expectedTypeAnnotation);
            }

            return(expectedTypeAnnotation);
        }
        /// <summary>
        /// Gets or adds the expected type annotation.
        /// </summary>
        /// <param name="payloadElement">The payload element to get or add the annotation to.</param>
        /// <returns>The expected type annotation to use.</returns>
        public static ExpectedTypeODataPayloadElementAnnotation AddExpectedTypeAnnotation(this ODataPayloadElement payloadElement, IEdmType expectedType)
        {
            Debug.Assert(payloadElement != null, "payloadElement != null");

            var expectedTypeAnnotation = payloadElement.GetAnnotation <ExpectedTypeODataPayloadElementAnnotation>();

            if (expectedTypeAnnotation == null)
            {
                expectedTypeAnnotation = new ExpectedTypeODataPayloadElementAnnotation();
                payloadElement.SetAnnotation(expectedTypeAnnotation);
            }

            expectedTypeAnnotation.EdmExpectedType = expectedType.ToTypeReference();
            return(expectedTypeAnnotation);
        }
Пример #6
0
        /// <summary>
        /// Gets the custom content type header for the payload element (if specified).
        /// </summary>
        /// <param name="payloadElement">The payload element to get the custom content type header for.</param>
        /// <returns>The custom content types header or null if none is specified.</returns>
        public static string GetCustomContentTypeHeader(this ODataPayloadElement payloadElement)
        {
            if (payloadElement == null)
            {
                return(null);
            }

            CustomContentTypeHeaderAnnotation contentTypeAnnotation = payloadElement.GetAnnotation <CustomContentTypeHeaderAnnotation>();

            if (contentTypeAnnotation != null)
            {
                return(contentTypeAnnotation.ContentType);
            }

            BatchBoundaryAnnotation batchBoundaryAnnotation = payloadElement.GetAnnotation <BatchBoundaryAnnotation>();

            if (batchBoundaryAnnotation != null)
            {
                Debug.Assert(batchBoundaryAnnotation.BatchBoundaryInHeader != null, "If an annotation is found the boundary must not be null.");
                return(MimeTypes.MultipartMixed + "; boundary=" + batchBoundaryAnnotation.BatchBoundaryInHeader);
            }

            return(null);
        }
Пример #7
0
        /// <summary>
        /// Annotates the <paramref name="payloadElement"/> with the format version if it's not already annotated.
        /// </summary>
        /// <param name="payloadElement">The payload element to annotate.</param>
        private void AddVersionAnnotation(ODataPayloadElement payloadElement)
        {
            PayloadFormatVersionAnnotation versionAnnotation =
                (PayloadFormatVersionAnnotation)payloadElement.GetAnnotation(typeof(PayloadFormatVersionAnnotation));

            if (versionAnnotation == null)
            {
                versionAnnotation = new PayloadFormatVersionAnnotation()
                {
                    Version  = this.version,
                    Response = !this.requestPayload,
                };

                payloadElement.AddAnnotation(versionAnnotation);
            }
        }
Пример #8
0
        /// <summary>
        /// Gets the <see cref="EntityType"/> of the specified entry or feed payload element.
        /// </summary>
        /// <param name="payloadElement">The payload element to get the entity type for.</param>
        /// <param name="model">The model to find the entity type in.</param>
        /// <returns>The <see cref="EntityType"/> of the <paramref name="payloadElement"/>.</returns>
        public static IEdmEntityType GetPayloadElementEntityType(ODataPayloadElement payloadElement, IEdmModel model)
        {
            ExceptionUtilities.CheckArgumentNotNull(payloadElement, "payloadElement");
            ExceptionUtilities.CheckArgumentNotNull(model, "model");

            ODataPayloadKind payloadKind = payloadElement.GetPayloadKindFromPayloadElement();

            ExceptionUtilities.Assert(
                payloadKind == ODataPayloadKind.Resource || payloadKind == ODataPayloadKind.ResourceSet,
                "Can only determine entity type for entry or feed payloads.");

            EntityModelTypeAnnotation typeAnnotation = payloadElement.GetAnnotation <EntityModelTypeAnnotation>();

            if (typeAnnotation != null)
            {
                var entityDataType = typeAnnotation.EdmModelType;
                Debug.Assert(entityDataType != null, "entityDataType != null");
                return(model.EntityTypes().Single(et => et.FullName() == entityDataType.FullName()));
            }

            string entityTypeName;

            if (payloadKind == ODataPayloadKind.Resource)
            {
                EntityInstance entity = payloadElement as EntityInstance;
                Debug.Assert(entity != null, "entity != null");
                entityTypeName = entity.FullTypeName;
                return(model.EntityTypes().Single(et => et.TestFullName() == entityTypeName));
            }
            else
            {
                //if feed has entries figure out type otherwise use first entity type
                EntitySetInstance feed = payloadElement as EntitySetInstance;
                Debug.Assert(feed != null, "feed != null");
                if (feed.Count > 0)
                {
                    return(model.EntityTypes().Single(et => et.TestFullName() == ((TypedValue)feed.First()).FullTypeName));
                }
                else
                {
                    return(model.EntityTypes().First());
                }
            }
        }
Пример #9
0
        public byte[] SerializeToBinary(ODataPayloadElement rootElement, string encodingName)
        {
            bool omitDeclaration = false;

            SerializationEncodingNameAnnotation encodingNameAnnotation = (SerializationEncodingNameAnnotation)rootElement.GetAnnotation(typeof(SerializationEncodingNameAnnotation));
            if (encodingNameAnnotation != null)
            {
                encodingName = encodingNameAnnotation.EncodingName;
                omitDeclaration = encodingNameAnnotation.OmitDeclaration;
            }

            var encoding = HttpUtilities.GetEncodingOrDefault(encodingName);

            XDocument document = new XDocument(this.payloadElementConverter.ConvertToXml(rootElement));

            if (!omitDeclaration)
            {
                document.Declaration = new XDeclaration("1.0", encoding.WebName, "yes");
            }

            // settings taken from server
            XmlWriterSettings settings = new XmlWriterSettings();
            settings.Encoding = encoding;
            settings.OmitXmlDeclaration = omitDeclaration;
            settings.Indent = true;
            settings.NewLineHandling = NewLineHandling.Entitize;
            settings.NamespaceHandling = NamespaceHandling.OmitDuplicates;

            using (MemoryStream stream = new MemoryStream())
            {
                using (XmlWriter writer = XmlWriter.Create(stream, settings))
                {
                    document.Save(writer);
                    writer.Flush();

                    return stream.ToArray();
                }
            }
        }
 private void ReplaceExpectedTypeAnnotationIfRootElement(ODataPayloadElement payloadElement)
 {
     if (this.payloadElementStack.Count == 2)
     {
         var expectedTypeAnnotation = payloadElement.GetAnnotation<ExpectedTypeODataPayloadElementAnnotation>();
         if (expectedTypeAnnotation != null)
         {
             payloadElement.WithContextUri(JsonLightODataPayloadElementExtensions.BuildContextUri(payloadElement.ElementType, JsonLightConstants.DefaultMetadataDocumentUri.OriginalString, expectedTypeAnnotation));
             payloadElement.RemoveAnnotations(typeof(ExpectedTypeODataPayloadElementAnnotation));
         }
     }
 }
            /// <summary>
            /// Constructor
            /// </summary>
            /// <param name="model">The model used to resolve the metadata.</param>
            /// <param name="payloadElement">The payload element to get the reader metadata for.</param>
            public ReaderMetadata(IEdmModel model, ODataPayloadElement payloadElement)
            {
                var expectedTypeAnnotation = payloadElement.GetAnnotation <ExpectedTypeODataPayloadElementAnnotation>();

                // NOTE: we don't require a model for the computation of the expected type (since the expected one might be a primitive type).
                this.expectedType = GetExpectedType(expectedTypeAnnotation, model);

                // We need a model for all the other expected reader metadata
                if (model == null)
                {
                    // If the annotation specified some model dependent data (basically anything but primitive expected type)
                    // and we don't have a model, we wouldn't be able to correctly represent it here (since we need the model to resolve these)
                    // and thus we should not pass in the expected type alone, as that would be changing the intent of the annotation.
                    if (expectedTypeAnnotation != null &&
                        (expectedTypeAnnotation.EntitySet != null ||
                         expectedTypeAnnotation.EdmEntitySet != null ||
                         expectedTypeAnnotation.FunctionImport != null ||
                         expectedTypeAnnotation.ProductFunctionImport != null ||
                         expectedTypeAnnotation.MemberProperty != null ||
                         expectedTypeAnnotation.EdmProperty != null ||
                         expectedTypeAnnotation.NavigationProperty != null ||
                         expectedTypeAnnotation.EdmNavigationProperty != null ||
                         expectedTypeAnnotation.OpenMemberPropertyName != null ||
                         expectedTypeAnnotation.OwningType != null ||
                         expectedTypeAnnotation.EdmOwningType != null))
                    {
                        this.expectedType = null;
                    }

                    return;
                }

                ODataPayloadElementType elementType = payloadElement.ElementType;

                switch (elementType)
                {
                case ODataPayloadElementType.EntityInstance:        // fall through
                case ODataPayloadElementType.EntitySetInstance:
                    this.entitySet = GetExpectedEntitySet(expectedTypeAnnotation, model, payloadElement);
                    break;

                case ODataPayloadElementType.DeferredLink:          // fall through
                case ODataPayloadElementType.LinkCollection:
                    this.navigationProperty = GetExpectedNavigationProperty(expectedTypeAnnotation, model);
                    break;

                case ODataPayloadElementType.PrimitiveMultiValueProperty:       // fall through
                case ODataPayloadElementType.PrimitiveProperty:                 // fall through
                case ODataPayloadElementType.ComplexProperty:                   // fall through
                case ODataPayloadElementType.ComplexMultiValueProperty:         // fall through
                case ODataPayloadElementType.EmptyCollectionProperty:
                    this.structuralProperty = GetExpectedStructuralProperty(expectedTypeAnnotation, model);
                    this.functionImport     = GetExpectedFunctionImport(expectedTypeAnnotation, model);
                    break;

                case ODataPayloadElementType.ComplexInstanceCollection:         // fall through
                case ODataPayloadElementType.PrimitiveCollection:               // fall through
                case ODataPayloadElementType.EmptyUntypedCollection:
                    this.functionImport = GetExpectedFunctionImport(expectedTypeAnnotation, model);
                    break;

                case ODataPayloadElementType.ComplexInstance:
                    // NOTE: this is how we model parameter payloads
                    this.functionImport = GetExpectedFunctionImport(expectedTypeAnnotation, model);
                    break;
                }
            }
        public void EntryPayloadOrderTest()
        {
            IEnumerable <PayloadReaderTestDescriptor> testDescriptors = new[]
            {
                // Nothing
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    PayloadElement = PayloadBuilder.Entity()
                                     .XmlRepresentation("<entry></entry>")
                                     .PayloadOrderItems("__StartEntry__")
                },
                // Just type name after nav. link - type name should be reported first.
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    PayloadElement = PayloadBuilder.Entity("MyType").NavigationProperty("Category", "http://odata.org/Category")
                                     .XmlRepresentation(
                        "<entry>" +
                        "<link rel='http://docs.oasis-open.org/odata/ns/related/Category' type='application/atom+xml;type=entry' href='http://odata.org/Category'/>" +
                        "<category term='MyType' scheme='http://docs.oasis-open.org/odata/ns/scheme'/>" +
                        "</entry>")
                                     .PayloadOrderItems(
                        "TypeName",
                        "__StartEntry__",
                        "NavigationLink_Category")
                },
                // Type name properties and other things after link - type name and etag should be reported first, the rest after the link
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    PayloadElement = PayloadBuilder.Entity("MyType")
                                     .ETag("bar")
                                     .NavigationProperty("Category", "http://odata.org/Category")
                                     .WithSelfLink("http://odata.org")
                                     .PrimitiveProperty("Name", "Foo")
                                     .XmlRepresentation(
                        "<entry m:etag='bar'>" +
                        "<link rel='http://docs.oasis-open.org/odata/ns/related/Category' type='application/atom+xml;type=entry' href='http://odata.org/Category'/>" +
                        "<category term='MyType' scheme='http://docs.oasis-open.org/odata/ns/scheme'/>" +
                        "<content type='application/xml'><m:properties><d:Name>Foo</d:Name></m:properties></content>" +
                        "<link rel='self' href='http://odata.org'/>" +
                        "</entry>")
                                     .PayloadOrderItems(
                        "TypeName",
                        "ETag",
                        "__StartEntry__",
                        "NavigationLink_Category",
                        "ReadLink",
                        "Property_Name"),
                    // [Astoria-ODataLib-Integration] Parsing of URLs on OData recognized places may fail, but Astoria server doesn't
                    SkipTestConfiguration = config => config.RunBehaviorKind == TestODataBehaviorKind.WcfDataServicesServer
                },
                // Everything before nav. link
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    PayloadElement = PayloadBuilder.Entity("MyType")
                                     .ETag("bar")
                                     .PrimitiveProperty("Name", "Foo")
                                     .NavigationProperty("Category", "http://odata.org/Category")
                                     .WithSelfLink("http://odata.org")
                                     .OperationDescriptor(new ServiceOperationDescriptor()
                    {
                        IsAction = true, Metadata = "/actionMetadata", Target = "http://odata.org/action"
                    })
                                     .OperationDescriptor(new ServiceOperationDescriptor()
                    {
                        IsFunction = true, Metadata = "/functionMetadata", Target = "http://odata.org/function"
                    })
                                     .XmlRepresentation(
                        "<entry m:etag='bar'>" +
                        "<category term='MyType' scheme='http://docs.oasis-open.org/odata/ns/scheme'/>" +
                        "<content type='application/xml'><m:properties><d:Name>Foo</d:Name></m:properties></content>" +
                        "<link rel='self' href='http://odata.org'/>" +
                        "<m:action metadata='/actionMetadata' target='http://odata.org/action'/>" +
                        "<m:function metadata='/functionMetadata' target='http://odata.org/function'/>" +
                        "<link rel='http://docs.oasis-open.org/odata/ns/relatedlinks/PoliceStation' href='http://odata.org/associationlink' type='application/xml'/>" +
                        "<link rel='http://docs.oasis-open.org/odata/ns/related/Category' type='application/atom+xml;type=entry' href='http://odata.org/Category'/>" +
                        "</entry>")
                                     .PayloadOrderItems(
                        "TypeName",
                        "ReadLink",
                        "ETag",
                        "Action_/actionMetadata",
                        "Function_/functionMetadata",
                        "Property_Name",
                        "__StartEntry__",
                        "NavigationLink_Category"),
                    // [Astoria-ODataLib-Integration] Parsing of URLs on OData recognized places may fail, but Astoria server doesn't
                    SkipTestConfiguration = config => config.RunBehaviorKind == TestODataBehaviorKind.WcfDataServicesServer || config.IsRequest
                },
                // Everything before nav. link - Server behavior - server ignores most of links
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    PayloadElement = PayloadBuilder.Entity("MyType")
                                     .ETag("bar")
                                     .PrimitiveProperty("Name", "Foo")
                                     .NavigationProperty("Category", "http://odata.org/Category")
                                     .OperationDescriptor(new ServiceOperationDescriptor()
                    {
                        IsAction = true, Metadata = "/actionMetadata", Target = "http://odata.org/action"
                    })
                                     .OperationDescriptor(new ServiceOperationDescriptor()
                    {
                        IsFunction = true, Metadata = "/functionMetadata", Target = "http://odata.org/function"
                    })
                                     .XmlRepresentation(
                        "<entry m:etag='bar'>" +
                        "<category term='MyType' scheme='http://docs.oasis-open.org/odata/ns/scheme'/>" +
                        "<content type='application/xml'><m:properties><d:Name>Foo</d:Name></m:properties></content>" +
                        "<link rel='self' href='http://odata.org'/>" +
                        "<m:action metadata='/actionMetadata' target='http://odata.org/action'/>" +
                        "<m:function metadata='/functionMetadata' target='http://odata.org/function'/>" +
                        "<link rel='http://docs.oasis-open.org/odata/ns/relatedlinks/PoliceStation' href='http://odata.org/associationlink' type='application/xml'/>" +
                        "<link rel='http://docs.oasis-open.org/odata/ns/related/Category' type='application/atom+xml;type=entry' href='http://odata.org/Category'/>" +
                        "</entry>")
                                     .PayloadOrderItems(
                        "TypeName",
                        "ETag",
                        "Action_/actionMetadata",
                        "Function_/functionMetadata",
                        "Property_Name",
                        "__StartEntry__",
                        "NavigationLink_Category"),
                    SkipTestConfiguration = config => config.RunBehaviorKind != TestODataBehaviorKind.WcfDataServicesServer || config.IsRequest
                },
                // Everything between nav. links
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    PayloadElement = PayloadBuilder.Entity("MyType")
                                     .ETag("bar")
                                     .NavigationProperty("Order", "http://odata.org/Order")
                                     .PrimitiveProperty("Name", "Foo")
                                     .NavigationProperty("Category", "http://odata.org/Category")
                                     .WithSelfLink("http://odata.org")
                                     .OperationDescriptor(new ServiceOperationDescriptor()
                    {
                        IsAction = true, Metadata = "/actionMetadata", Target = "http://odata.org/action"
                    })
                                     .OperationDescriptor(new ServiceOperationDescriptor()
                    {
                        IsFunction = true, Metadata = "/functionMetadata", Target = "http://odata.org/function"
                    })
                                     .XmlRepresentation(
                        "<entry m:etag='bar'>" +
                        "<link rel='http://docs.oasis-open.org/odata/ns/related/Order' type='application/atom+xml;type=entry' href='http://odata.org/Order'/>" +
                        "<category term='MyType' scheme='http://docs.oasis-open.org/odata/ns/scheme'/>" +
                        "<content type='application/xml'><m:properties><d:Name>Foo</d:Name></m:properties></content>" +
                        "<link rel='self' href='http://odata.org'/>" +
                        "<m:action metadata='/actionMetadata' target='http://odata.org/action'/>" +
                        "<m:function metadata='/functionMetadata' target='http://odata.org/function'/>" +
                        "<link rel='http://docs.oasis-open.org/odata/ns/relatedlinks/PoliceStation' href='http://odata.org/associationlink' type='application/xml'/>" +
                        "<link rel='http://docs.oasis-open.org/odata/ns/related/Category' type='application/atom+xml;type=entry' href='http://odata.org/Category'/>" +
                        "</entry>")
                                     .PayloadOrderItems(
                        "TypeName",
                        "ETag",
                        "__StartEntry__",
                        "NavigationLink_Order",
                        "ReadLink",
                        "Action_/actionMetadata",
                        "Function_/functionMetadata",
                        "Property_Name",
                        "NavigationLink_Category"),
                    // [Astoria-ODataLib-Integration] Parsing of URLs on OData recognized places may fail, but Astoria server doesn't
                    SkipTestConfiguration = config => config.RunBehaviorKind == TestODataBehaviorKind.WcfDataServicesServer || config.IsRequest
                },
                // Everything between nav. links - server behavior
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    PayloadElement = PayloadBuilder.Entity("MyType")
                                     .ETag("bar")
                                     .NavigationProperty("Order", "http://odata.org/Order")
                                     .PrimitiveProperty("Name", "Foo")
                                     .NavigationProperty("Category", "http://odata.org/Category")
                                     .OperationDescriptor(new ServiceOperationDescriptor()
                    {
                        IsAction = true, Metadata = "/actionMetadata", Target = "http://odata.org/action"
                    })
                                     .OperationDescriptor(new ServiceOperationDescriptor()
                    {
                        IsFunction = true, Metadata = "/functionMetadata", Target = "http://odata.org/function"
                    })
                                     .XmlRepresentation(
                        "<entry m:etag='bar'>" +
                        "<link rel='http://docs.oasis-open.org/odata/ns/related/Order' type='application/atom+xml;type=entry' href='http://odata.org/Order'/>" +
                        "<category term='MyType' scheme='http://docs.oasis-open.org/odata/ns/scheme'/>" +
                        "<content type='application/xml'><m:properties><d:Name>Foo</d:Name></m:properties></content>" +
                        "<link rel='self' href='http://odata.org'/>" +
                        "<m:action metadata='/actionMetadata' target='http://odata.org/action'/>" +
                        "<m:function metadata='/functionMetadata' target='http://odata.org/function'/>" +
                        "<link rel='http://docs.oasis-open.org/odata/ns/relatedlinks/PoliceStation' href='http://odata.org/associationlink' type='application/xml'/>" +
                        "<link rel='http://docs.oasis-open.org/odata/ns/related/Category' type='application/atom+xml;type=entry' href='http://odata.org/Category'/>" +
                        "</entry>")
                                     .PayloadOrderItems(
                        "TypeName",
                        "ETag",
                        "__StartEntry__",
                        "NavigationLink_Order",
                        "Action_/actionMetadata",
                        "Function_/functionMetadata",
                        "Property_Name",
                        "NavigationLink_Category"),
                    SkipTestConfiguration = config => config.RunBehaviorKind != TestODataBehaviorKind.WcfDataServicesServer || config.IsRequest
                },
                // EPM
                //new PayloadReaderTestDescriptor(this.Settings)
                //{
                //    PayloadElement = PayloadBuilder.Entity("TestModel.EpmEntity")
                //        .NavigationProperty("Order", "http://odata.org/Order")
                //        .PrimitiveProperty("Name", "Foo")
                //        .NavigationProperty("Orders", "http://odata.org/Orders")
                //        .PrimitiveProperty("Description", "Bart")
                //        .XmlRepresentation(
                //            "<entry>" +
                //                "<link rel='http://docs.oasis-open.org/odata/ns/related/Order' type='application/atom+xml;type=entry' href='http://odata.org/Order'/>" +
                //                "<category term='TestModel.EpmEntity' scheme='http://docs.oasis-open.org/odata/ns/scheme'/>" +
                //                "<content type='application/xml'><m:properties><d:Name>Foo</d:Name></m:properties></content>" +
                //                "<link rel='http://docs.oasis-open.org/odata/ns/related/Orders' type='application/atom+xml;type=feed' href='http://odata.org/Orders'/>" +
                //                "<author><name>Bart</name></author>" +
                //            "</entry>")
                //        .PayloadOrderItems(
                //            "TypeName",
                //            "__StartEntry__",
                //            "NavigationLink_Order",
                //            "Property_Name",
                //            "NavigationLink_Orders",
                //            "Property_Description"),
                //    PayloadModel = model
                //}
            };

            this.CombinatorialEngineProvider.RunCombinations(
                testDescriptors,
                this.ReaderTestConfigurationProvider.AtomFormatConfigurations,
                TestReaderUtils.ODataBehaviorKinds,
                (testDescriptor, testConfiguration, behavior) =>
            {
                // In WCF DS Server mode the reader reports the StartEntry as soon as it finds a type name.
                //   Since the ETag is always on the start element it will be reported in StartEntry as well.
                if (behavior == TestODataBehaviorKind.WcfDataServicesServer)
                {
                    ODataPayloadElement element = testDescriptor.PayloadElement.DeepCopy();
                    PayloadOrderODataPayloadElementAnnotation payloadOrderAnnotation = element.GetAnnotation <PayloadOrderODataPayloadElementAnnotation>();
                    int startEntryPosition = 0;
                    if (payloadOrderAnnotation.PayloadItems[0] == "TypeName")
                    {
                        startEntryPosition++;
                    }

                    if (payloadOrderAnnotation.PayloadItems.Contains("ETag"))
                    {
                        payloadOrderAnnotation.PayloadItems.Remove("ETag");
                        payloadOrderAnnotation.PayloadItems.Insert(1, "ETag");
                        startEntryPosition++;
                    }

                    payloadOrderAnnotation.PayloadItems.Remove("__StartEntry__");
                    payloadOrderAnnotation.PayloadItems.Insert(startEntryPosition, "__StartEntry__");

                    testDescriptor = new PayloadReaderTestDescriptor(testDescriptor)
                    {
                        PayloadElement = element
                    };
                }

                // We must remove any payload normalizers since we are now supersensitive to ordering issues in this test.
                testDescriptor.ExpectedResultNormalizers.Clear();
                testDescriptor.RunTest(testConfiguration.CloneAndApplyBehavior(behavior));
            });
        }
 /// <summary>
 /// Returns annotation of a payload element.
 /// </summary>
 /// <typeparam name="T">The type of the annotation to get.</typeparam>
 /// <param name="payloadElement">The payload element to get the annotation from.</param>
 /// <returns>The annotation or null if none was found.</returns>
 public static T GetAnnotation <T>(this ODataPayloadElement payloadElement) where T : ODataPayloadElementAnnotation
 {
     ExceptionUtilities.CheckArgumentNotNull(payloadElement, "payloadElement");
     return((T)payloadElement.GetAnnotation(typeof(T)));
 }
Пример #14
0
        /// <summary>
        /// Builds a complex instance from the given payloadElements to represent a parameters payload.
        /// </summary>
        /// <param name="payloadElements">Each ODataPayloadElement represents the value for each parameter.</param>
        /// <param name="model">EdmModel instance.</param>
        /// <param name="functionImportName">Name of the function import to add to the model.</param>
        /// <returns></returns>
        private static ComplexInstance PayloadElementsToParameterPayload(ODataPayloadElement[] payloadElements, EdmModel model, string functionImportName)
        {
            EdmOperationImport operationImport = (EdmOperationImport)model.EntityContainer.FindOperationImports(functionImportName).FirstOrDefault();
            EdmOperation       operation       = (EdmOperation)operationImport.Operation;

            var parameterPayload = new ComplexInstance(null, false);

            for (int idx = 0; idx < payloadElements.Length; idx++)
            {
                ODataPayloadElement p           = payloadElements[idx];
                string            parameterName = "p" + idx;
                PropertyInstance  parameter;
                IEdmTypeReference entityModelType = p.GetAnnotation <EntityModelTypeAnnotation>().EdmModelType;
                switch (p.ElementType)
                {
                case ODataPayloadElementType.PrimitiveValue:
                    object         clrValue       = ((PrimitiveValue)p).ClrValue;
                    PrimitiveValue primitiveValue = new PrimitiveValue(clrValue == null ? null : clrValue.GetType().FullName, clrValue);
                    primitiveValue.CopyAnnotation <PrimitiveValue, EntityModelTypeAnnotation>(p);
                    parameter = new PrimitiveProperty(parameterName, primitiveValue);
                    operation.AddParameter(parameterName, MetadataUtils.GetPrimitiveTypeReference(primitiveValue.ClrValue.GetType()));
                    break;

                case ODataPayloadElementType.ComplexInstance:
                    parameter = new ComplexProperty(parameterName, (ComplexInstance)p);
                    operation.AddParameter(parameterName, entityModelType);
                    break;

                case ODataPayloadElementType.PrimitiveMultiValue:
                    PrimitiveMultiValue primitiveMultiValue = (PrimitiveMultiValue)p;
                    if (primitiveMultiValue.Annotations.OfType <JsonCollectionResultWrapperAnnotation>().SingleOrDefault() == null)
                    {
                        primitiveMultiValue.Annotations.Add(new JsonCollectionResultWrapperAnnotation(false));
                    }

                    parameter = new PrimitiveMultiValueProperty(parameterName, primitiveMultiValue);
                    operation.AddParameter(parameterName, entityModelType);
                    break;

                case ODataPayloadElementType.ComplexMultiValue:
                    ComplexMultiValue complexMultiValue = (ComplexMultiValue)p;
                    if (complexMultiValue.Annotations.OfType <JsonCollectionResultWrapperAnnotation>().SingleOrDefault() == null)
                    {
                        complexMultiValue.Annotations.Add(new JsonCollectionResultWrapperAnnotation(false));
                    }

                    parameter = new ComplexMultiValueProperty(parameterName, complexMultiValue);
                    operation.AddParameter(parameterName, entityModelType);
                    break;

                case ODataPayloadElementType.EntityInstance:
                    parameter = new NavigationPropertyInstance(parameterName, (EntityInstance)p);
                    operation.AddParameter(parameterName, entityModelType);
                    break;

                case ODataPayloadElementType.EntitySetInstance:
                    parameter = new NavigationPropertyInstance(parameterName, (EntitySetInstance)p);
                    operation.AddParameter(parameterName, entityModelType);
                    break;

                default:
                    throw new NotSupportedException("PayloadElementsToParameterPayload() is called on unsupported ODataPayloadElement type: " + p.ElementType);
                }

                parameterPayload.Add(parameter);
            }

            parameterPayload.ExpectedFunctionImport(operationImport);
            return(parameterPayload);
        }
            /// <summary>
            /// Returns the entity set for the given payload element (only for entries and feeds).
            /// </summary>
            /// <param name="expectedTypeAnnotation">The expected type annotation.</param>
            /// <param name="model">The model to get the type from.</param>
            /// <param name="payloadElement">The payload element to get the expected type for.</param>
            /// <returns>The expected type for the specified payload element.</returns>
            private static IEdmEntitySet GetExpectedEntitySet(ExpectedTypeODataPayloadElementAnnotation expectedTypeAnnotation, IEdmModel model, ODataPayloadElement payloadElement)
            {
                ExceptionUtilities.Assert(model != null, "model != null");
                ExceptionUtilities.Assert(payloadElement != null, "payloadElement != null");

                if (payloadElement.GetAnnotation<IgnoreEntitySetAnnotation>() != null)
                {
                    // Entity set information is explicitly ignored
                    return null;
                }

                if (expectedTypeAnnotation != null)
                {
                    if (expectedTypeAnnotation.EdmEntitySet != null)
                    {
                        return expectedTypeAnnotation.EdmEntitySet;
                    }
                    EntitySet entitySet = expectedTypeAnnotation.EntitySet;
                    if (entitySet != null)
                    {
                        return model.EntityContainersAcrossModels().Select(m => m.FindEntitySet(entitySet.Name)).FirstOrDefault(s => s != null);
                    }
                }

                EntityModelTypeAnnotation typeAnnotation = payloadElement.GetAnnotation<EntityModelTypeAnnotation>();
                if (typeAnnotation != null)
                {
                    var edmEntityType = typeAnnotation.EdmModelType;
                    return model.EntityContainersAcrossModels().First().EntitySets().SingleOrDefault(es => es.EntityType().FullName() == edmEntityType.FullName());
                }

                return null;
            }
            /// <summary>
            /// Constructor
            /// </summary>
            /// <param name="model">The model used to resolve the metadata.</param>
            /// <param name="payloadElement">The payload element to get the reader metadata for.</param>
            public ReaderMetadata(IEdmModel model, ODataPayloadElement payloadElement)
            {
                var expectedTypeAnnotation = payloadElement.GetAnnotation<ExpectedTypeODataPayloadElementAnnotation>();

                // NOTE: we don't require a model for the computation of the expected type (since the expected one might be a primitive type).
                this.expectedType = GetExpectedType(expectedTypeAnnotation, model);

                // We need a model for all the other expected reader metadata
                if (model == null)
                {
                    // If the annotation specified some model dependent data (basically anything but primitive expected type)
                    // and we don't have a model, we wouldn't be able to correctly represent it here (since we need the model to resolve these)
                    // and thus we should not pass in the expected type alone, as that would be changing the intent of the annotation.
                    if (expectedTypeAnnotation != null &&
                        (expectedTypeAnnotation.EntitySet != null ||
                         expectedTypeAnnotation.EdmEntitySet != null ||
                         expectedTypeAnnotation.FunctionImport != null ||
                         expectedTypeAnnotation.ProductFunctionImport != null ||
                         expectedTypeAnnotation.MemberProperty != null ||
                         expectedTypeAnnotation.EdmProperty != null ||
                         expectedTypeAnnotation.NavigationProperty != null ||
                         expectedTypeAnnotation.EdmNavigationProperty != null ||
                         expectedTypeAnnotation.OpenMemberPropertyName != null ||
                         expectedTypeAnnotation.OwningType != null ||
                         expectedTypeAnnotation.EdmOwningType != null))
                    {
                        this.expectedType = null;
                    }

                    return;
                }

                ODataPayloadElementType elementType = payloadElement.ElementType;
                switch (elementType)
                {
                    case ODataPayloadElementType.EntityInstance:    // fall through
                    case ODataPayloadElementType.EntitySetInstance:
                        this.entitySet = GetExpectedEntitySet(expectedTypeAnnotation, model, payloadElement);
                        break;

                    case ODataPayloadElementType.DeferredLink:      // fall through
                    case ODataPayloadElementType.LinkCollection:
                        this.navigationProperty = GetExpectedNavigationProperty(expectedTypeAnnotation, model);
                        break;

                    case ODataPayloadElementType.PrimitiveMultiValueProperty:   // fall through
                    case ODataPayloadElementType.PrimitiveProperty:             // fall through
                    case ODataPayloadElementType.ComplexProperty:               // fall through
                    case ODataPayloadElementType.ComplexMultiValueProperty:     // fall through
                    case ODataPayloadElementType.EmptyCollectionProperty:
                        this.structuralProperty = GetExpectedStructuralProperty(expectedTypeAnnotation, model);
                        this.functionImport = GetExpectedFunctionImport(expectedTypeAnnotation, model);
                        break;

                    case ODataPayloadElementType.ComplexInstanceCollection:     // fall through
                    case ODataPayloadElementType.PrimitiveCollection:           // fall through
                    case ODataPayloadElementType.EmptyUntypedCollection:
                        this.functionImport = GetExpectedFunctionImport(expectedTypeAnnotation, model);
                        break;

                    case ODataPayloadElementType.ComplexInstance:
                        // NOTE: this is how we model parameter payloads
                        this.functionImport = GetExpectedFunctionImport(expectedTypeAnnotation, model);
                        break;
                }
            }
        /// <summary>
        /// Gets the context URI for the specified ODataPayloadElement.
        /// </summary>
        /// <param name="payloadElement">The annotated payload element to get the context URI for.</param>
        /// <returns>The context URI from the annotated payload element or null if no context URI annotation exists.</returns>
        /// <remarks>If not context URI annotation is found on the <paramref name="payloadElement"/>, this
        /// method will try to compute the context URI from the expected type annotation. If successful,
        /// it will cache the computed context URI as annotation on the payload element.</remarks>
        public static string ContextUri(this ODataPayloadElement payloadElement)
        {
            ExceptionUtilities.CheckArgumentNotNull(payloadElement, "payloadElement");
            JsonLightContextUriAnnotation contextUriAnnotation = (JsonLightContextUriAnnotation)payloadElement.GetAnnotation(typeof(JsonLightContextUriAnnotation));

            string contextUri      = null;
            bool   cacheContextUri = false;

            // If an explicit context URI exists, return it
            if (contextUriAnnotation != null)
            {
                contextUri = contextUriAnnotation.ContextUri;
            }
            else
            {
                // Otherwise construct a context URI from the expected type annotation
                ExpectedTypeODataPayloadElementAnnotation expectedTypeAnnotation =
                    (ExpectedTypeODataPayloadElementAnnotation)payloadElement.GetAnnotation(typeof(ExpectedTypeODataPayloadElementAnnotation));
                if (expectedTypeAnnotation != null)
                {
                    // Construct a context URI from the exptected type annotation
                    JsonLightMetadataDocumentUriAnnotation metadataDocumentUriAnnotation =
                        (JsonLightMetadataDocumentUriAnnotation)payloadElement.GetAnnotation(typeof(JsonLightMetadataDocumentUriAnnotation));
                    string metadataDocumentUri = metadataDocumentUriAnnotation == null
                        ? JsonLightConstants.DefaultMetadataDocumentUri.AbsoluteUri
                        : metadataDocumentUriAnnotation.MetadataDocumentUri;

                    string projectionString = null;
                    JsonLightContextUriProjectionAnnotation contextUriProjectionAnnotation = (JsonLightContextUriProjectionAnnotation)payloadElement.GetAnnotation(typeof(JsonLightContextUriProjectionAnnotation));
                    if (contextUriProjectionAnnotation != null)
                    {
                        // If we have a context URI projection, apply it to the context URI if the context URI does not already have one.
                        projectionString = contextUriProjectionAnnotation.ContextUriProjection;
                        Regex contextUriSelectExpandPattern = new Regex(@"(?:(?<!#Collection))\(.*\)");

                        // A 'null' projection string means that all properties should be projected.
                        if (projectionString != null)
                        {
                            bool hasProjection = contextUriSelectExpandPattern.IsMatch(projectionString);
                            if (!hasProjection)
                            {
                                // Inject the projection string into the context URI
                                projectionString = JsonLightConstants.ContextUriProjectionStart + projectionString + JsonLightConstants.ContextUriProjectionEnd;
                            }
                        }
                    }

                    contextUri      = BuildContextUri(payloadElement.ElementType, metadataDocumentUri, expectedTypeAnnotation, projectionString);
                    cacheContextUri = true;
                }
            }

            // Cache the computed context URI on the payload element (non-comparable annotation)
            if (cacheContextUri)
            {
                payloadElement.WithContextUri(contextUri);
                payloadElement.RemoveAnnotations(typeof(JsonLightContextUriProjectionAnnotation));
            }

            return(contextUri);
        }
Пример #18
0
        public byte[] SerializeToBinary(ODataPayloadElement rootElement, string encodingName)
        {
            bool omitDeclaration = false;

            SerializationEncodingNameAnnotation encodingNameAnnotation = (SerializationEncodingNameAnnotation)rootElement.GetAnnotation(typeof(SerializationEncodingNameAnnotation));

            if (encodingNameAnnotation != null)
            {
                encodingName    = encodingNameAnnotation.EncodingName;
                omitDeclaration = encodingNameAnnotation.OmitDeclaration;
            }

            var encoding = HttpUtilities.GetEncodingOrDefault(encodingName);

            XDocument document = new XDocument(this.payloadElementConverter.ConvertToXml(rootElement));

            if (!omitDeclaration)
            {
                document.Declaration = new XDeclaration("1.0", encoding.WebName, "yes");
            }

            // settings taken from server
            XmlWriterSettings settings = new XmlWriterSettings();

            settings.Encoding           = encoding;
            settings.OmitXmlDeclaration = omitDeclaration;
            settings.Indent             = true;
            settings.NewLineHandling    = NewLineHandling.Entitize;
            settings.NamespaceHandling  = NamespaceHandling.OmitDuplicates;

            using (MemoryStream stream = new MemoryStream())
            {
                using (XmlWriter writer = XmlWriter.Create(stream, settings))
                {
                    document.Save(writer);
                    writer.Flush();

                    return(stream.ToArray());
                }
            }
        }
        /// <summary>
        /// Annotates the <paramref name="payloadElement"/> with the format version if it's not already annotated.
        /// </summary>
        /// <param name="payloadElement">The payload element to annotate.</param>
        private void AddVersionAnnotation(ODataPayloadElement payloadElement)
        {
            PayloadFormatVersionAnnotation versionAnnotation =
                (PayloadFormatVersionAnnotation)payloadElement.GetAnnotation(typeof(PayloadFormatVersionAnnotation));

            if (versionAnnotation == null)
            {
                versionAnnotation = new PayloadFormatVersionAnnotation()
                {
                    Version = this.version,
                    Response = !this.requestPayload,
                };

                payloadElement.AddAnnotation(versionAnnotation);
            }
        }
Пример #20
0
        /// <summary>
        /// Determins the payload kind appropriate for the payload element used for this test.
        /// </summary>
        /// <param name="payloadElement">The payload element to get the kind for.</param>
        /// <returns>The payload kind to be used for this test.</returns>
        public static ODataPayloadKind GetPayloadKindFromPayloadElement(this ODataPayloadElement payloadElement)
        {
            if (payloadElement == null)
            {
                return(ODataPayloadKind.Unsupported);
            }

            switch (payloadElement.ElementType)
            {
            case ODataPayloadElementType.NullPropertyInstance:
            case ODataPayloadElementType.PrimitiveProperty:
            case ODataPayloadElementType.PrimitiveMultiValueProperty:
            case ODataPayloadElementType.NamedStreamInstance:
            case ODataPayloadElementType.NavigationPropertyInstance:
                return(ODataPayloadKind.Property);

            case ODataPayloadElementType.ComplexMultiValueProperty:
            case ODataPayloadElementType.EntitySetInstance:
                return(ODataPayloadKind.ResourceSet);

            case ODataPayloadElementType.ComplexProperty:
            case ODataPayloadElementType.EntityInstance:
                return(ODataPayloadKind.Resource);

            case ODataPayloadElementType.PrimitiveCollection:
            case ODataPayloadElementType.ComplexInstanceCollection:
            case ODataPayloadElementType.PrimitiveMultiValue:
            case ODataPayloadElementType.ComplexMultiValue:
                return(ODataPayloadKind.Collection);

            case ODataPayloadElementType.ODataErrorPayload:
                return(ODataPayloadKind.Error);

            case ODataPayloadElementType.DeferredLink:
                return(ODataPayloadKind.EntityReferenceLink);

            case ODataPayloadElementType.LinkCollection:
                return(ODataPayloadKind.EntityReferenceLinks);

            case ODataPayloadElementType.ServiceDocumentInstance:
                return(ODataPayloadKind.ServiceDocument);

            case ODataPayloadElementType.PrimitiveValue:
                EntityModelTypeAnnotation typeAnnotation = payloadElement.GetAnnotation <EntityModelTypeAnnotation>();
                if (typeAnnotation != null && ((IEdmPrimitiveType)typeAnnotation.EdmModelType.Definition).PrimitiveKind == EdmPrimitiveTypeKind.Binary)
                {
                    return(ODataPayloadKind.BinaryValue);
                }

                return(ODataPayloadKind.Value);

            case ODataPayloadElementType.BatchRequestPayload:
            case ODataPayloadElementType.BatchResponsePayload:
                return(ODataPayloadKind.Batch);

            case ODataPayloadElementType.ComplexInstance:
                // TODO: ODataLib test item: Add new ODataPayloadElement for parameters payload
                return(ODataPayloadKind.Parameter);

            default:
                ExceptionUtilities.Assert(
                    false,
                    "Payload element type '{0}' is not yet recognized by GetPayloadKindFromPayloadElement.",
                    payloadElement.ElementType);
                return(ODataPayloadKind.Unsupported);
            }
        }