Code:
/ Net / Net / 3.5.50727.3053 / DEVDIV / depot / DevDiv / releases / Orcas / SP / ndp / fx / src / DataWeb / Server / System / Data / Services / Serializers / PlainXmlDeserializer.cs / 3 / PlainXmlDeserializer.cs
//----------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Provides a deserializer for plain XML content.
//
//
// @owner [....]
//---------------------------------------------------------------------
namespace System.Data.Services.Serializers
{
using System;
using System.Diagnostics;
using System.IO;
using System.Text;
using System.Xml;
using System.Data.Services.Parsing;
using System.Data.Services.Providers;
/// Provides a deserializer for plain XML content.
internal class PlainXmlDeserializer : Deserializer
{
/// reader to read xml from the request stream
private readonly XmlReader xmlReader;
/// Whether is owned and should be disposed of.
private readonly bool xmlReaderOwned;
/// Initializes a new for the specified stream.
/// Input stream reader from which POX content must be read.
/// Encoding to use for the stream (null to auto-discover).
/// Data service for which the deserializer will act.
/// Indicates whether this is a PUT operation (rather than POST).
/// Tracker to use for modifications.
internal PlainXmlDeserializer(Stream stream, Encoding encoding, IDataService dataService, bool update, UpdateTracker tracker)
: base(update, dataService, tracker)
{
Debug.Assert(stream != null, "stream != null");
this.xmlReader = XmlUtil.CreateXmlReader(stream, encoding);
this.xmlReaderOwned = true;
}
/// Initializes a new based on the settings for another one.
/// Reader for content.
/// Parent deserializer.
internal PlainXmlDeserializer(XmlReader reader, Deserializer deserializer)
: base(deserializer)
{
Debug.Assert(reader != null, "reader != null");
this.xmlReader = reader;
// this.xmlReaderOwned = false;
}
/// Returns the content format for the deserializer.
protected override ContentFormat ContentFormat
{
get
{
return ContentFormat.PlainXml;
}
}
/// Applies properties from the reader to the specified resource.
/// Deserializer which is driving the .
/// XmlReader to read from.
/// Type of resource.
/// Resource to set value on.
/// current object count for this operation.
///
/// This method will end as soon as it find something that is not an
/// XML element to process.
///
internal static void ApplyContent(Deserializer deserializer, XmlReader reader, ResourceType resourceType, object resource, int currentObjectCount)
{
Debug.Assert(deserializer != null, "deserializer != null");
Debug.Assert(reader != null, "reader != null");
using (PlainXmlDeserializer xml = new PlainXmlDeserializer(reader, deserializer))
{
// 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);
}
}
///
/// Converts the given value to the expected type as per XML serializer rules.
/// Make sure these rules are in [....] with PlainXmlSerializer.
///
/// value to the converted
/// name of the property whose value is getting converted
/// clr type to which the value needs to be converted to
/// object which is in [....] with the properties type
internal static object ConvertValuesForXml(object value, string propertyName, Type typeToBeConverted)
{
Debug.Assert(WebUtil.IsPrimitiveType(typeToBeConverted), "WebUtil.IsPrimitiveType(typeToBeConverted)");
string stringValue = value as string;
if (stringValue != null)
{
try
{
value = WebConvert.StringToPrimitive(stringValue, typeToBeConverted);
}
catch (FormatException e)
{
throw DataServiceException.CreateBadRequestError(Strings.BadRequest_ErrorInConvertingPropertyValue(propertyName, typeToBeConverted), e);
}
}
return value;
}
///
/// Assumes the payload to represent a single object and processes accordingly
///
/// info about the object being created
/// the newly formed object that the payload represents
protected override object CreateSingleObject(SegmentInfo segmentInfo)
{
Debug.Assert(
#if ASTORIA_OPEN_OBJECT
segmentInfo.TargetKind == RequestTargetKind.OpenProperty ||
#endif
segmentInfo.TargetKind == RequestTargetKind.ComplexObject ||
segmentInfo.TargetKind == RequestTargetKind.Primitive,
segmentInfo.TargetKind + " is one of open property; complex object; primitive -- otherwise the wrong serializer was chosen");
if (!WebUtil.XmlReaderEnsureElement(this.xmlReader))
{
throw DataServiceException.CreateBadRequestError(Strings.PlainXml_PayloadLacksElement);
}
if (HasNullAttributeWithTrueValue(this.xmlReader))
{
return null;
}
ResourceType resourceType;
string propertyName;
#if ASTORIA_OPEN_OBJECT
if (segmentInfo.TargetKind == RequestTargetKind.OpenProperty)
{
bool typeNameSpecified;
resourceType = this.ReadOpenPropertyTypeAttribute(this.xmlReader, out typeNameSpecified);
if (resourceType.ResourceTypeKind == ResourceTypeKind.EntityType)
{
throw DataServiceException.CreateBadRequestError(
Strings.PlainXml_EntityTypeNotSupported(resourceType.Type));
}
Debug.Assert(resourceType != null, "resourceType != null");
propertyName = this.xmlReader.LocalName;
}
else
#endif
{
Debug.Assert(segmentInfo.ProjectedProperty != null, "segmentInfo.ProjectedProperty != null");
resourceType = segmentInfo.ProjectedProperty.ResourceType;
propertyName = segmentInfo.ProjectedProperty.Name;
if (propertyName != this.xmlReader.LocalName)
{
throw DataServiceException.CreateBadRequestError(
Strings.PlainXml_IncorrectElementName(propertyName, this.xmlReader.LocalName));
}
}
object result = this.ReadPropertyWithType(this.xmlReader, propertyName, resourceType);
return result;
}
/// Provides an opportunity to clean-up resources.
///
/// Whether the call is being made from an explicit call to
/// IDisposable.Dispose() rather than through the finalizer.
///
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (disposing && this.xmlReaderOwned)
{
this.xmlReader.Close();
}
}
///
/// Get the resource referred by the uri in the payload
///
/// resource referred by the uri in the payload.
protected override string GetLinkUriFromPayload()
{
if (!WebUtil.XmlReaderEnsureElement(this.xmlReader))
{
throw DataServiceException.CreateBadRequestError(Strings.PlainXml_PayloadLacksElement);
}
string uri = null;
bool skipped;
do
{
skipped = false;
switch (this.xmlReader.NodeType)
{
case XmlNodeType.Element:
string localName = this.xmlReader.LocalName;
string elementNamespace = this.xmlReader.NamespaceURI;
if (elementNamespace != XmlConstants.DataWebMetadataNamespace ||
localName != XmlConstants.UriElementName)
{
this.xmlReader.Skip();
skipped = true;
continue;
}
if (uri != null)
{
throw DataServiceException.CreateBadRequestError(Strings.BadRequest_MoreThanOneUriElementSpecified);
}
uri = ReadElementString(this.xmlReader, localName);
if (String.IsNullOrEmpty(uri))
{
throw DataServiceException.CreateBadRequestError(Strings.BadRequest_MissingUriForLinkOperation);
}
break;
default:
break;
}
}
while (skipped || this.xmlReader.Read());
Debug.Assert(
this.xmlReader.NodeType != XmlNodeType.Element,
"reader.NodeType != XmlNodeType.Element -- otherwise we should have kept processing");
if (String.IsNullOrEmpty(uri))
{
throw DataServiceException.CreateBadRequestError(Strings.BadRequest_MissingUriForLinkOperation);
}
return uri;
}
///
/// returns true if the null attribute is specified and the value is true
///
/// xml reader from which attribute needs to be read
/// true if the null attribute is specified and the attribute value is true
private static bool HasNullAttributeWithTrueValue(XmlReader reader)
{
Debug.Assert(reader != null, "reader != null");
Debug.Assert(reader.NodeType == XmlNodeType.Element, "reader.NodeType == XmlNodeType.Element");
string elementValue = reader.GetAttribute(XmlConstants.AtomNullAttributeName, XmlConstants.DataWebMetadataNamespace);
// If the null attribute is specified and the value is true, then set the property value to null,
// otherwise set the value to empty string
if ((null != elementValue) && XmlConvert.ToBoolean(elementValue))
{
string elementName = reader.LocalName;
if (!reader.IsEmptyElement)
{
reader.Read();
if (reader.NodeType != XmlNodeType.EndElement)
{
throw DataServiceException.CreateBadRequestError(
Strings.BadRequest_CannotSpecifyValueOrChildElementsForNullElement(elementName));
}
}
return true;
}
return false;
}
///
/// Reads the value from the given element. This leaves the reader in the EndElement.
///
/// xml reader from which the value needs to be read
/// name of the element whose value is getting read
/// returns the xml string values as specified in the payload
private static string ReadElementString(XmlReader reader, string elementName)
{
Debug.Assert(reader != null, "reader != null");
Debug.Assert(XmlNodeType.Element == reader.NodeType, "not positioned on Element");
string elementValue = null;
if (HasNullAttributeWithTrueValue(reader))
{
return null;
}
else if (reader.IsEmptyElement)
{
return String.Empty;
}
StringBuilder builder = null;
bool done = false;
while (!done && reader.Read())
{
switch (reader.NodeType)
{
case XmlNodeType.EndElement:
done = true;
break;
case XmlNodeType.CDATA:
case XmlNodeType.Text:
case XmlNodeType.SignificantWhitespace:
if (elementValue == null)
{
elementValue = reader.Value;
}
else if (builder == null)
{
string newValue = reader.Value;
builder = new StringBuilder(newValue.Length + elementValue.Length);
builder.Append(elementValue);
builder.Append(newValue);
}
else
{
builder.Append(reader.Value);
}
break;
case XmlNodeType.Comment:
case XmlNodeType.Whitespace:
break;
#region XmlNodeType error
case XmlNodeType.None:
case XmlNodeType.XmlDeclaration:
case XmlNodeType.Attribute:
case XmlNodeType.EndEntity:
case XmlNodeType.EntityReference:
case XmlNodeType.Entity:
case XmlNodeType.Document:
case XmlNodeType.DocumentType:
case XmlNodeType.DocumentFragment:
case XmlNodeType.Notation:
case XmlNodeType.ProcessingInstruction:
default:
throw DataServiceException.CreateBadRequestError(Strings.BadRequest_InvalidValue(elementName));
#endregion
}
}
if (builder != null)
{
elementValue = builder.ToString();
}
else if (elementValue == null)
{
elementValue = String.Empty;
}
return elementValue;
}
/// Applies properties from the reader to the specified resource.
/// XmlReader to read from.
/// Type of resource.
/// Resource to set value on.
///
/// This method will end as soon as it find something that is not an
/// XML element to process.
///
private void ApplyContent(XmlReader reader, ResourceType resourceType, object resource)
{
Debug.Assert(resourceType != null, "resourceType != null");
Debug.Assert(resource != null, "resource != null");
if (!WebUtil.XmlReaderEnsureElement(reader))
{
return;
}
this.RecurseEnter();
bool skipped;
do
{
skipped = false;
switch (reader.NodeType)
{
case XmlNodeType.Element:
string localName = reader.LocalName;
string elementNamespace = reader.NamespaceURI;
if (elementNamespace != XmlConstants.DataWebNamespace)
{
reader.Skip();
skipped = true;
continue;
}
this.ApplyProperty(reader, localName, resourceType, resource);
break;
default:
break;
}
}
while (skipped || reader.Read());
Debug.Assert(
reader.NodeType != XmlNodeType.Element,
"reader.NodeType != XmlNodeType.Element -- otherwise we should have kept processing");
this.RecurseLeave();
}
/// Applies a property from the reader to the specified resource.
/// XmlReader to read from.
/// Name of property to set on the specified resource.
/// Type of resource.
/// Resource to set value on.
private void ApplyProperty(XmlReader reader, string propertyName, ResourceType resourceType, object resource)
{
Debug.Assert(reader != null, "reader != null");
Debug.Assert(propertyName != null, "propertyName != null");
Debug.Assert(resourceType != null, "resourceType != null");
Debug.Assert(resource != null, "resource != null");
ResourceProperty property = resourceType.TryResolvePropertyName(propertyName);
ResourceType propertyType;
bool ignoreValue = false;
if (property == null)
{
#if ASTORIA_OPEN_OBJECT
if (resourceType.OpenTypeKind != OpenTypeKind.CompletelyOpen)
#endif
{
throw DataServiceException.CreateBadRequestError(Strings.BadRequest_InvalidPropertyNameSpecified(propertyName, resourceType.FullName));
}
#if ASTORIA_OPEN_OBJECT
bool typeNameSpecified;
propertyType = this.ReadOpenPropertyTypeAttribute(reader, out typeNameSpecified);
#endif
}
else
{
propertyType = property.ResourceType;
if (this.Update && property.IsOfKind(ResourcePropertyKind.Key))
{
ignoreValue = true;
}
}
object propertyValue = this.ReadPropertyWithType(reader, propertyName, propertyType);
if (!ignoreValue)
{
this.Service.Provider.SetValue(resource, propertyName, propertyValue);
}
}
#if ASTORIA_OPEN_OBJECT
/// Gets the type attribute and resolves the type.
/// reader from which type attribute needs to be read
/// true if the reader contains a type attribute otherwise false
/// resolved type
private ResourceType ReadOpenPropertyTypeAttribute(XmlReader reader, out bool typeNameSpecified)
{
Debug.Assert(reader != null, "reader != null");
string typeName = reader.GetAttribute(XmlConstants.AtomTypeAttributeName, XmlConstants.DataWebMetadataNamespace);
ResourceType resourceType = null;
// If the type is not specified in the payload, we assume the type to be the expected type
if (String.IsNullOrEmpty(typeName))
{
typeNameSpecified = false;
resourceType = this.Service.Provider.GetResourceType(typeof(string));
}
else
{
typeNameSpecified = true;
// try and resolve the name specified in the payload
resourceType = this.Service.Provider.TryResolveTypeName(typeName);
if (resourceType == null)
{
throw DataServiceException.CreateBadRequestError(Strings.BadRequest_InvalidTypeName(typeName));
}
}
return resourceType;
}
#endif
/// Reads a typed property from the specified XmlReader.
/// XmlReader to read from.
/// Name of property to read.
/// Type of property to read.
/// The instance read, possibly null.
private object ReadPropertyWithType(XmlReader reader, string propertyName, ResourceType propertyType)
{
Debug.Assert(reader != null, "reader != null");
Debug.Assert(propertyName != null, "propertyName != null");
Debug.Assert(propertyType != null, "propertyType != null");
object propertyValue;
switch (propertyType.ResourceTypeKind)
{
case ResourceTypeKind.ComplexType:
this.CheckAndIncrementObjectCount();
if (HasNullAttributeWithTrueValue(reader))
{
propertyValue = null;
}
else
{
propertyValue = this.Service.Provider.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();
ApplyContent(propertyReader, propertyType, propertyValue);
}
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);
string stringValue = ReadElementString(reader, propertyName);
propertyValue = PlainXmlDeserializer.ConvertValuesForXml(stringValue, propertyName, propertyType.Type);
break;
}
return propertyValue;
}
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//----------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Provides a deserializer for plain XML content.
//
//
// @owner [....]
//---------------------------------------------------------------------
namespace System.Data.Services.Serializers
{
using System;
using System.Diagnostics;
using System.IO;
using System.Text;
using System.Xml;
using System.Data.Services.Parsing;
using System.Data.Services.Providers;
/// Provides a deserializer for plain XML content.
internal class PlainXmlDeserializer : Deserializer
{
/// reader to read xml from the request stream
private readonly XmlReader xmlReader;
/// Whether is owned and should be disposed of.
private readonly bool xmlReaderOwned;
/// Initializes a new for the specified stream.
/// Input stream reader from which POX content must be read.
/// Encoding to use for the stream (null to auto-discover).
/// Data service for which the deserializer will act.
/// Indicates whether this is a PUT operation (rather than POST).
/// Tracker to use for modifications.
internal PlainXmlDeserializer(Stream stream, Encoding encoding, IDataService dataService, bool update, UpdateTracker tracker)
: base(update, dataService, tracker)
{
Debug.Assert(stream != null, "stream != null");
this.xmlReader = XmlUtil.CreateXmlReader(stream, encoding);
this.xmlReaderOwned = true;
}
/// Initializes a new based on the settings for another one.
/// Reader for content.
/// Parent deserializer.
internal PlainXmlDeserializer(XmlReader reader, Deserializer deserializer)
: base(deserializer)
{
Debug.Assert(reader != null, "reader != null");
this.xmlReader = reader;
// this.xmlReaderOwned = false;
}
/// Returns the content format for the deserializer.
protected override ContentFormat ContentFormat
{
get
{
return ContentFormat.PlainXml;
}
}
/// Applies properties from the reader to the specified resource.
/// Deserializer which is driving the .
/// XmlReader to read from.
/// Type of resource.
/// Resource to set value on.
/// current object count for this operation.
///
/// This method will end as soon as it find something that is not an
/// XML element to process.
///
internal static void ApplyContent(Deserializer deserializer, XmlReader reader, ResourceType resourceType, object resource, int currentObjectCount)
{
Debug.Assert(deserializer != null, "deserializer != null");
Debug.Assert(reader != null, "reader != null");
using (PlainXmlDeserializer xml = new PlainXmlDeserializer(reader, deserializer))
{
// 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);
}
}
///
/// Converts the given value to the expected type as per XML serializer rules.
/// Make sure these rules are in [....] with PlainXmlSerializer.
///
/// value to the converted
/// name of the property whose value is getting converted
/// clr type to which the value needs to be converted to
/// object which is in [....] with the properties type
internal static object ConvertValuesForXml(object value, string propertyName, Type typeToBeConverted)
{
Debug.Assert(WebUtil.IsPrimitiveType(typeToBeConverted), "WebUtil.IsPrimitiveType(typeToBeConverted)");
string stringValue = value as string;
if (stringValue != null)
{
try
{
value = WebConvert.StringToPrimitive(stringValue, typeToBeConverted);
}
catch (FormatException e)
{
throw DataServiceException.CreateBadRequestError(Strings.BadRequest_ErrorInConvertingPropertyValue(propertyName, typeToBeConverted), e);
}
}
return value;
}
///
/// Assumes the payload to represent a single object and processes accordingly
///
/// info about the object being created
/// the newly formed object that the payload represents
protected override object CreateSingleObject(SegmentInfo segmentInfo)
{
Debug.Assert(
#if ASTORIA_OPEN_OBJECT
segmentInfo.TargetKind == RequestTargetKind.OpenProperty ||
#endif
segmentInfo.TargetKind == RequestTargetKind.ComplexObject ||
segmentInfo.TargetKind == RequestTargetKind.Primitive,
segmentInfo.TargetKind + " is one of open property; complex object; primitive -- otherwise the wrong serializer was chosen");
if (!WebUtil.XmlReaderEnsureElement(this.xmlReader))
{
throw DataServiceException.CreateBadRequestError(Strings.PlainXml_PayloadLacksElement);
}
if (HasNullAttributeWithTrueValue(this.xmlReader))
{
return null;
}
ResourceType resourceType;
string propertyName;
#if ASTORIA_OPEN_OBJECT
if (segmentInfo.TargetKind == RequestTargetKind.OpenProperty)
{
bool typeNameSpecified;
resourceType = this.ReadOpenPropertyTypeAttribute(this.xmlReader, out typeNameSpecified);
if (resourceType.ResourceTypeKind == ResourceTypeKind.EntityType)
{
throw DataServiceException.CreateBadRequestError(
Strings.PlainXml_EntityTypeNotSupported(resourceType.Type));
}
Debug.Assert(resourceType != null, "resourceType != null");
propertyName = this.xmlReader.LocalName;
}
else
#endif
{
Debug.Assert(segmentInfo.ProjectedProperty != null, "segmentInfo.ProjectedProperty != null");
resourceType = segmentInfo.ProjectedProperty.ResourceType;
propertyName = segmentInfo.ProjectedProperty.Name;
if (propertyName != this.xmlReader.LocalName)
{
throw DataServiceException.CreateBadRequestError(
Strings.PlainXml_IncorrectElementName(propertyName, this.xmlReader.LocalName));
}
}
object result = this.ReadPropertyWithType(this.xmlReader, propertyName, resourceType);
return result;
}
/// Provides an opportunity to clean-up resources.
///
/// Whether the call is being made from an explicit call to
/// IDisposable.Dispose() rather than through the finalizer.
///
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (disposing && this.xmlReaderOwned)
{
this.xmlReader.Close();
}
}
///
/// Get the resource referred by the uri in the payload
///
/// resource referred by the uri in the payload.
protected override string GetLinkUriFromPayload()
{
if (!WebUtil.XmlReaderEnsureElement(this.xmlReader))
{
throw DataServiceException.CreateBadRequestError(Strings.PlainXml_PayloadLacksElement);
}
string uri = null;
bool skipped;
do
{
skipped = false;
switch (this.xmlReader.NodeType)
{
case XmlNodeType.Element:
string localName = this.xmlReader.LocalName;
string elementNamespace = this.xmlReader.NamespaceURI;
if (elementNamespace != XmlConstants.DataWebMetadataNamespace ||
localName != XmlConstants.UriElementName)
{
this.xmlReader.Skip();
skipped = true;
continue;
}
if (uri != null)
{
throw DataServiceException.CreateBadRequestError(Strings.BadRequest_MoreThanOneUriElementSpecified);
}
uri = ReadElementString(this.xmlReader, localName);
if (String.IsNullOrEmpty(uri))
{
throw DataServiceException.CreateBadRequestError(Strings.BadRequest_MissingUriForLinkOperation);
}
break;
default:
break;
}
}
while (skipped || this.xmlReader.Read());
Debug.Assert(
this.xmlReader.NodeType != XmlNodeType.Element,
"reader.NodeType != XmlNodeType.Element -- otherwise we should have kept processing");
if (String.IsNullOrEmpty(uri))
{
throw DataServiceException.CreateBadRequestError(Strings.BadRequest_MissingUriForLinkOperation);
}
return uri;
}
///
/// returns true if the null attribute is specified and the value is true
///
/// xml reader from which attribute needs to be read
/// true if the null attribute is specified and the attribute value is true
private static bool HasNullAttributeWithTrueValue(XmlReader reader)
{
Debug.Assert(reader != null, "reader != null");
Debug.Assert(reader.NodeType == XmlNodeType.Element, "reader.NodeType == XmlNodeType.Element");
string elementValue = reader.GetAttribute(XmlConstants.AtomNullAttributeName, XmlConstants.DataWebMetadataNamespace);
// If the null attribute is specified and the value is true, then set the property value to null,
// otherwise set the value to empty string
if ((null != elementValue) && XmlConvert.ToBoolean(elementValue))
{
string elementName = reader.LocalName;
if (!reader.IsEmptyElement)
{
reader.Read();
if (reader.NodeType != XmlNodeType.EndElement)
{
throw DataServiceException.CreateBadRequestError(
Strings.BadRequest_CannotSpecifyValueOrChildElementsForNullElement(elementName));
}
}
return true;
}
return false;
}
///
/// Reads the value from the given element. This leaves the reader in the EndElement.
///
/// xml reader from which the value needs to be read
/// name of the element whose value is getting read
/// returns the xml string values as specified in the payload
private static string ReadElementString(XmlReader reader, string elementName)
{
Debug.Assert(reader != null, "reader != null");
Debug.Assert(XmlNodeType.Element == reader.NodeType, "not positioned on Element");
string elementValue = null;
if (HasNullAttributeWithTrueValue(reader))
{
return null;
}
else if (reader.IsEmptyElement)
{
return String.Empty;
}
StringBuilder builder = null;
bool done = false;
while (!done && reader.Read())
{
switch (reader.NodeType)
{
case XmlNodeType.EndElement:
done = true;
break;
case XmlNodeType.CDATA:
case XmlNodeType.Text:
case XmlNodeType.SignificantWhitespace:
if (elementValue == null)
{
elementValue = reader.Value;
}
else if (builder == null)
{
string newValue = reader.Value;
builder = new StringBuilder(newValue.Length + elementValue.Length);
builder.Append(elementValue);
builder.Append(newValue);
}
else
{
builder.Append(reader.Value);
}
break;
case XmlNodeType.Comment:
case XmlNodeType.Whitespace:
break;
#region XmlNodeType error
case XmlNodeType.None:
case XmlNodeType.XmlDeclaration:
case XmlNodeType.Attribute:
case XmlNodeType.EndEntity:
case XmlNodeType.EntityReference:
case XmlNodeType.Entity:
case XmlNodeType.Document:
case XmlNodeType.DocumentType:
case XmlNodeType.DocumentFragment:
case XmlNodeType.Notation:
case XmlNodeType.ProcessingInstruction:
default:
throw DataServiceException.CreateBadRequestError(Strings.BadRequest_InvalidValue(elementName));
#endregion
}
}
if (builder != null)
{
elementValue = builder.ToString();
}
else if (elementValue == null)
{
elementValue = String.Empty;
}
return elementValue;
}
/// Applies properties from the reader to the specified resource.
/// XmlReader to read from.
/// Type of resource.
/// Resource to set value on.
///
/// This method will end as soon as it find something that is not an
/// XML element to process.
///
private void ApplyContent(XmlReader reader, ResourceType resourceType, object resource)
{
Debug.Assert(resourceType != null, "resourceType != null");
Debug.Assert(resource != null, "resource != null");
if (!WebUtil.XmlReaderEnsureElement(reader))
{
return;
}
this.RecurseEnter();
bool skipped;
do
{
skipped = false;
switch (reader.NodeType)
{
case XmlNodeType.Element:
string localName = reader.LocalName;
string elementNamespace = reader.NamespaceURI;
if (elementNamespace != XmlConstants.DataWebNamespace)
{
reader.Skip();
skipped = true;
continue;
}
this.ApplyProperty(reader, localName, resourceType, resource);
break;
default:
break;
}
}
while (skipped || reader.Read());
Debug.Assert(
reader.NodeType != XmlNodeType.Element,
"reader.NodeType != XmlNodeType.Element -- otherwise we should have kept processing");
this.RecurseLeave();
}
/// Applies a property from the reader to the specified resource.
/// XmlReader to read from.
/// Name of property to set on the specified resource.
/// Type of resource.
/// Resource to set value on.
private void ApplyProperty(XmlReader reader, string propertyName, ResourceType resourceType, object resource)
{
Debug.Assert(reader != null, "reader != null");
Debug.Assert(propertyName != null, "propertyName != null");
Debug.Assert(resourceType != null, "resourceType != null");
Debug.Assert(resource != null, "resource != null");
ResourceProperty property = resourceType.TryResolvePropertyName(propertyName);
ResourceType propertyType;
bool ignoreValue = false;
if (property == null)
{
#if ASTORIA_OPEN_OBJECT
if (resourceType.OpenTypeKind != OpenTypeKind.CompletelyOpen)
#endif
{
throw DataServiceException.CreateBadRequestError(Strings.BadRequest_InvalidPropertyNameSpecified(propertyName, resourceType.FullName));
}
#if ASTORIA_OPEN_OBJECT
bool typeNameSpecified;
propertyType = this.ReadOpenPropertyTypeAttribute(reader, out typeNameSpecified);
#endif
}
else
{
propertyType = property.ResourceType;
if (this.Update && property.IsOfKind(ResourcePropertyKind.Key))
{
ignoreValue = true;
}
}
object propertyValue = this.ReadPropertyWithType(reader, propertyName, propertyType);
if (!ignoreValue)
{
this.Service.Provider.SetValue(resource, propertyName, propertyValue);
}
}
#if ASTORIA_OPEN_OBJECT
/// Gets the type attribute and resolves the type.
/// reader from which type attribute needs to be read
/// true if the reader contains a type attribute otherwise false
/// resolved type
private ResourceType ReadOpenPropertyTypeAttribute(XmlReader reader, out bool typeNameSpecified)
{
Debug.Assert(reader != null, "reader != null");
string typeName = reader.GetAttribute(XmlConstants.AtomTypeAttributeName, XmlConstants.DataWebMetadataNamespace);
ResourceType resourceType = null;
// If the type is not specified in the payload, we assume the type to be the expected type
if (String.IsNullOrEmpty(typeName))
{
typeNameSpecified = false;
resourceType = this.Service.Provider.GetResourceType(typeof(string));
}
else
{
typeNameSpecified = true;
// try and resolve the name specified in the payload
resourceType = this.Service.Provider.TryResolveTypeName(typeName);
if (resourceType == null)
{
throw DataServiceException.CreateBadRequestError(Strings.BadRequest_InvalidTypeName(typeName));
}
}
return resourceType;
}
#endif
/// Reads a typed property from the specified XmlReader.
/// XmlReader to read from.
/// Name of property to read.
/// Type of property to read.
/// The instance read, possibly null.
private object ReadPropertyWithType(XmlReader reader, string propertyName, ResourceType propertyType)
{
Debug.Assert(reader != null, "reader != null");
Debug.Assert(propertyName != null, "propertyName != null");
Debug.Assert(propertyType != null, "propertyType != null");
object propertyValue;
switch (propertyType.ResourceTypeKind)
{
case ResourceTypeKind.ComplexType:
this.CheckAndIncrementObjectCount();
if (HasNullAttributeWithTrueValue(reader))
{
propertyValue = null;
}
else
{
propertyValue = this.Service.Provider.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();
ApplyContent(propertyReader, propertyType, propertyValue);
}
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);
string stringValue = ReadElementString(reader, propertyName);
propertyValue = PlainXmlDeserializer.ConvertValuesForXml(stringValue, propertyName, propertyType.Type);
break;
}
return propertyValue;
}
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- ComponentResourceKey.cs
- WinCategoryAttribute.cs
- MultiViewDesigner.cs
- BufferedGraphics.cs
- XmlnsCompatibleWithAttribute.cs
- BitmapDecoder.cs
- BaseCollection.cs
- OracleCommandSet.cs
- XmlUtil.cs
- TextPointerBase.cs
- XmlSchemaObject.cs
- MulticastNotSupportedException.cs
- controlskin.cs
- SecurityPolicyVersion.cs
- COM2TypeInfoProcessor.cs
- Models.cs
- RadioButtonList.cs
- SymLanguageType.cs
- XmlAttributeOverrides.cs
- PtsCache.cs
- PropertyDescriptorGridEntry.cs
- Pkcs7Recipient.cs
- precedingquery.cs
- XmlValidatingReader.cs
- MachineKeySection.cs
- CopyNamespacesAction.cs
- FileDialog.cs
- ScrollProviderWrapper.cs
- FragmentNavigationEventArgs.cs
- ProjectionNode.cs
- TdsParserSessionPool.cs
- ComponentDispatcherThread.cs
- BuildResult.cs
- DocumentSequenceHighlightLayer.cs
- ScrollEventArgs.cs
- ConnectionsZone.cs
- SoapServerMessage.cs
- CompositeActivityTypeDescriptor.cs
- BitmapEffectInput.cs
- NameScopePropertyAttribute.cs
- RandomDelayQueuedSendsAsyncResult.cs
- CompilerResults.cs
- ConfigurationValidatorAttribute.cs
- RemoteWebConfigurationHostServer.cs
- LinqDataSourceStatusEventArgs.cs
- Italic.cs
- SafeBitVector32.cs
- initElementDictionary.cs
- SwitchAttribute.cs
- TextRangeEditLists.cs
- ScrollViewer.cs
- InkPresenterAutomationPeer.cs
- XslTransform.cs
- TransformGroup.cs
- RotateTransform3D.cs
- SharedPerformanceCounter.cs
- AppSettingsSection.cs
- SchemaObjectWriter.cs
- ScriptIgnoreAttribute.cs
- QueryContinueDragEventArgs.cs
- PopOutPanel.cs
- ProcessHostFactoryHelper.cs
- safex509handles.cs
- HttpListenerResponse.cs
- QilValidationVisitor.cs
- CapiHashAlgorithm.cs
- CompilerResults.cs
- URL.cs
- SlipBehavior.cs
- EntityClientCacheEntry.cs
- TypeConverterHelper.cs
- SignerInfo.cs
- AppDomainManager.cs
- ExpressionEditorAttribute.cs
- WebDescriptionAttribute.cs
- HebrewCalendar.cs
- RegexRunnerFactory.cs
- SqlDataSourceCommandEventArgs.cs
- _AutoWebProxyScriptWrapper.cs
- CodeIndexerExpression.cs
- ColorConvertedBitmap.cs
- ColumnHeaderConverter.cs
- CollectionsUtil.cs
- WindowsUserNameSecurityTokenAuthenticator.cs
- SpecularMaterial.cs
- X509AsymmetricSecurityKey.cs
- ScrollData.cs
- CopyNamespacesAction.cs
- PermissionSetEnumerator.cs
- TextStore.cs
- MemoryFailPoint.cs
- QueryableFilterUserControl.cs
- IncrementalReadDecoders.cs
- MetadataArtifactLoaderResource.cs
- ContentElementAutomationPeer.cs
- PrintDialog.cs
- MultiPropertyDescriptorGridEntry.cs
- RawAppCommandInputReport.cs
- CompModSwitches.cs
- BinaryFormatter.cs