private object DeserializeArrayXmlSerializer(System.Xml.XmlDictionaryReader xmlReader, Type parameterType, string parameterName, string parameterNs, ICustomAttributeProvider customAttributeProvider) { var xmlArrayAttributes = customAttributeProvider.GetCustomAttributes(typeof(XmlArrayItemAttribute), true); XmlArrayItemAttribute xmlArrayItemAttribute = xmlArrayAttributes.FirstOrDefault() as XmlArrayItemAttribute; var xmlElementAttributes = customAttributeProvider.GetCustomAttributes(typeof(XmlElementAttribute), true); XmlElementAttribute xmlElementAttribute = xmlElementAttributes.FirstOrDefault() as XmlElementAttribute; var isEmpty = xmlReader.IsEmptyElement; var hasContainerElement = xmlElementAttribute == null; if (hasContainerElement) { xmlReader.ReadStartElement(parameterName, parameterNs); } var elementType = parameterType.GetElementType(); var arrayItemName = xmlArrayItemAttribute?.ElementName ?? xmlElementAttribute?.ElementName ?? elementType.Name; if (xmlArrayItemAttribute?.ElementName == null && elementType.Namespace?.StartsWith("System") == true) { var compiler = new CSharpCodeProvider(); var type = new CodeTypeReference(elementType); arrayItemName = compiler.GetTypeOutput(type); } var deserializeMethod = typeof(XmlSerializerExtensions).GetGenericMethod(nameof(XmlSerializerExtensions.DeserializeArray), elementType); var arrayItemNamespace = xmlArrayItemAttribute?.Namespace ?? parameterNs; var serializer = CachedXmlSerializer.GetXmlSerializer(elementType, arrayItemName, arrayItemNamespace); object result = null; lock (serializer) { if (xmlReader.HasValue && elementType?.FullName == "System.Byte") { result = xmlReader.ReadContentAsBase64(); } else { result = deserializeMethod.Invoke(null, new object[] { serializer, arrayItemName, arrayItemNamespace, xmlReader }); } } if (!isEmpty && hasContainerElement) { xmlReader.ReadEndElement(); } return(result); }
private object DeserializeObject(System.Xml.XmlDictionaryReader xmlReader, Type parameterType, string parameterName, string parameterNs) { // see https://referencesource.microsoft.com/System.Xml/System/Xml/Serialization/XmlSerializer.cs.html#c97688a6c07294d5 var elementType = parameterType.GetElementType(); if (elementType == null || parameterType.IsArray) { elementType = parameterType; } var serializer = CachedXmlSerializer.GetXmlSerializer(elementType, parameterName, parameterNs); lock (serializer) { return(serializer.Deserialize(xmlReader)); } }
private object DeserializeArray(System.Xml.XmlDictionaryReader xmlReader, Type parameterType, string parameterName, string parameterNs, SoapMethodParameterInfo parameterInfo) { var isEmpty = xmlReader.IsEmptyElement; //if (parameterInfo.ArrayItemName != null) { xmlReader.ReadStartElement(parameterName, parameterNs); } var elementType = parameterType.GetElementType(); var localName = parameterInfo.ArrayItemName ?? elementType.Name; if (parameterInfo.ArrayItemName == null && elementType.Namespace.StartsWith("System")) { var compiler = new CSharpCodeProvider(); var type = new CodeTypeReference(elementType); localName = compiler.GetTypeOutput(type); } //localName = "ComplexModelInput"; var deserializeMethod = typeof(XmlSerializerExtensions).GetGenericMethod(nameof(XmlSerializerExtensions.DeserializeArray), elementType); var serializer = CachedXmlSerializer.GetXmlSerializer(elementType, localName, parameterNs); object result = null; lock (serializer) { result = deserializeMethod.Invoke(null, new object[] { serializer, localName, parameterNs, xmlReader }); } //if (parameterInfo.ArrayItemName != null) if (!isEmpty) { xmlReader.ReadEndElement(); } return(result); }
private object DeserializeArrayXmlSerializer(System.Xml.XmlDictionaryReader xmlReader, Type parameterType, string parameterName, string parameterNs, MemberInfo memberInfo) { XmlArrayItemAttribute xmlArrayItemAttribute = memberInfo.GetCustomAttribute(typeof(XmlArrayItemAttribute)) as XmlArrayItemAttribute; var isEmpty = xmlReader.IsEmptyElement; xmlReader.ReadStartElement(parameterName, parameterNs); var elementType = parameterType.GetElementType(); var arrayItemName = xmlArrayItemAttribute?.ElementName ?? elementType.Name; if (xmlArrayItemAttribute?.ElementName == null && elementType.Namespace?.StartsWith("System") == true) { var compiler = new CSharpCodeProvider(); var type = new CodeTypeReference(elementType); arrayItemName = compiler.GetTypeOutput(type); } var deserializeMethod = typeof(XmlSerializerExtensions).GetGenericMethod(nameof(XmlSerializerExtensions.DeserializeArray), elementType); var arrayItemNamespace = xmlArrayItemAttribute?.Namespace ?? parameterNs; var serializer = CachedXmlSerializer.GetXmlSerializer(elementType, arrayItemName, arrayItemNamespace); object result = null; lock (serializer) { result = deserializeMethod.Invoke(null, new object[] { serializer, arrayItemName, arrayItemNamespace, xmlReader }); } if (!isEmpty) { xmlReader.ReadEndElement(); } return(result); }
private static object DeserializeObject(System.Xml.XmlDictionaryReader xmlReader, Type parameterType, string parameterName, string parameterNs) { // see https://referencesource.microsoft.com/System.Xml/System/Xml/Serialization/XmlSerializer.cs.html#c97688a6c07294d5 var elementType = parameterType.GetElementType(); if (elementType == null || parameterType.IsArray) { elementType = parameterType; } var serializer = CachedXmlSerializer.GetXmlSerializer(elementType, parameterName, parameterNs); lock (serializer) { if (elementType == typeof(Stream) || typeof(Stream).IsAssignableFrom(elementType)) { xmlReader.Read(); return(new MemoryStream(xmlReader.ReadContentAsBase64())); } return(serializer.Deserialize(xmlReader)); } }
private object[] GetRequestArguments(Message requestMessage, System.Xml.XmlDictionaryReader xmlReader, OperationDescription operation, ref Dictionary <string, object> outArgs) { var parameters = operation.NormalParameters; // avoid reallocation var arguments = new List <object>(parameters.Length + operation.OutParameters.Length); // Find the element for the operation's data xmlReader.ReadStartElement(operation.Name, operation.Contract.Namespace); for (int i = 0; i < parameters.Length; i++) { var parameterName = parameters[i].Name; var parameterNs = parameters[i].Namespace; if (xmlReader.IsStartElement(parameterName, parameterNs)) { xmlReader.MoveToStartElement(parameterName, parameterNs); if (xmlReader.IsStartElement(parameterName, parameterNs)) { var elementType = parameters[i].Parameter.ParameterType.GetElementType(); if (elementType == null || parameters[i].Parameter.ParameterType.IsArray) { elementType = parameters[i].Parameter.ParameterType; } switch (_serializer) { case SoapSerializer.XmlSerializer: { // see https://referencesource.microsoft.com/System.Xml/System/Xml/Serialization/XmlSerializer.cs.html#c97688a6c07294d5 var serializer = CachedXmlSerializer.GetXmlSerializer(elementType, parameterName, parameterNs); lock (serializer) arguments.Add(serializer.Deserialize(xmlReader)); } break; case SoapSerializer.DataContractSerializer: { var serializer = new DataContractSerializer(elementType, parameterName, parameterNs); arguments.Add(serializer.ReadObject(xmlReader, verifyObjectName: true)); } break; default: throw new NotImplementedException(); } } } else { arguments.Add(null); } } foreach (var parameterInfo in operation.OutParameters) { if (parameterInfo.Parameter.ParameterType.Name == "Guid&") { outArgs[parameterInfo.Name] = Guid.Empty; } else if (parameterInfo.Parameter.ParameterType.Name == "String&" || parameterInfo.Parameter.ParameterType.GetElementType().IsArray) { outArgs[parameterInfo.Name] = null; } else { var type = parameterInfo.Parameter.ParameterType.GetElementType(); outArgs[parameterInfo.Name] = Activator.CreateInstance(type); } } return(arguments.ToArray()); }
private void OnWriteXmlSerializerBodyContents(XmlDictionaryWriter writer) { Debug.Assert(_outResults != null, "Object should set empty out results"); // Do not wrap old-style single element response into additional xml element for xml serializer var needResponseEnvelope = _result == null || (_outResults.Count > 0) || !_operation.IsMessageContractResponse; if (needResponseEnvelope) { writer.WriteStartElement(_envelopeName, _serviceNamespace); } foreach (var outResult in _outResults) { string value = null; if (outResult.Value is Guid) { value = outResult.Value.ToString(); } else if (outResult.Value is bool) { value = outResult.Value.ToString().ToLower(); } else if (outResult.Value is string) { value = System.Security.SecurityElement.Escape(outResult.Value.ToString()); } else if (outResult.Value is Enum) { value = outResult.Value.ToString(); } else if (outResult.Value == null) { value = null; } else { //for complex types using (var ms = new MemoryStream()) using (var stream = new BufferedStream(ms)) { // write element with name as outResult.Key and type information as outResultType // i.e. <outResult.Key xsi:type="outResultType" ... /> var outResultType = outResult.Value.GetType(); var serializer = CachedXmlSerializer.GetXmlSerializer(outResultType, outResult.Key, _serviceNamespace); lock (serializer) { serializer.Serialize(stream, outResult.Value); } //add outResultType. ugly, but working stream.Position = 0; XmlDocument xdoc = new XmlDocument(); xdoc.Load(stream); var attr = xdoc.CreateAttribute("xsi", "type", "http://www.w3.org/2001/XMLSchema-instance"); attr.Value = outResultType.Name; xdoc.DocumentElement.Attributes.Prepend(attr); writer.WriteRaw(xdoc.DocumentElement.OuterXml); } } if (value != null) { writer.WriteRaw(string.Format("<{0}>{1}</{0}>", outResult.Key, value)); } } if (_result != null) { // see https://referencesource.microsoft.com/System.Xml/System/Xml/Serialization/XmlSerializer.cs.html#c97688a6c07294d5 var resultType = _result.GetType(); var xmlRootAttr = resultType.GetTypeInfo().GetCustomAttributes <XmlRootAttribute>().FirstOrDefault(); var xmlName = _operation.ReturnElementName ?? (needResponseEnvelope ? _resultName : (string.IsNullOrWhiteSpace(xmlRootAttr?.ElementName) ? resultType.Name : xmlRootAttr.ElementName)); var xmlNs = _operation.ReturnNamespace ?? (string.IsNullOrWhiteSpace(xmlRootAttr?.Namespace) ? _serviceNamespace : xmlRootAttr.Namespace); var xmlArrayAttr = _operation.DispatchMethod.GetCustomAttribute <XmlArrayAttribute>(); if (xmlArrayAttr != null && resultType.IsArray) { var serializer = CachedXmlSerializer.GetXmlSerializer(resultType.GetElementType(), xmlName, xmlNs); lock (serializer) { serializer.SerializeArray(writer, (object[])_result); } } else { var messageContractAttribute = resultType.GetCustomAttribute <MessageContractAttribute>(); // This behavior is opt-in i.e. you have to explicitly have a [MessageContract(IsWrapped=false)] // to have the message body members inlined. var shouldInline = messageContractAttribute != null && messageContractAttribute.IsWrapped == false; if (shouldInline) { var memberInformation = resultType .GetPropertyOrFieldMembers() .Select(mi => new { Member = mi, MessageBodyMemberAttribute = mi.GetCustomAttribute <MessageBodyMemberAttribute>() }) .OrderBy(x => x.MessageBodyMemberAttribute?.Order ?? 0); foreach (var memberInfo in memberInformation) { var memberType = memberInfo.Member.GetPropertyOrFieldType(); var memberValue = memberInfo.Member.GetPropertyOrFieldValue(_result); var memberName = memberInfo.MessageBodyMemberAttribute?.Name ?? memberInfo.Member.Name; var memberNamespace = memberInfo.MessageBodyMemberAttribute?.Namespace ?? xmlNs; var serializer = CachedXmlSerializer.GetXmlSerializer(memberType, memberName, memberNamespace); lock (serializer) { serializer.Serialize(writer, memberValue); } } } else { var serializer = CachedXmlSerializer.GetXmlSerializer(resultType, xmlName, xmlNs); lock (serializer) { serializer.Serialize(writer, _result); } } } } if (needResponseEnvelope) { writer.WriteEndElement(); } }
protected override void OnWriteBodyContents(XmlDictionaryWriter writer) { // do not wrap old-style single element response into additional xml element for xml serializer var needResponseEnvelope = _serializer != SoapSerializer.XmlSerializer || _result == null || (_outResults != null && _outResults.Count > 0) || !_operation.IsMessageContractResponse; if (needResponseEnvelope) { writer.WriteStartElement(_envelopeName, _serviceNamespace); } if (_outResults != null) { foreach (var outResult in _outResults) { string value = null; if (outResult.Value is Guid) { value = outResult.Value.ToString(); } else if (outResult.Value is bool) { value = outResult.Value.ToString().ToLower(); } else if (outResult.Value is string) { value = System.Security.SecurityElement.Escape(outResult.Value.ToString()); } else if (outResult.Value is Enum) { value = outResult.Value.ToString(); } else if (outResult.Value == null) { value = null; } //for complex types else { using (var ms = new MemoryStream()) using (var stream = new BufferedStream(ms)) { switch (_serializer) { case SoapSerializer.XmlSerializer: // write element with name as outResult.Key and type information as outResultType // i.e. <outResult.Key xsi:type="outResultType" ... /> var outResultType = outResult.Value.GetType(); var serializer = CachedXmlSerializer.GetXmlSerializer(outResultType, outResult.Key, _serviceNamespace); lock (serializer) { serializer.Serialize(stream, outResult.Value); } //add outResultType. ugly, but working stream.Position = 0; XmlDocument xdoc = new XmlDocument(); xdoc.Load(stream); var attr = xdoc.CreateAttribute("xsi", "type", "http://www.w3.org/2001/XMLSchema-instance"); attr.Value = outResultType.Name; xdoc.DocumentElement.Attributes.Prepend(attr); writer.WriteRaw(xdoc.DocumentElement.OuterXml); break; case SoapSerializer.DataContractSerializer: new DataContractSerializer(outResult.Value.GetType()).WriteObject(ms, outResult.Value); stream.Position = 0; using (var reader = XmlReader.Create(stream)) { reader.MoveToContent(); value = reader.ReadInnerXml(); } break; default: throw new NotImplementedException(); } } } if (value != null) { writer.WriteRaw(string.Format("<{0}>{1}</{0}>", outResult.Key, value)); } } } if (_result != null) { switch (_serializer) { case SoapSerializer.XmlSerializer: { // see https://referencesource.microsoft.com/System.Xml/System/Xml/Serialization/XmlSerializer.cs.html#c97688a6c07294d5 var resultType = _result.GetType(); var serializer = CachedXmlSerializer.GetXmlSerializer(resultType, needResponseEnvelope ? _resultName : resultType.Name, _serviceNamespace); lock (serializer) { serializer.Serialize(writer, _result); } } break; case SoapSerializer.DataContractSerializer: { var serializer = new DataContractSerializer(_result.GetType(), _resultName, _serviceNamespace); serializer.WriteObject(writer, _result); } break; default: throw new NotImplementedException(); } } if (needResponseEnvelope) { writer.WriteEndElement(); } }
private object[] GetRequestArguments(Message requestMessage, System.Xml.XmlDictionaryReader xmlReader, OperationDescription operation) { var arguments = new object[operation.AllParameters.Length]; // Find the element for the operation's data if (!operation.IsMessageContractRequest) { xmlReader.ReadStartElement(operation.Name, operation.Contract.Namespace); } // if any ordering issues, possible to rewrite like: /*while (!xmlReader.EOF) * { * var parameterInfo = operation.InParameters.FirstOrDefault(p => p.Name == xmlReader.LocalName && p.Namespace == xmlReader.NamespaceURI); * if (parameterInfo == null) * { * xmlReader.Skip(); * continue; * } * var parameterName = parameterInfo.Name; * var parameterNs = parameterInfo.Namespace; * ... * }*/ foreach (var parameterInfo in operation.InParameters) { var parameterName = parameterInfo.Name; var parameterNs = parameterInfo.Namespace; if (xmlReader.IsStartElement(parameterName, parameterNs)) { xmlReader.MoveToStartElement(parameterName, parameterNs); if (xmlReader.IsStartElement(parameterName, parameterNs)) { var elementType = parameterInfo.Parameter.ParameterType.GetElementType(); if (elementType == null || parameterInfo.Parameter.ParameterType.IsArray) { elementType = parameterInfo.Parameter.ParameterType; } switch (_serializer) { case SoapSerializer.XmlSerializer: { // see https://referencesource.microsoft.com/System.Xml/System/Xml/Serialization/XmlSerializer.cs.html#c97688a6c07294d5 var serializer = CachedXmlSerializer.GetXmlSerializer(elementType, parameterName, parameterNs); lock (serializer) { arguments[parameterInfo.Index] = serializer.Deserialize(xmlReader); } } break; case SoapSerializer.DataContractSerializer: { var serializer = new DataContractSerializer(elementType, parameterName, parameterNs); arguments[parameterInfo.Index] = serializer.ReadObject(xmlReader, verifyObjectName: true); } break; default: throw new NotImplementedException(); } } } else { arguments[parameterInfo.Index] = null; } } foreach (var parameterInfo in operation.OutParameters) { if (arguments[parameterInfo.Index] != null) { // do not overwrite input ref parameters continue; } if (parameterInfo.Parameter.ParameterType.Name == "Guid&") { arguments[parameterInfo.Index] = Guid.Empty; } else if (parameterInfo.Parameter.ParameterType.Name == "String&" || parameterInfo.Parameter.ParameterType.GetElementType().IsArray) { arguments[parameterInfo.Index] = null; } else { var type = parameterInfo.Parameter.ParameterType.GetElementType(); arguments[parameterInfo.Index] = Activator.CreateInstance(type); } } return(arguments); }
private object[] GetRequestArguments(Message requestMessage, System.Xml.XmlDictionaryReader xmlReader, OperationDescription operation, HttpContext httpContext) { var arguments = new object[operation.AllParameters.Length]; // Find the element for the operation's data if (!operation.IsMessageContractRequest) { xmlReader.ReadStartElement(operation.Name, operation.Contract.Namespace); } // if any ordering issues, possible to rewrite like: /*while (!xmlReader.EOF) * { * var parameterInfo = operation.InParameters.FirstOrDefault(p => p.Name == xmlReader.LocalName && p.Namespace == xmlReader.NamespaceURI); * if (parameterInfo == null) * { * xmlReader.Skip(); * continue; * } * var parameterName = parameterInfo.Name; * var parameterNs = parameterInfo.Namespace; * ... * }*/ foreach (var parameterInfo in operation.InParameters) { var parameterName = parameterInfo.Name; var parameterNs = parameterInfo.Namespace ?? operation.Contract.Namespace; if (xmlReader.IsStartElement(parameterName, parameterNs)) { xmlReader.MoveToStartElement(parameterName, parameterNs); if (xmlReader.IsStartElement(parameterName, parameterNs)) { switch (_serializer) { case SoapSerializer.XmlSerializer: { // case [XmlElement("parameter")] int parameter // case int[] parameter // case [XmlArray("parameter")] int[] parameter if (!parameterInfo.Parameter.ParameterType.IsArray || (parameterInfo.ArrayName != null && parameterInfo.ArrayItemName == null)) { // see https://referencesource.microsoft.com/System.Xml/System/Xml/Serialization/XmlSerializer.cs.html#c97688a6c07294d5 var elementType = parameterInfo.Parameter.ParameterType.GetElementType(); if (elementType == null || parameterInfo.Parameter.ParameterType.IsArray) { elementType = parameterInfo.Parameter.ParameterType; } var serializer = CachedXmlSerializer.GetXmlSerializer(elementType, parameterName, parameterNs); lock (serializer) { arguments[parameterInfo.Index] = serializer.Deserialize(xmlReader); } } // case [XmlElement("parameter")] int[] parameter // case [XmlArray("parameter"), XmlArrayItem(ElementName = "item")] int[] parameter else { //if (parameterInfo.ArrayItemName != null) { xmlReader.ReadStartElement(parameterName, parameterNs); } var elementType = parameterInfo.Parameter.ParameterType.GetElementType(); var localName = parameterInfo.ArrayItemName ?? elementType.Name; if (parameterInfo.ArrayItemName == null && elementType.Namespace.StartsWith("System")) { localName = localName.ToLower(); } //localName = "ComplexModelInput"; var deserializeMethod = typeof(XmlSerializerExtensions) .GetGenericMethod(nameof(XmlSerializerExtensions.DeserializeArray), new[] { elementType }); var serializer = CachedXmlSerializer.GetXmlSerializer(elementType, localName, parameterNs); lock (serializer) { arguments[parameterInfo.Index] = deserializeMethod.Invoke(null, new object[] { serializer, localName, parameterNs, xmlReader }); } //if (parameterInfo.ArrayItemName != null) { xmlReader.ReadEndElement(); } } } break; case SoapSerializer.DataContractSerializer: { var elementType = parameterInfo.Parameter.ParameterType.GetElementType(); if (elementType == null || parameterInfo.Parameter.ParameterType.IsArray) { elementType = parameterInfo.Parameter.ParameterType; } var serializer = new DataContractSerializer(elementType, parameterName, parameterNs); arguments[parameterInfo.Index] = serializer.ReadObject(xmlReader, verifyObjectName: true); } break; default: throw new NotImplementedException(); } } } else if (parameterInfo.Parameter.ParameterType == typeof(HttpContext)) { arguments[parameterInfo.Index] = httpContext; } else { arguments[parameterInfo.Index] = null; } } foreach (var parameterInfo in operation.OutParameters) { if (arguments[parameterInfo.Index] != null) { // do not overwrite input ref parameters continue; } if (parameterInfo.Parameter.ParameterType.Name == "Guid&") { arguments[parameterInfo.Index] = Guid.Empty; } else if (parameterInfo.Parameter.ParameterType.Name == "String&" || parameterInfo.Parameter.ParameterType.GetElementType().IsArray) { arguments[parameterInfo.Index] = null; } else { var type = parameterInfo.Parameter.ParameterType.GetElementType(); arguments[parameterInfo.Index] = Activator.CreateInstance(type); } } return(arguments); }
protected override void OnWriteBodyContents(XmlDictionaryWriter writer) { writer.WriteStartElement(_envelopeName, _serviceNamespace); if (_outResults != null) { foreach (var outResult in _outResults) { string value; if (outResult.Value is Guid) { value = outResult.Value.ToString(); } else if (outResult.Value is bool) { value = outResult.Value.ToString().ToLower(); } else if (outResult.Value is string) { value = SecurityElement.Escape(outResult.Value.ToString()); } else if (outResult.Value is Enum) { value = outResult.Value.ToString(); } else if (outResult.Value == null) { value = null; } else //for complex types { using (var ms = new MemoryStream()) using (var stream = new BufferedStream(ms)) { switch (_serializer) { case SoapSerializer.XmlSerializer: new XmlSerializer(outResult.Value.GetType()).Serialize(ms, outResult.Value); break; case SoapSerializer.DataContractSerializer: new DataContractSerializer(outResult.Value.GetType()).WriteObject(ms, outResult.Value); break; default: throw new NotImplementedException(); } stream.Position = 0; using (var reader = XmlReader.Create(stream)) { reader.MoveToContent(); value = reader.ReadInnerXml(); } } } if (value != null) { writer.WriteRaw(string.Format("<{0}>{1}</{0}>", outResult.Key, value)); } } } if (_result != null) { switch (_serializer) { case SoapSerializer.XmlSerializer: { // see https://referencesource.microsoft.com/System.Xml/System/Xml/Serialization/XmlSerializer.cs.html#c97688a6c07294d5 var serializer = CachedXmlSerializer.GetXmlSerializer(_result.GetType(), _resultName, _serviceNamespace); lock (serializer) serializer.Serialize(writer, _result); } break; case SoapSerializer.DataContractSerializer: { var serializer = new DataContractSerializer(_result.GetType(), _resultName, _serviceNamespace); serializer.WriteObject(writer, _result); } break; default: throw new NotImplementedException(); } } writer.WriteEndElement(); }