예제 #1
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);
                    }
                }
        }
예제 #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);
            }
        }
        /// <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);
            }
        }
예제 #4
0
        /// <summary>Reads a typed property from the specified XmlReader.</summary>
        /// <param name='reader'>XmlReader to read from.</param>
        /// <param name='propertyName'>Name of property to read.</param>
        /// <param name='resourceProperty'>resourceProperty whose value is to be read.</param>
        /// <returns>The instance read, possibly null.</returns>
        private object ReadPropertyWithType(XmlReader reader, string propertyName, ResourceProperty resourceProperty)
        {
            Debug.Assert(reader != null, "reader != null");
            Debug.Assert(propertyName != null, "propertyName != null");
            ResourceType propertyType = null;

            // If this is a open property OR we do not have to do type conversion for primitive types,
            // read the type from the payload.
            bool readTypeFromWire =
                resourceProperty == null ||
                (!this.Service.Configuration.EnableTypeConversion && resourceProperty.ResourceType.ResourceTypeKind == ResourceTypeKind.Primitive);

            if (readTypeFromWire)
            {
                propertyType = this.ReadOpenPropertyTypeAttribute(reader);
            }
            else
            {
                propertyType = resourceProperty.ResourceType;
            }

            if (this.propertiesApplied != null)
            {
                this.propertiesApplied.AddPropertyToTypeMapItem(
                    this.BuildPropertyPath(propertyName),
                    propertyType.FullName);
            }

            object propertyValue;
            String appliedPropertyName = resourceProperty != null ? resourceProperty.Name : propertyName;

            switch (propertyType.ResourceTypeKind)
            {
            case ResourceTypeKind.ComplexType:
                this.CheckAndIncrementObjectCount();

                bool isNull = HasNullAttributeWithTrueValue(reader);
                if (this.propertiesApplied != null)
                {
                    this.propertiesApplied.AddAppliedProperty(this.BuildPropertyPath(appliedPropertyName), isNull);
                }

                if (isNull)
                {
                    propertyValue = null;
                }
                else
                {
                    propertyValue = this.Updatable.CreateResource(null, propertyType.FullName);
                    if (!reader.IsEmptyElement)
                    {
                        // Step inside the complex type, apply its properties, and pop back out.
                        using (XmlReader propertyReader = reader.ReadSubtree())
                        {
                            if (!WebUtil.XmlReaderEnsureElement(propertyReader))
                            {
                                throw DataServiceException.CreateBadRequestError(
                                          Strings.PlainXml_PropertyLacksElement(propertyName));
                            }

                            propertyReader.ReadStartElement();
                            String savedPath = this.currentPathPrefix;
                            this.currentPathPrefix = String.IsNullOrEmpty(this.currentPathPrefix) ? appliedPropertyName : this.currentPathPrefix + "/" + appliedPropertyName;
                            ApplyContent(propertyReader, propertyType, propertyValue);
                            this.currentPathPrefix = savedPath;
                        }

                        Debug.Assert(
                            reader.NodeType == XmlNodeType.EndElement,
                            "reader.NodeType == XmlNodeType.EndElement -- otherwise ReadSubtree left outer read in incorrect position.");
                    }
                }

                break;

            case ResourceTypeKind.EntityType:
                throw DataServiceException.CreateBadRequestError(
                          Strings.PlainXml_NavigationPropertyNotSupported(propertyName));

            default:
                Debug.Assert(
                    propertyType.ResourceTypeKind == ResourceTypeKind.Primitive,
                    "property.TypeKind == ResourceTypeKind.Primitive -- metadata shouldn't return " + propertyType.ResourceTypeKind);

                propertyValue = ReadElementString(reader, propertyName);

                // We need to convert the type to the wire type. Conversion to the property type happens in Deserializer.SetValue method.
                if (readTypeFromWire)
                {
                    propertyValue = PlainXmlDeserializer.ConvertValuesForXml(propertyValue, propertyName, propertyType.InstanceType);
                }

                if (this.propertiesApplied != null)
                {
                    this.propertiesApplied.AddAppliedProperty(this.BuildPropertyPath(appliedPropertyName), false);
                }

                break;
            }

            return(propertyValue);
        }
예제 #5
0
        /// <summary>
        /// Creates a new <see cref="Deserializer"/> for the specified stream.
        /// </summary>
        /// <param name="description">description about the request uri.</param>
        /// <param name="dataService">Data service for which the deserializer will act.</param>
        /// <param name="update">indicates whether this is a update operation or not</param>
        /// <param name="tracker">Tracker to use for modifications.</param>
        /// <returns>A new instance of <see cref="Deserializer"/>.</returns>
        internal static Deserializer CreateDeserializer(RequestDescription description, IDataService dataService, bool update, UpdateTracker tracker)
        {
            string mimeType;
            System.Text.Encoding encoding;
            DataServiceHostWrapper host = dataService.OperationContext.Host;
            HttpProcessUtility.ReadContentType(host.RequestContentType, out mimeType, out encoding);
            ContentFormat requestFormat = WebUtil.SelectRequestFormat(mimeType, description);
            Stream requestStream = host.RequestStream;
            Debug.Assert(requestStream != null, "requestStream != null");
            Debug.Assert(tracker != null, "Change tracker must always be created.");
            Deserializer deserializer = null;

            Debug.Assert(
                (!update /*POST*/ && dataService.OperationContext.Host.AstoriaHttpVerb == AstoriaVerbs.POST) ||
                (update /*PUT,MERGE*/ && (dataService.OperationContext.Host.AstoriaHttpVerb == AstoriaVerbs.MERGE || dataService.OperationContext.Host.AstoriaHttpVerb == AstoriaVerbs.PUT)),
                "For PUT and MERGE, update must be true; for POST, update must be false");

            switch (requestFormat)
            {
                case ContentFormat.Json:
                    deserializer = new JsonDeserializer(
                        requestStream,
                        encoding,
                        update,
                        dataService,
                        tracker);
                    break;
                case ContentFormat.Atom:
                    SyndicationFormatterFactory factory = new Atom10FormatterFactory();
                    deserializer = new SyndicationDeserializer(
                        requestStream,  // stream
                        encoding,       // encoding
                        dataService,    // dataService
                        update,
                        factory,
                        tracker);       // factory
                    break;
                case ContentFormat.PlainXml:
                    deserializer = new PlainXmlDeserializer(
                        requestStream,
                        encoding,
                        dataService,
                        update,
                        tracker);
                    break;
                default:
                    throw new DataServiceException(415, Strings.BadRequest_UnsupportedRequestContentType(host.RequestContentType));
            }

            Debug.Assert(deserializer != null, "deserializer != null");

            return deserializer;
        }