Пример #1
0
        private void WriteEntry(IExpandedResult expanded, object element, bool resourceInstanceInFeed, ResourceType expectedType)
        {
            Uri uri;
            Func <ProjectionNode, bool> predicate = null;

            base.IncrementSegmentResultCount();
            ODataEntry        entry      = new ODataEntry();
            AtomEntryMetadata annotation = new AtomEntryMetadata();

            entry.SetAnnotation <AtomEntryMetadata>(annotation);
            string       name = expectedType.Name;
            ResourceType actualResourceType = WebUtil.GetNonPrimitiveResourceType(base.Provider, element);

            if (actualResourceType.ResourceTypeKind != ResourceTypeKind.EntityType)
            {
                throw new DataServiceException(500, System.Data.Services.Strings.BadProvider_InconsistentEntityOrComplexTypeUsage(actualResourceType.FullName));
            }
            Uri absoluteUri = Serializer.GetIdAndEditLink(element, actualResourceType, base.Provider, base.CurrentContainer, base.AbsoluteServiceUri, out uri);
            Uri relativeUri = new Uri(absoluteUri.AbsoluteUri.Substring(base.AbsoluteServiceUri.AbsoluteUri.Length), UriKind.Relative);

            entry.MediaResource = this.GetMediaResource(element, actualResourceType, name, relativeUri);
            entry.TypeName      = actualResourceType.FullName;
            entry.Id            = uri.AbsoluteUri;
            entry.EditLink      = relativeUri;
            AtomLinkMetadata metadata2 = new AtomLinkMetadata {
                Title = name
            };

            annotation.EditLink = metadata2;
            string eTagValue = base.GetETagValue(element, actualResourceType);

            if (eTagValue != null)
            {
                entry.ETag = eTagValue;
            }
            IEnumerable <ProjectionNode> projections = base.GetProjections();

            if (projections != null)
            {
                if (predicate == null)
                {
                    predicate = projectionNode => projectionNode.TargetResourceType.IsAssignableFrom(actualResourceType);
                }
                projections = projections.Where <ProjectionNode>(predicate);
                entry.SetAnnotation <ProjectedPropertiesAnnotation>(new ProjectedPropertiesAnnotation(from p in projections select p.PropertyName));
            }
            entry.AssociationLinks = this.GetEntityAssociationLinks(actualResourceType, relativeUri, projections);
            this.PopulateODataOperations(element, resourceInstanceInFeed, entry, actualResourceType);
            this.odataWriter.WriteStart(entry);
            this.WriteNavigationProperties(expanded, element, resourceInstanceInFeed, actualResourceType, absoluteUri, relativeUri, projections);
            entry.Properties = this.GetEntityProperties(element, actualResourceType, relativeUri, projections);
            this.odataWriter.WriteEnd();
        }
Пример #2
0
        /// <summary>
        /// Creates and returns an ODataEntry from the given value.
        /// </summary>
        /// <param name="entityType">The value type.</param>
        /// <param name="value">The entry value.</param>
        /// <param name="properties">The given properties to serialize.</param>
        /// <returns>An ODataEntry representing the given value.</returns>
        internal ODataEntry CreateODataEntry(Type entityType, object value, params ClientPropertyAnnotation[] properties)
        {
            Debug.Assert(entityType != null, "entityType != null");
            Debug.Assert(value != null, "value != null");

            ClientEdmModel       model = this.requestInfo.Model;
            ClientTypeAnnotation entityTypeAnnotation = model.GetClientTypeAnnotation(entityType);

            Debug.Assert(entityTypeAnnotation != null, "entityTypeAnnotation != null");
            Debug.Assert(entityTypeAnnotation.IsEntityType, "Unexpected type");

            ODataEntry odataEntityValue = new ODataEntry()
            {
                TypeName = entityTypeAnnotation.ElementTypeName,
            };

            string serverTypeName = this.requestInfo.GetServerTypeName(entityTypeAnnotation);

            odataEntityValue.SetAnnotation(new SerializationTypeNameAnnotation {
                TypeName = serverTypeName
            });

            odataEntityValue.Properties = this.PopulateProperties(value, serverTypeName, properties.Any() ? properties : entityTypeAnnotation.PropertiesToSerialize(), null);

            return(odataEntityValue);
        }
Пример #3
0
        private void EndEntry()
        {
            IODataAtomReaderEntryState currentEntryState = this.CurrentEntryState;
            ODataEntry entry = currentEntryState.Entry;

            if (entry != null)
            {
                if (currentEntryState.CachedEpm != null)
                {
                    AtomScope currentScope = (AtomScope)base.CurrentScope;
                    if (currentScope.HasAtomEntryMetadata)
                    {
                        EpmSyndicationReader.ReadEntryEpm(currentEntryState, this.atomInputContext);
                    }
                    if (currentScope.HasEpmCustomReaderValueCache)
                    {
                        EpmCustomReader.ReadEntryEpm(currentEntryState, this.atomInputContext);
                    }
                }
                if (currentEntryState.AtomEntryMetadata != null)
                {
                    entry.SetAnnotation <AtomEntryMetadata>(currentEntryState.AtomEntryMetadata);
                }
                IEdmEntityType entityType = currentEntryState.EntityType;
                if ((!currentEntryState.MediaLinkEntry.HasValue && (entityType != null)) && this.atomInputContext.Model.HasDefaultStream(entityType))
                {
                    ODataAtomEntryAndFeedDeserializer.EnsureMediaResource(currentEntryState, true);
                }
                bool validateMediaResource = this.atomInputContext.UseDefaultFormatBehavior || this.atomInputContext.UseServerFormatBehavior;
                ValidationUtils.ValidateEntryMetadata(entry, entityType, this.atomInputContext.Model, validateMediaResource);
            }
            this.ReplaceScope(ODataReaderState.EntryEnd);
        }
Пример #4
0
        private void TryAnnotateV2FeedPackage(ODataEntry entry, EntityInstanceContext entityInstanceContext)
        {
            var instance = entityInstanceContext.EntityInstance as ODataPackage;

            if (instance != null)
            {
                // Set Atom entry metadata
                var atomEntryMetadata = new AtomEntryMetadata();
                atomEntryMetadata.Title = instance.Id;
                if (!string.IsNullOrEmpty(instance.Authors))
                {
                    atomEntryMetadata.Authors = new[] { new AtomPersonMetadata {
                                                            Name = instance.Authors
                                                        } }
                }
                ;
                if (instance.Published > DateTime.MinValue)
                {
                    atomEntryMetadata.Published = instance.Published;
                }
                if (!string.IsNullOrEmpty(instance.Summary))
                {
                    atomEntryMetadata.Summary = instance.Summary;
                }
                entry.SetAnnotation(atomEntryMetadata);

                // Set the ID and links. We have to do this because the self link should have a version containing
                // SemVer 2.0.0 metadata (e.g. 1.0.0+git).
                entry.Id       = BuildId(instance, entityInstanceContext);
                entry.ReadLink = new Uri(entry.Id);
                entry.EditLink = new Uri(entry.Id);

                // Add package download link
                entry.MediaResource = new ODataStreamReferenceValue
                {
                    ContentType = ContentType,
                    ReadLink    = BuildLinkForStreamProperty(instance, entityInstanceContext)
                };

                // Make the download action target match the media resource link.
                entry.Actions = entry
                                .Actions
                                .Select(action =>
                {
                    if (StringComparer.OrdinalIgnoreCase.Equals("Download", action.Title))
                    {
                        return new ODataAction
                        {
                            Metadata = action.Metadata,
                            Target   = entry.MediaResource.ReadLink,
                            Title    = action.Title
                        }
                    }
                    ;

                    return(action);
                })
                                .ToList();
            }
        }
Пример #5
0
        public void ReadEditLinkShouldBeOmittedWhenNeitherSetInAtom()
        {
            DateTimeOffset updatedTime = DateTimeOffset.UtcNow;
            var            entry       = new ODataEntry
            {
                Id = new Uri("http://test.org/EntitySet('1')")
            };

            entry.SetAnnotation(new AtomEntryMetadata()
            {
                Updated = updatedTime
            });
            string actual   = this.WriteAtomEntry(entry);
            string expected = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
                              "<entry xmlns=\"http://www.w3.org/2005/Atom\" xmlns:d=\"http://docs.oasis-open.org/odata/ns/data\" xmlns:m=\"http://docs.oasis-open.org/odata/ns/metadata\" xmlns:georss=\"http://www.georss.org/georss\" xmlns:gml=\"http://www.opengis.net/gml\" m:context=\"http://temp.org/$metadata#EntitySet/$entity\">" +
                              "<id>http://test.org/EntitySet('1')</id>" +
                              "<title />" +
                              "<updated>" + ODataAtomConvert.ToAtomString(updatedTime) + "</updated>" +
                              "<author>" +
                              "<name />" +
                              "</author>" +
                              "<content type=\"application/xml\" />" +
                              "</entry>";

            Assert.Equal(expected, actual);
        }
Пример #6
0
        /// <summary>
        /// Creates a new ODataEntry from the specified entity set, instance, and type.
        /// </summary>
        /// <param name="entitySet">Entity set for the new entry.</param>
        /// <param name="value">Entity instance for the new entry.</param>
        /// <param name="entityType">Entity type for the new entry.</param>
        /// <returns>New ODataEntry with the specified entity set and type, property values from the specified instance.</returns>
        internal static ODataEntry CreateODataEntry(IEdmEntitySet entitySet, IEdmStructuredValue value, IEdmEntityType entityType)
        {
            var entry = new ODataEntry();

            entry.SetAnnotation(new ODataTypeAnnotation(entitySet, entityType));
            entry.Properties = value.PropertyValues.Select(p =>
            {
                object propertyValue;
                if (p.Value.ValueKind == EdmValueKind.Null)
                {
                    propertyValue = null;
                }
                else if (p.Value is IEdmPrimitiveValue)
                {
                    propertyValue = ((IEdmPrimitiveValue)p.Value).ToClrValue();
                }
                else
                {
                    Assert.True(false, "Test only currently supports creating ODataEntry from IEdmPrimitiveValue instances.");
                    return(null);
                }

                return(new ODataProperty()
                {
                    Name = p.Name, Value = propertyValue
                });
            });

            return(entry);
        }
Пример #7
0
        /// <summary>
        /// Creates an ODataEntry for the given EntityDescriptor and fills in its ODataLib metadata.
        /// </summary>
        /// <param name="entityDescriptor">The entity descriptor.</param>
        /// <param name="serverTypeName">Name of the server type.</param>
        /// <param name="entityType">The client-side entity type.</param>
        /// <param name="clientFormat">The current client format.</param>
        /// <returns>An odata entry with its metadata filled in.</returns>
        internal static ODataEntry CreateODataEntry(EntityDescriptor entityDescriptor, string serverTypeName, ClientTypeAnnotation entityType, DataServiceClientFormat clientFormat)
        {
            ODataEntry entry = new ODataEntry();

            // If the client type name is different from the server type name, then add SerializationTypeNameAnnotation
            // which tells ODataLib to write the type name in the annotation in the payload.
            if (entityType.ElementTypeName != serverTypeName)
            {
                entry.SetAnnotation(new SerializationTypeNameAnnotation {
                    TypeName = serverTypeName
                });
            }

            // We always need to write the client type name, since this is the type name used by ODataLib
            // to resolve the entity type using EdmModel.FindSchemaElement.
            entry.TypeName = entityType.ElementTypeName;

            // Continue to send the entry's ID in update payloads in Atom for compatibility with V1-V3,
            // but for JSON-Light we do not want the extra information on the wire.
            if (clientFormat.UsingAtom && EntityStates.Modified == entityDescriptor.State)
            {
                // <id>http://host/service/entityset(key)</id>
                entry.Id = entityDescriptor.GetLatestIdentity();
            }

            if (entityDescriptor.IsMediaLinkEntry || entityType.IsMediaLinkEntry)
            {
                // Since we are already enabled EnableWcfDataServicesClientBehavior in the writer settings,
                // setting the MediaResource value will tell ODataLib to write MLE payload, irrespective of
                // what the metadata says.
                entry.MediaResource = new ODataStreamReferenceValue();
            }

            return(entry);
        }
 public void ReadLinkShouldNotBeOmittedWhenNotIdenticalToEditLink()
 {
     DateTimeOffset updatedTime = DateTimeOffset.UtcNow;
     var entry = new ODataEntry
     {
         Id = new Uri("http://test.org/EntitySet('1')"),
         EditLink = new Uri("http://test.org/EntitySet('1')/edit"),
         ReadLink = new Uri("http://test.org/EntitySet('1')/read")
     };
     entry.SetAnnotation(new AtomEntryMetadata() { Updated = updatedTime });
     string actual = this.WriteAtomEntry(entry);
     string expected = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
         "<entry xmlns=\"http://www.w3.org/2005/Atom\" xmlns:d=\"http://docs.oasis-open.org/odata/ns/data\" xmlns:m=\"http://docs.oasis-open.org/odata/ns/metadata\" xmlns:georss=\"http://www.georss.org/georss\" xmlns:gml=\"http://www.opengis.net/gml\" m:context=\"http://temp.org/$metadata#EntitySet/$entity\">" +
             "<id>http://test.org/EntitySet('1')</id>" +
             "<link rel=\"edit\" href=\"http://test.org/EntitySet('1')/edit\" />" +
             "<link rel=\"self\" href=\"http://test.org/EntitySet('1')/read\" />" +
             "<title />" +
             "<updated>" + ODataAtomConvert.ToAtomString(updatedTime) + "</updated>" +
             "<author>" +
                 "<name />" +
             "</author>" +
             "<content type=\"application/xml\" />" +
         "</entry>";
     Assert.Equal(expected, actual);
 }
        private static ODataEntry CreateEntryWithKeyAsSegmentConvention(bool addAnnotation, bool? useKeyAsSegment)
        {
            var model = new EdmModel();
            var container = new EdmEntityContainer("Fake", "Container");
            model.AddElement(container);
            if (addAnnotation)
            {
                model.AddVocabularyAnnotation(new EdmAnnotation(container, UrlConventionsConstants.ConventionTerm, UrlConventionsConstants.KeyAsSegmentAnnotationValue));                
            }
            
            EdmEntityType entityType = new EdmEntityType("Fake", "FakeType");
            entityType.AddKeys(entityType.AddStructuralProperty("Id", EdmPrimitiveTypeKind.Int32));
            model.AddElement(entityType);

            var entitySet = new EdmEntitySet(container, "FakeSet", entityType);
            container.AddElement(entitySet);

            var metadataContext = new ODataMetadataContext(
                true,
                ODataReaderBehavior.DefaultBehavior.OperationsBoundToEntityTypeMustBeContainerQualified,
                new EdmTypeReaderResolver(model, ODataReaderBehavior.DefaultBehavior),
                model,
                new Uri("http://temp.org/$metadata"),
                null /*requestUri*/);

            var thing = new ODataEntry {Properties = new[] {new ODataProperty {Name = "Id", Value = 1}}};
            thing.SetAnnotation(new ODataTypeAnnotation(entitySet, entityType));
            thing.MetadataBuilder = metadataContext.GetEntityMetadataBuilderForReader(new TestJsonLightReaderEntryState { Entry = thing, SelectedProperties = new SelectedPropertiesNode("*")}, useKeyAsSegment);
            return thing;
        }
        internal static void AddTypeNameAnnotationAsNeeded(ODataEntry entry, IEdmEntityType odataPathType,
                                                           ODataMetadataLevel metadataLevel)
        {
            // ODataLib normally has the caller decide whether or not to serialize properties by leaving properties
            // null when values should not be serialized. The TypeName property is different and should always be
            // provided to ODataLib to enable model validation. A separate annotation is used to decide whether or not
            // to serialize the type name (a null value prevents serialization).

            // Note that this annotation should not be used for Atom or JSON verbose formats, as it will interfere with
            // the correct default behavior for those formats.

            Contract.Assert(entry != null);

            // Only add an annotation if we want to override ODataLib's default type name serialization behavior.
            if (ShouldAddTypeNameAnnotation(metadataLevel))
            {
                string typeName;

                // Provide the type name to serialize (or null to force it not to serialize).
                if (ShouldSuppressTypeNameSerialization(entry, odataPathType, metadataLevel))
                {
                    typeName = null;
                }
                else
                {
                    typeName = entry.TypeName;
                }

                entry.SetAnnotation <SerializationTypeNameAnnotation>(new SerializationTypeNameAnnotation
                {
                    TypeName = typeName
                });
            }
        }
        internal static void AddTypeNameAnnotationAsNeeded(ODataEntry entry, IEdmEntityType odataPathType,
                                                           ODataMetadataLevel metadataLevel)
        {
            // ODataLib normally has the caller decide whether or not to serialize properties by leaving properties
            // null when values should not be serialized. The TypeName property is different and should always be
            // provided to ODataLib to enable model validation. A separate annotation is used to decide whether or not
            // to serialize the type name (a null value prevents serialization).

            // Note: In the current version of ODataLib the default behavior likely now matches the requirements for
            // minimal metadata mode. However, there have been behavior changes/bugs there in the past, so the safer
            // option is for this class to take control of type name serialization in minimal metadata mode.

            Contract.Assert(entry != null);

            string typeName = null; // Set null to force the type name not to serialize.

            // Provide the type name to serialize.
            if (!ShouldSuppressTypeNameSerialization(entry, odataPathType, metadataLevel))
            {
                typeName = entry.TypeName;
            }

            entry.SetAnnotation <SerializationTypeNameAnnotation>(new SerializationTypeNameAnnotation
            {
                TypeName = typeName
            });
        }
        private void TryAnnotateV2FeedPackage(ODataEntry entry, EntityInstanceContext entityInstanceContext)
        {
            var instance = entityInstanceContext.EntityInstance as V2FeedPackage;

            if (instance != null)
            {
                // Set Atom entry metadata
                var atomEntryMetadata = new AtomEntryMetadata();
                atomEntryMetadata.Title = instance.Id;
                if (!string.IsNullOrEmpty(instance.Authors))
                {
                    atomEntryMetadata.Authors = new[] { new AtomPersonMetadata {
                                                            Name = instance.Authors
                                                        } };
                }
                if (instance.LastUpdated > DateTime.MinValue)
                {
                    atomEntryMetadata.Updated = instance.LastUpdated;
                }
                if (!string.IsNullOrEmpty(instance.Summary))
                {
                    atomEntryMetadata.Summary = instance.Summary;
                }
                entry.SetAnnotation(atomEntryMetadata);

                // Add package download link
                entry.MediaResource = new ODataStreamReferenceValue
                {
                    ContentType = ContentType,
                    ReadLink    = BuildLinkForStreamProperty("v2", instance.Id, instance.Version, entityInstanceContext.Request)
                };
            }
        }
Пример #13
0
        public void FlagsEnumAsEntityProperty_NullAsValue_ButNonNullable_GetNullError()
        {
            DateTimeOffset    updatedTime = DateTimeOffset.UtcNow;
            Func <ODataEntry> entryClone  = () =>
            {
                var tmp = new ODataEntry
                {
                    TypeName   = "NS.MyEntityType",
                    Properties = new[]
                    {
                        new ODataProperty
                        {
                            Name  = "ColorFlags",
                            Value = null
                        }
                    },
                    SerializationInfo = MySerializationInfo
                };

                tmp.SetAnnotation(new AtomEntryMetadata()
                {
                    Updated = updatedTime
                });
                return(tmp);
            };

            string fullName = this.entityType.FindProperty("ColorFlags").Type.FullName();

            // model-request
            Action action = () => this.WriteRequestWithModelAndValidatePayload(nestedItemToWrite: new[] { entryClone() }, expectedPayload: "");

            action.ShouldThrow <ODataException>().WithMessage(Strings.WriterValidationUtils_NonNullablePropertiesMustNotHaveNullValue("ColorFlags", fullName));

            // model-reseponse
            action = () => this.WriteResponseWithModelAndValidatePayload(nestedItemToWrite: new[] { entryClone() }, expectedPayload: "");
            action.ShouldThrow <ODataException>().WithMessage(Strings.WriterValidationUtils_NonNullablePropertiesMustNotHaveNullValue("ColorFlags", fullName));

            // NoModel-request
            string expectedPayload = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
                                     "<entry xmlns=\"http://www.w3.org/2005/Atom\" xmlns:d=\"http://docs.oasis-open.org/odata/ns/data\" xmlns:m=\"http://docs.oasis-open.org/odata/ns/metadata\" " +
                                     "xmlns:georss=\"http://www.georss.org/georss\" xmlns:gml=\"http://www.opengis.net/gml\" m:context=\"http://odata.org/test/$metadata#MySet/$entity\">" +
                                     "<category term=\"#NS.MyEntityType\" scheme=\"http://docs.oasis-open.org/odata/ns/scheme\" />" +
                                     "<id />" +
                                     "<title />" +
                                     "<updated>" + ODataAtomConvert.ToAtomString(updatedTime) + "</updated>" +
                                     "<author><name /></author>" +
                                     "<content type=\"application/xml\">" +
                                     "<m:properties>" +
                                     "<d:ColorFlags m:null=\"true\" />" +
                                     "</m:properties>" +
                                     "</content>" +
                                     "</entry>";

            this.WriteRequestWithoutModelAndValidatePayload(nestedItemToWrite: new[] { entryClone() }, expectedPayload: expectedPayload);

            // NoModel-response
            this.WriteResponseWithoutModelAndValidatePayload(nestedItemToWrite: new[] { entryClone() }, expectedPayload: expectedPayload);
        }
Пример #14
0
 public JsonMinimalMetadataTypeNameOracleTests()
 {
     entryWithTypeAnnotationAndTypeName.SetAnnotation(new SerializationTypeNameAnnotation {
         TypeName = "TypeNameFromSTNA"
     });
     entryWithTypeAnnotationWithoutTypeName.SetAnnotation(new SerializationTypeNameAnnotation {
         TypeName = "TypeNameFromSTNA"
     });
 }
Пример #15
0
        /// <summary>
        /// Creates the materializer entry.
        /// </summary>
        /// <param name="entry">The entry.</param>
        /// <param name="format">The format the entry was read in.</param>
        /// <param name="isTracking">True if the contents of the entry will be tracked in the context, otherwise False.</param>
        /// <param name="model">The client model.</param>
        /// <returns>A new materializer entry.</returns>
        public static MaterializerEntry CreateEntry(ODataEntry entry, ODataFormat format, bool isTracking, ClientEdmModel model)
        {
            Debug.Assert(entry.GetAnnotation <MaterializerEntry>() == null, "MaterializerEntry has already been created.");

            MaterializerEntry materializerEntry = new MaterializerEntry(entry, format, isTracking, model);

            entry.SetAnnotation <MaterializerEntry>(materializerEntry);

            return(materializerEntry);
        }
Пример #16
0
        private static XmlReader EntryXmlCustomizer(ODataEntry entry, XmlReader entryReader, Uri baseUri)
        {
            XElement payload = XElement.Load(entryReader.ReadSubtree(), LoadOptions.None);

            entryReader.Read();
            entry.SetAnnotation <ReadingEntityInfo>(new ReadingEntityInfo(payload, baseUri));
            XmlReader reader = payload.CreateReader();

            reader.Read();
            return(reader);
        }
Пример #17
0
        public void FlagsEnumAsEntityProperty_StrAsValue_StrAsTypeName()
        {
            DateTimeOffset    updatedTime = DateTimeOffset.UtcNow;
            Func <ODataEntry> entryClone  = () =>
            {
                var tmp = new ODataEntry
                {
                    TypeName   = "NS.MyEntityType",
                    Properties = new[]
                    {
                        new ODataProperty
                        {
                            Name  = "ColorFlags",
                            Value = new ODataEnumValue(
                                (ColorFlags.Green | ColorFlags.Red).ToString(CultureInfo.InvariantCulture),
                                "NS.MyEnumTypeName")     // type name
                        }
                    },
                    SerializationInfo = MySerializationInfo
                };
                tmp.SetAnnotation(new AtomEntryMetadata()
                {
                    Updated = updatedTime
                });
                return(tmp);
            };

            // model-request
            string expectedPayload = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
                                     "<entry xmlns=\"http://www.w3.org/2005/Atom\" xmlns:d=\"http://docs.oasis-open.org/odata/ns/data\" xmlns:m=\"http://docs.oasis-open.org/odata/ns/metadata\" " +
                                     "xmlns:georss=\"http://www.georss.org/georss\" xmlns:gml=\"http://www.opengis.net/gml\" m:context=\"http://odata.org/test/$metadata#MySet/$entity\">" +
                                     "<category term=\"#NS.MyEntityType\" scheme=\"http://docs.oasis-open.org/odata/ns/scheme\" />" +
                                     "<id />" +
                                     "<title />" +
                                     "<updated>" + ODataAtomConvert.ToAtomString(updatedTime) + "</updated>" +
                                     "<author><name /></author>" +
                                     "<content type=\"application/xml\">" +
                                     "<m:properties>" +
                                     "<d:ColorFlags m:type=\"#NS.MyEnumTypeName\">Red, Green</d:ColorFlags>" +
                                     "</m:properties>" +
                                     "</content>" +
                                     "</entry>";

            this.WriteRequestWithModelAndValidatePayload(nestedItemToWrite: new[] { entryClone() }, expectedPayload: expectedPayload);

            // model-reseponse
            this.WriteResponseWithModelAndValidatePayload(nestedItemToWrite: new[] { entryClone() }, expectedPayload: expectedPayload);

            // NoModel-request
            this.WriteRequestWithoutModelAndValidatePayload(nestedItemToWrite: new[] { entryClone() }, expectedPayload: expectedPayload);

            // NoModel-response
            this.WriteResponseWithoutModelAndValidatePayload(nestedItemToWrite: new[] { entryClone() }, expectedPayload: expectedPayload);
        }
Пример #18
0
        public static AtomEntryMetadata Atom(this ODataEntry entry)
        {
            ExceptionUtils.CheckArgumentNotNull <ODataEntry>(entry, "entry");
            AtomEntryMetadata annotation = entry.GetAnnotation <AtomEntryMetadata>();

            if (annotation == null)
            {
                annotation = new AtomEntryMetadata();
                entry.SetAnnotation <AtomEntryMetadata>(annotation);
            }
            return(annotation);
        }
Пример #19
0
        internal void WriteEntry(EntityDescriptor entityDescriptor, IEnumerable <LinkDescriptor> relatedLinks, ODataRequestMessageWrapper requestMessage)
        {
            ClientEdmModel       model = ClientEdmModel.GetModel(this.requestInfo.MaxProtocolVersion);
            ClientTypeAnnotation clientTypeAnnotation = model.GetClientTypeAnnotation(model.GetOrCreateEdmType(entityDescriptor.Entity.GetType()));

            using (ODataMessageWriter writer = CreateMessageWriter(requestMessage, this.requestInfo))
            {
                ODataWriter odataWriter = writer.CreateODataEntryWriter();
                ODataEntry  entry       = new ODataEntry();
                if (this.requestInfo.HasWritingEventHandlers)
                {
                    entry.SetAnnotation <WritingEntityInfo>(new WritingEntityInfo(entityDescriptor.Entity, this.requestInfo));
                }
                string serverTypeName = this.requestInfo.GetServerTypeName(entityDescriptor);
                if (clientTypeAnnotation.ElementTypeName != serverTypeName)
                {
                    SerializationTypeNameAnnotation annotation = new SerializationTypeNameAnnotation {
                        TypeName = serverTypeName
                    };
                    entry.SetAnnotation <SerializationTypeNameAnnotation>(annotation);
                }
                entry.TypeName = clientTypeAnnotation.ElementTypeName;
                if (EntityStates.Modified == entityDescriptor.State)
                {
                    entry.Id = entityDescriptor.GetLatestIdentity();
                }
                if (entityDescriptor.IsMediaLinkEntry || clientTypeAnnotation.IsMediaLinkEntry)
                {
                    entry.MediaResource = new ODataStreamReferenceValue();
                }
                odataWriter.WriteStart(entry);
                if (EntityStates.Added == entityDescriptor.State)
                {
                    this.WriteNavigationLink(entityDescriptor, relatedLinks, odataWriter);
                }
                entry.Properties = this.PopulateProperties(clientTypeAnnotation, entityDescriptor.Entity, null);
                odataWriter.WriteEnd();
            }
        }
Пример #20
0
        /// <summary>
        /// Returns the new XmlReader to cache the payload for firing ReadingEntity event.
        /// </summary>
        /// <param name="entry">ODataEntry instance that is currently getting deserialized.</param>
        /// <param name="entryReader">XmlReader that is used to read the payload.</param>
        /// <param name="baseUri">BaseUri for the entry payload.</param>
        /// <returns>XmlReader instance that needs to be used to read the payload for the given odataentry.</returns>
        internal static XmlReader BufferAndCacheEntryPayload(ODataEntry entry, XmlReader entryReader, Uri baseUri)
        {
            XElement entryPayload = XElement.Load(entryReader.ReadSubtree(), LoadOptions.None);

            // Move the parent entry reader after the end element of the entry.
            entryReader.Read();

            entry.SetAnnotation(new ReadingEntityInfo(entryPayload, baseUri));
            XmlReader xmlReader = entryPayload.CreateReader();

            xmlReader.Read();
            return(xmlReader);
        }
Пример #21
0
        public static AtomEntryMetadata Atom(this ODataEntry entry)
        {
            ExceptionUtils.CheckArgumentNotNull(entry, "entry");

            AtomEntryMetadata entryMetadata = entry.GetAnnotation <AtomEntryMetadata>();

            if (entryMetadata == null)
            {
                entryMetadata = new AtomEntryMetadata();
                entry.SetAnnotation(entryMetadata);
            }

            return(entryMetadata);
        }
        internal void SetTypeName(ODataEntry entry, string entitySetBaseTypeName, string entryTypeName)
        {
            Debug.Assert(entry != null, "entry != null");

            // We should always write this since for derived types, ODL needs to know the typename.
            entry.TypeName = entryTypeName;

            if (this.interpreter.ShouldIncludeEntryTypeName(entitySetBaseTypeName, entryTypeName))
            {
                entry.SetAnnotation(new SerializationTypeNameAnnotation()
                {
                    TypeName = entry.TypeName
                });
            }
            else
            {
                // When we should not write the typename, setting the serialization type name to null
                // so that ODL does not write the type on the wire.
                entry.SetAnnotation(new SerializationTypeNameAnnotation()
                {
                    TypeName = null
                });
            }
        }
Пример #23
0
        public static MaterializerEntry CreateEntry(ODataEntry entry, DataServiceProtocolVersion maxProtocolVersion)
        {
            MaterializerEntry annotation = new MaterializerEntry(entry, maxProtocolVersion);

            entry.SetAnnotation <MaterializerEntry>(annotation);
            if (entry.Id == null)
            {
                throw System.Data.Services.Client.Error.InvalidOperation(System.Data.Services.Client.Strings.Deserialize_MissingIdElement);
            }
            annotation.EntityDescriptor.Identity = entry.Id;
            annotation.EntityDescriptor.EditLink = entry.EditLink;
            annotation.EntityDescriptor.SelfLink = entry.ReadLink;
            annotation.EntityDescriptor.ETag     = entry.ETag;
            return(annotation);
        }
Пример #24
0
        private static void WriteOdataEntity(ITableEntity entity, TableOperationType operationType, OperationContext ctx, ODataWriter writer, TableRequestOptions options)
        {
            ODataEntry entry = new ODataEntry()
            {
                Properties = GetPropertiesWithKeys(entity, ctx, operationType, options),
                TypeName   = "account.sometype"
            };

            entry.SetAnnotation(new SerializationTypeNameAnnotation {
                TypeName = null
            });
            writer.WriteStart(entry);
            writer.WriteEnd();
            writer.Flush();
        }
Пример #25
0
        internal static IEdmValue CreateStructuredEdmValue(ODataEntry entry, IEdmEntitySet entitySet, IEdmEntityTypeReference entityType)
        {
            if (entitySet != null)
            {
                object typeAnnotation = ReflectionUtils.CreateInstance(
                    odataTypeAnnotationType,
                    new Type[] { typeof(IEdmEntitySet), typeof(IEdmEntityTypeReference) },
                    entitySet, entityType);
                entry.SetAnnotation(typeAnnotation);
            }

            return((IEdmValue)ReflectionUtils.CreateInstance(
                       odataEdmStructuredValueType,
                       new Type[] { typeof(ODataEntry) },
                       entry));
        }
        public override void Annotate(HttpRequestMessage request, ODataEntry entry, object entityInstance)
        {
            var feedPackage = entityInstance as V2FeedPackage;

            if (feedPackage == null)
            {
                return;
            }

            // Patch links to use normalized versions
            var normalizedVersion = NuGetVersionFormatter.Normalize(feedPackage.Version);

            NormalizeNavigationLinks(entry, request, feedPackage, normalizedVersion);

            // Set Atom entry metadata
            var atomEntryMetadata = new AtomEntryMetadata();

            atomEntryMetadata.Title = feedPackage.Title;

            if (!string.IsNullOrEmpty(feedPackage.Authors))
            {
                atomEntryMetadata.Authors = new[] { new AtomPersonMetadata {
                                                        Name = feedPackage.Authors
                                                    } };
            }

            if (feedPackage.LastUpdated > DateTime.MinValue)
            {
                atomEntryMetadata.Updated = feedPackage.LastUpdated;
            }

            if (!string.IsNullOrEmpty(feedPackage.Summary))
            {
                atomEntryMetadata.Summary = feedPackage.Summary;
            }

            entry.SetAnnotation(atomEntryMetadata);

            // Add package download link
            entry.MediaResource = new ODataStreamReferenceValue
            {
                ContentType = ContentType,
                ReadLink    = BuildLinkForStreamProperty("v2", feedPackage.Id, normalizedVersion, request)
            };
        }
        private static void WriteOdataEntity(ITableEntity entity, TableOperationType operationType, OperationContext ctx, ODataWriter writer)
        {
            ODataEntry entry = new ODataEntry()
            {
                Properties = GetPropertiesWithKeys(entity, ctx, operationType),
                TypeName   = "account.sometype"
            };

            if (operationType != TableOperationType.Insert && operationType != TableOperationType.Retrieve)
            {
                entry.ETag = entity.ETag;
            }

            entry.SetAnnotation(new SerializationTypeNameAnnotation {
                TypeName = null
            });
            writer.WriteStart(entry);
            writer.WriteEnd();
            writer.Flush();
        }
Пример #28
0
        private static void WriteEntry(ODataWriter writer, object entity, IEnumerable <string> projectedProperties)
        {
            var entry = new ODataEntry()
            {
                Id = new Uri("http://temp.org/" + Guid.NewGuid()),
                SerializationInfo = MySerializationInfo
            };

            if (projectedProperties != null)
            {
                entry.SetAnnotation <ProjectedPropertiesAnnotation>(new ProjectedPropertiesAnnotation(projectedProperties));
            }

            entry.Properties = entity.GetType().GetProperties().Select(p => new ODataProperty()
            {
                Name = p.Name, Value = p.GetValue(entity, null)
            });

            writer.WriteStart(entry);
            writer.WriteEnd();
        }
        private static ODataEntry CreateEntryWithKeyAsSegmentConvention(bool addAnnotation, bool?useKeyAsSegment)
        {
            var model     = new EdmModel();
            var container = new EdmEntityContainer("Fake", "Container");

            model.AddElement(container);
            if (addAnnotation)
            {
                model.AddVocabularyAnnotation(new EdmAnnotation(container, UrlConventionsConstants.ConventionTerm, UrlConventionsConstants.KeyAsSegmentAnnotationValue));
            }

            EdmEntityType entityType = new EdmEntityType("Fake", "FakeType");

            entityType.AddKeys(entityType.AddStructuralProperty("Id", EdmPrimitiveTypeKind.Int32));
            model.AddElement(entityType);

            var entitySet = new EdmEntitySet(container, "FakeSet", entityType);

            container.AddElement(entitySet);

            var metadataContext = new ODataMetadataContext(
                true,
                ODataReaderBehavior.DefaultBehavior.OperationsBoundToEntityTypeMustBeContainerQualified,
                new EdmTypeReaderResolver(model, ODataReaderBehavior.DefaultBehavior),
                model,
                new Uri("http://temp.org/$metadata"),
                null /*requestUri*/);

            var thing = new ODataEntry {
                Properties = new[] { new ODataProperty {
                                         Name = "Id", Value = 1
                                     } }
            };

            thing.SetAnnotation(new ODataTypeAnnotation(entitySet, entityType));
            thing.MetadataBuilder = metadataContext.GetEntityMetadataBuilderForReader(new TestJsonLightReaderEntryState {
                Entry = thing, SelectedProperties = new SelectedPropertiesNode("*")
            }, useKeyAsSegment);
            return(thing);
        }
        public void FlagsEnumAsEntityProperty_NullAsValue_ButNonNullable_GetNullError()
        {
            DateTimeOffset updatedTime = DateTimeOffset.UtcNow;
            Func<ODataEntry> entryClone = () =>
            {
                var tmp = new ODataEntry
                {
                    TypeName = "NS.MyEntityType",
                    Properties = new[]
                        {
                            new ODataProperty
                            {
                                Name = "ColorFlags",
                                Value = null
                            }
                        },
                    SerializationInfo = MySerializationInfo
                };

                tmp.SetAnnotation(new AtomEntryMetadata() { Updated = updatedTime });
                return tmp;
            };

            string fullName = this.entityType.FindProperty("ColorFlags").Type.FullName();

            // model-request
            Action action = () => this.WriteRequestWithModelAndValidatePayload(nestedItemToWrite: new[] { entryClone() }, expectedPayload: "");
            action.ShouldThrow<ODataException>().WithMessage(Strings.WriterValidationUtils_NonNullablePropertiesMustNotHaveNullValue("ColorFlags", fullName));

            // model-reseponse
            action = () => this.WriteResponseWithModelAndValidatePayload(nestedItemToWrite: new[] { entryClone() }, expectedPayload: "");
            action.ShouldThrow<ODataException>().WithMessage(Strings.WriterValidationUtils_NonNullablePropertiesMustNotHaveNullValue("ColorFlags", fullName));

            // NoModel-request 
            string expectedPayload = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
            "<entry xmlns=\"http://www.w3.org/2005/Atom\" xmlns:d=\"http://docs.oasis-open.org/odata/ns/data\" xmlns:m=\"http://docs.oasis-open.org/odata/ns/metadata\" " +
                "xmlns:georss=\"http://www.georss.org/georss\" xmlns:gml=\"http://www.opengis.net/gml\" m:context=\"http://odata.org/test/$metadata#MySet/$entity\">" +
                "<category term=\"#NS.MyEntityType\" scheme=\"http://docs.oasis-open.org/odata/ns/scheme\" />" +
                    "<id />" +
                    "<title />" +
                    "<updated>" + ODataAtomConvert.ToAtomString(updatedTime) + "</updated>" +
                    "<author><name /></author>" +
                    "<content type=\"application/xml\">" +
                    "<m:properties>" +
                        "<d:ColorFlags m:null=\"true\" />" +
                    "</m:properties>" +
                "</content>" +
            "</entry>";
            this.WriteRequestWithoutModelAndValidatePayload(nestedItemToWrite: new[] { entryClone() }, expectedPayload: expectedPayload);

            // NoModel-response  
            this.WriteResponseWithoutModelAndValidatePayload(nestedItemToWrite: new[] { entryClone() }, expectedPayload: expectedPayload);
        }
Пример #31
0
        private static void AddEntryMetadata(EntityInstance payloadElement, ODataEntry entry)
        {
            AtomEntryMetadata metadata = null;

            foreach (XmlTreeAnnotation epmTree in payloadElement.Annotations.OfType <XmlTreeAnnotation>())
            {
                if (epmTree.NamespaceName == TestAtomConstants.AtomNamespace)
                {
                    if (metadata == null)
                    {
                        metadata = new AtomEntryMetadata();
                    }

                    string localName = epmTree.LocalName;
                    if (localName == TestAtomConstants.AtomAuthorElementName)
                    {
                        Debug.Assert(!epmTree.IsAttribute);
                        AtomPersonMetadata author = CreateAuthorMetadata(epmTree.Children);

                        List <AtomPersonMetadata> authors;
                        if (metadata.Authors == null)
                        {
                            authors          = new List <AtomPersonMetadata>();
                            metadata.Authors = authors;
                        }
                        else
                        {
                            authors = (List <AtomPersonMetadata>)metadata.Authors;
                        }
                        authors.Add(author);
                    }
                    else if (localName == TestAtomConstants.AtomCategoryElementName)
                    {
                        Debug.Assert(!epmTree.IsAttribute);
                        AtomCategoryMetadata category = CreateCategoryMetadata(epmTree.Children);

                        List <AtomCategoryMetadata> categories;
                        if (metadata.Categories == null)
                        {
                            categories          = new List <AtomCategoryMetadata>();
                            metadata.Categories = categories;
                        }
                        else
                        {
                            categories = (List <AtomCategoryMetadata>)metadata.Categories;
                        }
                        categories.Add(category);
                    }
                    else if (localName == TestAtomConstants.AtomContributorElementName)
                    {
                        Debug.Assert(!epmTree.IsAttribute);
                        AtomPersonMetadata contributor = CreateAuthorMetadata(epmTree.Children);

                        List <AtomPersonMetadata> contributors;
                        if (metadata.Contributors == null)
                        {
                            contributors          = new List <AtomPersonMetadata>();
                            metadata.Contributors = contributors;
                        }
                        else
                        {
                            contributors = (List <AtomPersonMetadata>)metadata.Contributors;
                        }
                        contributors.Add(contributor);
                    }
                    else if (localName == TestAtomConstants.AtomIdElementName)
                    {
                        Debug.Assert(!epmTree.IsAttribute);
                        entry.Id = string.IsNullOrEmpty(epmTree.PropertyValue) ? null : new Uri(epmTree.PropertyValue);
                    }
                    else if (localName == TestAtomConstants.AtomLinkElementName)
                    {
                        Debug.Assert(!epmTree.IsAttribute);
                        AtomLinkMetadata link = CreateLinkMetadata(epmTree.Children);

                        List <AtomLinkMetadata> links;
                        if (metadata.Links == null)
                        {
                            links          = new List <AtomLinkMetadata>();
                            metadata.Links = links;
                        }
                        else
                        {
                            links = (List <AtomLinkMetadata>)metadata.Links;
                        }
                        links.Add(link);
                    }
                    else if (localName == TestAtomConstants.AtomPublishedElementName)
                    {
                        Debug.Assert(!epmTree.IsAttribute);
                        metadata.Published = string.IsNullOrEmpty(epmTree.PropertyValue) ? (DateTimeOffset?)null : DateTimeOffset.Parse(epmTree.PropertyValue);
                    }
                    else if (localName == TestAtomConstants.AtomRightsElementName)
                    {
                        Debug.Assert(!epmTree.IsAttribute);
                        AtomTextConstructKind atomConstructKind = GetAtomConstructKind(epmTree.Children);
                        metadata.Rights = new AtomTextConstruct {
                            Kind = atomConstructKind, Text = epmTree.PropertyValue
                        };
                    }
                    else if (localName == TestAtomConstants.AtomSourceElementName)
                    {
                        Debug.Assert(!epmTree.IsAttribute);
                        metadata.Source = CreateFeedMetadata(epmTree.Children, null);
                    }
                    else if (localName == TestAtomConstants.AtomSummaryElementName)
                    {
                        Debug.Assert(!epmTree.IsAttribute);
                        AtomTextConstructKind atomConstructKind = GetAtomConstructKind(epmTree.Children);
                        metadata.Summary = new AtomTextConstruct {
                            Kind = atomConstructKind, Text = epmTree.PropertyValue
                        };
                    }
                    else if (localName == TestAtomConstants.AtomTitleElementName)
                    {
                        Debug.Assert(!epmTree.IsAttribute);
                        AtomTextConstructKind atomConstructKind = GetAtomConstructKind(epmTree.Children);
                        metadata.Title = new AtomTextConstruct {
                            Kind = atomConstructKind, Text = epmTree.PropertyValue
                        };
                    }
                    else if (localName == TestAtomConstants.AtomUpdatedElementName)
                    {
                        Debug.Assert(!epmTree.IsAttribute);
                        metadata.Updated = string.IsNullOrEmpty(epmTree.PropertyValue) ? (DateTimeOffset?)null : DateTimeOffset.Parse(epmTree.PropertyValue);
                    }
                    else
                    {
                        throw new NotSupportedException("Unsupported atom metadata '" + localName + "' found for entry!");
                    }
                }
            }

            // Fix up metadata for baselining
            metadata = metadata.Fixup();

            if (metadata != null)
            {
                entry.SetAnnotation <AtomEntryMetadata>(metadata);
            }
        }
        public void FlagsEnumAsEntityProperty_EmptyStrAsValue_NullAsTypeName()
        {
            DateTimeOffset updatedTime = DateTimeOffset.UtcNow;
            Func<ODataEntry> entryClone = () =>
            {
                var tmp = new ODataEntry
                {
                    TypeName = "NS.MyEntityType",
                    Properties = new[]
                        {
                            new ODataProperty
                            {
                                Name = "ColorFlags",
                                Value = new ODataEnumValue("")
                            }
                        },
                    SerializationInfo = MySerializationInfo
                };
                tmp.SetAnnotation(new AtomEntryMetadata() { Updated = updatedTime });
                return tmp;
            };

            // model-request
            string expectedPayload = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
                "<entry xmlns=\"http://www.w3.org/2005/Atom\" xmlns:d=\"http://docs.oasis-open.org/odata/ns/data\" xmlns:m=\"http://docs.oasis-open.org/odata/ns/metadata\" " +
                    "xmlns:georss=\"http://www.georss.org/georss\" xmlns:gml=\"http://www.opengis.net/gml\" m:context=\"http://odata.org/test/$metadata#MySet/$entity\">" +
                    "<category term=\"#NS.MyEntityType\" scheme=\"http://docs.oasis-open.org/odata/ns/scheme\" />" +
                        "<id />" +
                        "<title />" +
                        "<updated>" + ODataAtomConvert.ToAtomString(updatedTime) + "</updated>" +
                        "<author><name /></author>" +
                        "<content type=\"application/xml\">" +
                        "<m:properties>" +
                            "<d:ColorFlags m:type=\"#NS.ColorFlags\"></d:ColorFlags>" +
                        "</m:properties>" +
                    "</content>" +
                "</entry>";
            this.WriteRequestWithModelAndValidatePayload(nestedItemToWrite: new[] { entryClone() }, expectedPayload: expectedPayload);

            // model-reseponse
            this.WriteResponseWithModelAndValidatePayload(nestedItemToWrite: new[] { entryClone() }, expectedPayload: expectedPayload);

            // NoModel-request
            expectedPayload = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
                "<entry xmlns=\"http://www.w3.org/2005/Atom\" xmlns:d=\"http://docs.oasis-open.org/odata/ns/data\" xmlns:m=\"http://docs.oasis-open.org/odata/ns/metadata\" " +
                    "xmlns:georss=\"http://www.georss.org/georss\" xmlns:gml=\"http://www.opengis.net/gml\" m:context=\"http://odata.org/test/$metadata#MySet/$entity\">" +
                    "<category term=\"#NS.MyEntityType\" scheme=\"http://docs.oasis-open.org/odata/ns/scheme\" />" +
                        "<id />" +
                        "<title />" +
                        "<updated>" + ODataAtomConvert.ToAtomString(updatedTime) + "</updated>" +
                        "<author><name /></author>" +
                        "<content type=\"application/xml\">" +
                        "<m:properties>" +
                            "<d:ColorFlags></d:ColorFlags>" +
                        "</m:properties>" +
                    "</content>" +
                "</entry>";
            this.WriteRequestWithoutModelAndValidatePayload(nestedItemToWrite: new[] { entryClone() }, expectedPayload: expectedPayload);

            // NoModel-response
            this.WriteResponseWithoutModelAndValidatePayload(nestedItemToWrite: new[] { entryClone() }, expectedPayload: expectedPayload);
        }
Пример #33
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();

            ODataEntry entry = new ODataEntry();

            if (!resourceInstanceInFeed)
            {
                entry.SetSerializationInfo(new ODataFeedAndEntrySerializationInfo {
                    NavigationSourceName = this.CurrentContainer.Name, NavigationSourceEntityTypeName = this.CurrentContainer.ResourceType.FullName, ExpectedTypeName = expectedType.FullName
                });
            }

            string title = expectedType.Name;

#pragma warning disable 618
            if (this.contentFormat == ODataFormat.Atom)
#pragma warning restore 618
            {
                AtomEntryMetadata entryAtom = new AtomEntryMetadata();
                entryAtom.EditLink = new AtomLinkMetadata {
                    Title = title
                };
                entry.SetAnnotation(entryAtom);
            }

            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();

                // And add the annotation to tell ODataLib which properties to write into content (the projections)
                entry.SetAnnotation(new ProjectedPropertiesAnnotation(projectionNodes.Select(p => p.PropertyName)));
            }

            // 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);

            // 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
        }
        private IEnumerable <ODataItem> CreatePayload(ProjectedPropertiesTestCase testCase)
        {
            // First create the entry itself (it might get wrapped later)
            ODataEntry entry = new ODataEntry()
            {
                TypeName   = "TestModel.EntityType",
                Properties = new List <ODataProperty>()
                {
                    new ODataProperty {
                        Name = "StringProperty", Value = "foo"
                    },
                    new ODataProperty {
                        Name = "NumberProperty", Value = 42
                    },
                    new ODataProperty {
                        Name = "SimpleComplexProperty", Value = new ODataComplexValue
                        {
                            TypeName   = "TestModel.SimplexComplexType",
                            Properties = new ODataProperty[] {
                                new ODataProperty {
                                    Name = "Name", Value = "Bart"
                                }
                            }
                        }
                    },
                    new ODataProperty {
                        Name = "DeepComplexProperty", Value = new ODataComplexValue
                        {
                            TypeName   = "TestModel.NestedComplexType",
                            Properties = new ODataProperty[] {
                                new ODataProperty {
                                    Name = "InnerComplexProperty", Value = new ODataComplexValue
                                    {
                                        TypeName   = "TestModel.SimplexComplexType2",
                                        Properties = new ODataProperty[] {
                                            new ODataProperty {
                                                Name = "Value", Value = 43
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },

                    new ODataProperty {
                        Name = "PrimitiveCollection", Value = new ODataCollectionValue
                        {
                            TypeName = "Collection(Edm.String)",
                            Items    = new object[] { "Simpson" }
                        }
                    },
                    new ODataProperty {
                        Name = "ComplexCollection", Value = new ODataCollectionValue
                        {
                            TypeName = "Collection(TestModel.RatingComplexType)",
                            Items    = new object[] {
                                new ODataComplexValue
                                {
                                    TypeName   = "TestModel.RatingComplexType",
                                    Properties = new ODataProperty[] { new ODataProperty {
                                                                           Name = "Rating", Value = -3
                                                                       } }
                                }
                            }
                        }
                    }
                },
                SerializationInfo = MySerializationInfo
            };

            if (testCase.ResponseOnly)
            {
                // Add a stream property for responses
                ((List <ODataProperty>)entry.Properties).Add(new ODataProperty {
                    Name = "NamedStream", Value = new ODataStreamReferenceValue {
                        EditLink = new Uri("http://odata.org/namedstream")
                    }
                });
            }

            ODataItem[] entryItems = new ODataItem[]
            {
                entry,
                new ODataNavigationLink {
                    Name = "DeferredNavigation", IsCollection = false, Url = new Uri("http://odata.org/deferred"), AssociationLinkUrl = testCase.ResponseOnly ? new Uri("http://odata.org/associationlink2") : null
                },
                null, // End deferred link

                new ODataNavigationLink {
                    Name = "ExpandedEntry", IsCollection = false, Url = new Uri("http://odata.org/entry")
                },
                new ODataEntry()
                {
                    TypeName   = "TestModel.ExpandedEntryType",
                    Properties = new ODataProperty[] {
                        new ODataProperty {
                            Name = "ExpandedEntryName", Value = "bar"
                        }
                    },
                    SerializationInfo = MySerializationInfo
                },
                new ODataNavigationLink {
                    Name = "ExpandedEntry_DeferredNavigation", IsCollection = false, Url = new Uri("http://odata.org/deferred")
                },
                null,         // End deffered link
                new ODataNavigationLink {
                    Name = "ExpandedEntry_ExpandedFeed", IsCollection = true, Url = new Uri("http://odata.org/feed")
                },
                new ODataFeed {
                    Id = new Uri("http://test/feedid1"), SerializationInfo = MySerializationInfo
                },
                null, // End feed
                null, // End exanded expanded feed link
                null, // End expanded entry
                null, // End expanded entry nav link

                new ODataNavigationLink {
                    Name = "ExpandedFeed", IsCollection = true, Url = new Uri("http://odata.org/feed")
                },
                new ODataFeed {
                    Id = new Uri("http://test/feedid2")
                },
                new ODataEntry {
                    TypeName = "TestModel.EntityType"
                },
                null,         // End entry
                new ODataEntry {
                    TypeName = "TestModel.EntityType", SerializationInfo = MySerializationInfo
                },
                null, // End entry
                null, // End expanded feed
                null, // End expanded feed nav link

                null, // End the top-level entry
            };

            ProjectedPropertiesAnnotation projectedProperties = testCase.TopLevelProjectedProperties;

            if (!testCase.NestedPayload)
            {
                this.Assert.IsNull(testCase.NestedProjectedProperties, "For a non-nested payload, no nested annotation must be specified.");
                entry.SetAnnotation(projectedProperties);
                return(entryItems);
            }

            // If we are processing a test case for a nested payload, wrap the entry items into a wrapping entry with an expanded navigation link.
            ODataEntry wrappingEntry = new ODataEntry()
            {
                TypeName   = "TestModel.WrappingEntityType",
                Properties = new[] { new ODataProperty {
                                         Name = "Wrapping_ID", Value = 1
                                     } },
                SerializationInfo = MySerializationInfo
            };
            IEnumerable <ODataItem> wrappedItems =
                new ODataItem[] { wrappingEntry, new ODataNavigationLink {
                                      Name = "Wrapping_ExpandedEntry", IsCollection = false, Url = new Uri("http://odata.org/wrapping")
                                  } }
            .Concat(entryItems)
            .Concat(new ODataItem[] { null, null });

            ProjectedPropertiesAnnotation nestedProjectedProperties = testCase.NestedProjectedProperties;

            entry.SetAnnotation(nestedProjectedProperties);
            wrappingEntry.SetAnnotation(projectedProperties);

            return(wrappedItems);
        }
        public void FlagsEnumAsComplexProperty_StrAsValue_StrAsTypeName()
        {
            DateTimeOffset updatedTime = DateTimeOffset.UtcNow;
            Func<ODataEntry> entryClone = () =>
            {
                var tmp = new ODataEntry
                {
                    TypeName = "NS.MyEntityType",
                    Properties = new[]
                    {
                        new ODataProperty{Name = "FloatId", Value = new ODataPrimitiveValue(12.3D)},       
                        new ODataProperty{Name = "Color", Value = new ODataEnumValue(Color.Green.ToString(), "NS.Color")},
                        new ODataProperty
                        {
                            Name = "MyComplexType",
                            Value = new ODataComplexValue { Properties = new[] { new ODataProperty { Name = "MyColorFlags", Value = new ODataEnumValue(Color.Red.ToString(), "NS.EnumUndefinedTypename") }, new ODataProperty { Name = "Height", Value = 98.6 }} }
                        }
                    },
                    SerializationInfo = MySerializationInfo
                };
                tmp.SetAnnotation(new AtomEntryMetadata() { Updated = updatedTime });
                return tmp;
            };

            // model-request
            string expectedPayload = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
                "<entry xmlns=\"http://www.w3.org/2005/Atom\" xmlns:d=\"http://docs.oasis-open.org/odata/ns/data\" xmlns:m=\"http://docs.oasis-open.org/odata/ns/metadata\" xmlns:georss=\"http://www.georss.org/georss\" xmlns:gml=\"http://www.opengis.net/gml\" m:context=\"http://odata.org/test/$metadata#MySet/$entity\">" +
                    "<category term=\"#NS.MyEntityType\" scheme=\"http://docs.oasis-open.org/odata/ns/scheme\" />" +
                    "<id />" +
                    "<title />" +
                    "<updated>" + ODataAtomConvert.ToAtomString(updatedTime) + "</updated>" +
                    "<author>" +
                        "<name />" +
                    "</author>" +
                    "<content type=\"application/xml\">" +
                        "<m:properties>" +
                            "<d:FloatId m:type=\"Double\">12.3</d:FloatId>" +
                            "<d:Color m:type=\"#NS.Color\">Green</d:Color>" +
                            "<d:MyComplexType m:type=\"#NS.MyComplexType\">" +
                                "<d:MyColorFlags m:type=\"#NS.EnumUndefinedTypename\">Red</d:MyColorFlags>" +
                                "<d:Height m:type=\"Double\">98.6</d:Height>" +
                            "</d:MyComplexType>" +
                        "</m:properties>" +
                    "</content>" +
                "</entry>";
            this.WriteRequestWithModelAndValidatePayload(nestedItemToWrite: new[] { entryClone() }, expectedPayload: expectedPayload);

            // model-reseponse
            this.WriteResponseWithModelAndValidatePayload(nestedItemToWrite: new[] { entryClone() }, expectedPayload: expectedPayload);

            // NoModel-request
            expectedPayload = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
                "<entry xmlns=\"http://www.w3.org/2005/Atom\" xmlns:d=\"http://docs.oasis-open.org/odata/ns/data\" xmlns:m=\"http://docs.oasis-open.org/odata/ns/metadata\" xmlns:georss=\"http://www.georss.org/georss\" xmlns:gml=\"http://www.opengis.net/gml\" m:context=\"http://odata.org/test/$metadata#MySet/$entity\">" +
                    "<category term=\"#NS.MyEntityType\" scheme=\"http://docs.oasis-open.org/odata/ns/scheme\" />" +
                    "<id />" +
                    "<title />" +
                    "<updated>" + ODataAtomConvert.ToAtomString(updatedTime) + "</updated>" +
                    "<author>" +
                        "<name />" +
                    "</author>" +
                    "<content type=\"application/xml\">" +
                        "<m:properties>" +
                            "<d:FloatId m:type=\"Double\">12.3</d:FloatId>" +
                            "<d:Color m:type=\"#NS.Color\">Green</d:Color>" +
                            "<d:MyComplexType>" +
                                "<d:MyColorFlags m:type=\"#NS.EnumUndefinedTypename\">Red</d:MyColorFlags>" +
                                "<d:Height m:type=\"Double\">98.6</d:Height>" +
                            "</d:MyComplexType>" +
                        "</m:properties>" +
                    "</content>" +
                "</entry>";
            this.WriteRequestWithoutModelAndValidatePayload(nestedItemToWrite: new[] { entryClone() }, expectedPayload: expectedPayload);

            // NoModel-response
            this.WriteResponseWithoutModelAndValidatePayload(nestedItemToWrite: new[] { entryClone() }, expectedPayload: expectedPayload);
        }