Exemplo n.º 1
0
        /// <summary>Initializes a new <see cref="PlainXmlDeserializer"/> based on the settings for another one.</summary>
        /// <param name="reader">Reader for content.</param>
        /// <param name="deserializer">Parent deserializer.</param>
        /// <param name="propertiesApplied">Properties already applied based on content</param>
        internal PlainXmlDeserializer(XmlReader reader, Deserializer deserializer, EpmContentDeSerializer.EpmAppliedPropertyInfo propertiesApplied)
            : base(deserializer)
        {
            Debug.Assert(reader != null, "reader != null");
            this.xmlReader = reader;
            Debug.Assert(propertiesApplied != null, "Requires valid collection for applied properties");
            this.propertiesApplied = propertiesApplied;
            this.currentPathPrefix = String.Empty;

            // this.xmlReaderOwned = false;
        }
Exemplo n.º 2
0
        /// <summary>Applies properties from the reader to the specified resource.</summary>
        /// <param name="deserializer">Deserializer which is driving the <paramref name="reader"/>.</param>
        /// <param name='reader'>XmlReader to read from.</param>
        /// <param name='resourceType'>Type of resource.</param>
        /// <param name='resource'>Resource to set value on.</param>
        /// <param name="propertiesApplied">Properties already applied based on content</param>
        /// <param name="currentObjectCount">current object count for this operation.</param>
        /// <remarks>
        /// This method will end as soon as it find something that is not an
        /// XML element to process.
        /// </remarks>
        internal static void ApplyContent(Deserializer deserializer, XmlReader reader, ResourceType resourceType, object resource, EpmContentDeSerializer.EpmAppliedPropertyInfo propertiesApplied, int currentObjectCount)
        {
            Debug.Assert(deserializer != null, "deserializer != null");
            Debug.Assert(reader != null, "reader != null");
            using (PlainXmlDeserializer xml = new PlainXmlDeserializer(reader, deserializer, propertiesApplied))
            {
                // Initialize the new deserializer instance with the current object count
                xml.UpdateObjectCount(currentObjectCount);

                // load all the properties
                xml.ApplyContent(xml.xmlReader, resourceType, resource);

                // After all the properties have been loaded, initialize the current deserializer value with the object count
                deserializer.UpdateObjectCount(xml.MaxObjectCount);
            }
        }
Exemplo n.º 3
0
        /// <summary>Reads the current object from the <paramref name="item"/>.</summary>
        /// <param name="segmentInfo">segmentinfo containing information about the current element that is getting processes</param>
        /// <param name="topLevel">true if the element currently pointed by the xml reader refers to a top level element</param>
        /// <param name="item">Item to read from.</param>
        /// <returns>returns the clr object with the data populated</returns>
        private object CreateObject(SegmentInfo segmentInfo, bool topLevel, SyndicationItem item)
        {
            Debug.Assert(item != null, "item != null");
            Debug.Assert(topLevel || !this.Update, "deep updates not supported");

            this.RecurseEnter();
            object result;

            // update the object count everytime you encounter a new resource
            this.CheckAndIncrementObjectCount();

            // Process the type annotation.
            ResourceType currentResourceType = this.GetResourceType(item, segmentInfo.TargetResourceType);

            if (currentResourceType.ResourceTypeKind != ResourceTypeKind.EntityType)
            {
                throw DataServiceException.CreateBadRequestError(Strings.BadRequest_OnlyEntityTypesMustBeSpecifiedInEntryElement(currentResourceType.FullName));
            }

            // We have the actual type info from the payload. Update the request/response DSV if any property is FF mapped with KeepInContent=false.
            this.UpdateAndCheckEpmRequestResponseDSV(currentResourceType, topLevel);

            // Get a resource cookie from the provider.
            ResourceSetWrapper container;

            if (segmentInfo.TargetKind == RequestTargetKind.OpenProperty)
            {
                // Open navigation properties are not supported on OpenTypes.
                throw DataServiceException.CreateBadRequestError(Strings.OpenNavigationPropertiesNotSupportedOnOpenTypes(segmentInfo.Identifier));
            }
            else
            {
                Debug.Assert(segmentInfo.TargetKind == RequestTargetKind.Resource, "segmentInfo.TargetKind == RequestTargetKind.Resource");
                container = segmentInfo.TargetContainer;
            }

            DataServiceHostWrapper host = this.Service.OperationContext.Host;

            if (this.Update)
            {
                Debug.Assert(currentResourceType.ResourceTypeKind == ResourceTypeKind.EntityType, "only expecting entity types");

                // Only verify ETag if there is going to be some update applied (that's the idea)
                // In reality:
                //   - for normal entities (V1 compatible) - don't check ETags if there is no content element. (Same as in V1)
                //   - for V2 stuff - check ETags always as we can't tell if there's going to be something modified or not
                //       with EPM properties can be anywhere in the payload and thus even without content there still can be updates
                //       with MLE the properties are not in the content element but in their own element
                // It's hard to recognize if there's going to be update up front and so this below is an approximation
                //   which seems to be good enough. Note that if we add new ways of handling properties in the content
                //   the condition below might need to change.
                bool verifyETag =
                    topLevel &&
                    (HasContent(item) || currentResourceType.HasEntityPropertyMappings || currentResourceType.IsMediaLinkEntry);
                bool replaceResource = topLevel && host.AstoriaHttpVerb == AstoriaVerbs.PUT;

                // if its a top level resource, then it cannot be null
                result = this.GetObjectFromSegmentInfo(currentResourceType, segmentInfo, verifyETag, topLevel /*checkForNull*/, replaceResource);
                if (this.Tracker != null)
                {
                    this.Tracker.TrackAction(result, container, UpdateOperations.Change);
                }
            }
            else
            {
                if (segmentInfo.TargetKind == RequestTargetKind.Resource)
                {
                    DataServiceConfiguration.CheckResourceRights(segmentInfo.TargetContainer, EntitySetRights.WriteAppend);
                }

                result = this.Updatable.CreateResource(container.Name, currentResourceType.FullName);
                if (this.Tracker != null)
                {
                    this.Tracker.TrackAction(result, container, UpdateOperations.Add);
                }
            }

            // Process the content in the entry.
            EpmContentDeSerializer.EpmAppliedPropertyInfo propertiesApplied = new EpmContentDeSerializer.EpmAppliedPropertyInfo();
            this.ApplyProperties(item, currentResourceType, propertiesApplied, result);

            // Perform application of epm properties here
            if (currentResourceType.HasEntityPropertyMappings)
            {
                new EpmContentDeSerializer(currentResourceType, result).DeSerialize(
                    item,
                    new EpmContentDeSerializer.EpmContentDeserializerState {
                    IsUpdateOperation = this.Update, Updatable = this.Updatable, Service = this.Service, PropertiesApplied = propertiesApplied
                });
            }

            // Process the links in the entry.
            foreach (SyndicationLink link in item.Links)
            {
                string navigationPropertyName = UriUtil.GetNameFromAtomLinkRelationAttribute(link.RelationshipType);

                if (null == navigationPropertyName)
                {
                    continue;
                }

                Deserializer.CheckForBindingInPutOperations(host.AstoriaHttpVerb);
                Debug.Assert(segmentInfo.TargetContainer != null, "segmentInfo.TargetContainer != null");
                this.ApplyLink(link, segmentInfo.TargetContainer, currentResourceType, result, navigationPropertyName);
            }

            this.RecurseLeave();
            return(result);
        }
Exemplo n.º 4
0
        /// <summary>Applies the properties in the plain XML content to the specified resource.</summary>
        /// <param name="item">item to read from.</param>
        /// <param name='resourceType'>Type of resource whose values are being set.</param>
        /// <param name="propertiesApplied">Properties that have been applied to the <paramref name="resource"/></param>
        /// <param name='resource'>Target resource.</param>
        private void ApplyProperties(SyndicationItem item, ResourceType resourceType, EpmContentDeSerializer.EpmAppliedPropertyInfo propertiesApplied, object resource)
        {
            Debug.Assert(item != null, "item != null");
            Debug.Assert(resourceType != null, "resourceType != null");
            Debug.Assert(propertiesApplied != null, "propertiesApplied != null");
            Debug.Assert(resource != null, "resource != null");

            using (XmlReader propertiesFromEntry = GetPropertiesReaderFromEntry(item))
                using (XmlReader propertiesFromContent = GetPropertiesReaderFromContent(item))
                {
                    XmlReader reader = null;

                    if (resourceType.IsMediaLinkEntry)
                    {
                        if (propertiesFromContent != null)
                        {
                            // The server is expecting a MLE payload, however we found a <m:properties> element under the <atom:content> element.
                            // The client must assumed the resource type is a non-MLE type and serialized as such.
                            //
                            // We must throw here otherwise the client would falsely assume all the properties are correctly deserialized on
                            // the server where as in fact the properties element is under the wrong node.
                            throw DataServiceException.CreateBadRequestError(Strings.DataServiceException_GeneralError);
                        }

                        reader = propertiesFromEntry;
                    }
                    else
                    {
                        if (propertiesFromEntry != null)
                        {
                            // The server is expecting a non-MLE payload, however we found a <m:properties> element under the <entry> element.
                            // The client must assumed the resource type is a MLE type and serialized as such.
                            //
                            // We must throw here otherwise the client would falsely assume all the properties are correctly deserialized on
                            // the server where as in fact the properties element is under the wrong node.
                            throw DataServiceException.CreateBadRequestError(Strings.DataServiceException_GeneralError);
                        }

                        reader = propertiesFromContent;
                    }

                    if (reader != null)
                    {
                        reader.ReadStartElement(XmlConstants.AtomPropertiesElementName, XmlConstants.DataWebMetadataNamespace);
                        PlainXmlDeserializer.ApplyContent(this, reader, resourceType, resource, propertiesApplied, this.MaxObjectCount);
                    }
                }
        }