| | | 1 | | // Licensed to the .NET Foundation under one or more agreements. |
| | | 2 | | // The .NET Foundation licenses this file to you under the MIT license. |
| | | 3 | | |
| | | 4 | | using System; |
| | | 5 | | using System.Collections; |
| | | 6 | | using System.Collections.Generic; |
| | | 7 | | using System.IO; |
| | | 8 | | using System.Reflection; |
| | | 9 | | using System.Xml; |
| | | 10 | | using System.Xml.Serialization; |
| | | 11 | | using CoreWCF.Channels; |
| | | 12 | | using CoreWCF.Description; |
| | | 13 | | |
| | | 14 | | namespace CoreWCF.Dispatcher |
| | | 15 | | { |
| | | 16 | | internal class XmlSerializerOperationFormatter : OperationFormatter |
| | | 17 | | { |
| | | 18 | | private const string soap11Encoding = "http://schemas.xmlsoap.org/soap/encoding/"; |
| | | 19 | | private const string soap12Encoding = "http://www.w3.org/2003/05/soap-encoding"; |
| | | 20 | | private readonly bool _isEncoded; |
| | | 21 | | private readonly MessageInfo _requestMessageInfo; |
| | | 22 | | private readonly MessageInfo _replyMessageInfo; |
| | | 23 | | |
| | | 24 | | public XmlSerializerOperationFormatter(OperationDescription description, XmlSerializerFormatAttribute xmlSeriali |
| | | 25 | | MessageInfo requestMessageInfo, MessageInfo replyMessageInfo) : |
| | 50 | 26 | | base(description, xmlSerializerFormatAttribute.Style == OperationFormatStyle.Rpc, xmlSerializerFormatAttribu |
| | | 27 | | { |
| | 50 | 28 | | if (xmlSerializerFormatAttribute.IsEncoded && xmlSerializerFormatAttribute.Style != OperationFormatStyle.Rpc |
| | | 29 | | { |
| | 0 | 30 | | throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.Format(SR.SFx |
| | | 31 | | } |
| | | 32 | | |
| | 50 | 33 | | _isEncoded = xmlSerializerFormatAttribute.IsEncoded; |
| | | 34 | | |
| | 50 | 35 | | _requestMessageInfo = requestMessageInfo; |
| | 50 | 36 | | _replyMessageInfo = replyMessageInfo; |
| | 50 | 37 | | } |
| | | 38 | | |
| | | 39 | | protected override void AddHeadersToMessage(Message message, MessageDescription messageDescription, object[] par |
| | | 40 | | { |
| | | 41 | | XmlSerializer serializer; |
| | | 42 | | MessageHeaderDescriptionTable headerDescriptionTable; |
| | | 43 | | MessageHeaderDescription unknownHeaderDescription; |
| | | 44 | | bool mustUnderstand; |
| | | 45 | | bool relay; |
| | | 46 | | string actor; |
| | | 47 | | try |
| | | 48 | | { |
| | 21 | 49 | | if (isRequest) |
| | | 50 | | { |
| | 0 | 51 | | serializer = _requestMessageInfo.HeaderSerializer; |
| | 0 | 52 | | headerDescriptionTable = _requestMessageInfo.HeaderDescriptionTable; |
| | 0 | 53 | | unknownHeaderDescription = _requestMessageInfo.UnknownHeaderDescription; |
| | | 54 | | } |
| | | 55 | | else |
| | | 56 | | { |
| | 21 | 57 | | serializer = _replyMessageInfo.HeaderSerializer; |
| | 21 | 58 | | headerDescriptionTable = _replyMessageInfo.HeaderDescriptionTable; |
| | 21 | 59 | | unknownHeaderDescription = _replyMessageInfo.UnknownHeaderDescription; |
| | | 60 | | } |
| | 21 | 61 | | if (serializer != null) |
| | | 62 | | { |
| | 1 | 63 | | object[] headerValues = new object[headerDescriptionTable.Count]; |
| | 1 | 64 | | MessageHeaderOfTHelper messageHeaderOfTHelper = null; |
| | 1 | 65 | | int headerIndex = 0; |
| | | 66 | | |
| | 6 | 67 | | foreach (MessageHeaderDescription headerDescription in messageDescription.Headers) |
| | | 68 | | { |
| | 2 | 69 | | object parameterValue = parameters[headerDescription.Index]; |
| | 2 | 70 | | if (!headerDescription.IsUnknownHeaderCollection) |
| | | 71 | | { |
| | 2 | 72 | | if (headerDescription.TypedHeader) |
| | | 73 | | { |
| | 0 | 74 | | if (messageHeaderOfTHelper == null) |
| | | 75 | | { |
| | 0 | 76 | | messageHeaderOfTHelper = new MessageHeaderOfTHelper(parameters.Length); |
| | | 77 | | } |
| | | 78 | | |
| | 0 | 79 | | headerValues[headerIndex++] = messageHeaderOfTHelper.GetContentAndSaveHeaderAttributes(p |
| | | 80 | | } |
| | | 81 | | else |
| | | 82 | | { |
| | 2 | 83 | | headerValues[headerIndex++] = parameterValue; |
| | | 84 | | } |
| | | 85 | | } |
| | | 86 | | } |
| | | 87 | | |
| | 1 | 88 | | MemoryStream memoryStream = new MemoryStream(); |
| | 1 | 89 | | XmlDictionaryWriter bufferWriter = XmlDictionaryWriter.CreateTextWriter(memoryStream); |
| | 1 | 90 | | bufferWriter.WriteStartElement("root"); |
| | 1 | 91 | | serializer.Serialize(bufferWriter, headerValues, null, _isEncoded ? GetEncoding(message.Version.Enve |
| | 1 | 92 | | bufferWriter.WriteEndElement(); |
| | 1 | 93 | | bufferWriter.Flush(); |
| | 1 | 94 | | XmlDocument doc = new XmlDocument(); |
| | 1 | 95 | | memoryStream.Position = 0; |
| | 1 | 96 | | doc.Load(memoryStream); |
| | | 97 | | |
| | | 98 | | //TODO: XmlTextReader supported in .Net Standard 1.7, prohibiting DtdProcessing is important |
| | | 99 | | //doc.Load(new XmlTextReader(memoryStream) { DtdProcessing = DtdProcessing.Prohibit }); |
| | | 100 | | //doc.Save(Console.Out); |
| | | 101 | | |
| | 10 | 102 | | foreach (XmlElement element in doc.DocumentElement.ChildNodes) |
| | | 103 | | { |
| | 4 | 104 | | MessageHeaderDescription matchingHeaderDescription = headerDescriptionTable.Get(element.LocalNam |
| | 4 | 105 | | if (matchingHeaderDescription == null) |
| | | 106 | | { |
| | 0 | 107 | | message.Headers.Add(new XmlElementMessageHeader(this, message.Version, element.LocalName, el |
| | 0 | 108 | | false/*mustUnderstand*/, null/*actor*/, fals |
| | | 109 | | } |
| | | 110 | | else |
| | | 111 | | { |
| | 4 | 112 | | if (matchingHeaderDescription.TypedHeader) |
| | | 113 | | { |
| | 0 | 114 | | messageHeaderOfTHelper.GetHeaderAttributes(matchingHeaderDescription, out mustUnderstand |
| | | 115 | | } |
| | | 116 | | else |
| | | 117 | | { |
| | 4 | 118 | | mustUnderstand = matchingHeaderDescription.MustUnderstand; |
| | 4 | 119 | | relay = matchingHeaderDescription.Relay; |
| | 4 | 120 | | actor = matchingHeaderDescription.Actor; |
| | | 121 | | } |
| | 4 | 122 | | message.Headers.Add(new XmlElementMessageHeader(this, message.Version, element.LocalName, el |
| | 4 | 123 | | mustUnderstand, actor, relay, element)); |
| | | 124 | | } |
| | | 125 | | } |
| | | 126 | | } |
| | 21 | 127 | | if (unknownHeaderDescription != null && parameters[unknownHeaderDescription.Index] != null) |
| | | 128 | | { |
| | 0 | 129 | | foreach (object unknownHeader in (IEnumerable)parameters[unknownHeaderDescription.Index]) |
| | | 130 | | { |
| | 0 | 131 | | XmlElement element = (XmlElement)GetContentOfMessageHeaderOfT(unknownHeaderDescription, unknownH |
| | 0 | 132 | | if (element != null) |
| | | 133 | | { |
| | 0 | 134 | | message.Headers.Add(new XmlElementMessageHeader(this, message.Version, element.LocalName, el |
| | 0 | 135 | | mustUnderstand, actor, relay, element)); |
| | | 136 | | } |
| | | 137 | | } |
| | | 138 | | } |
| | 21 | 139 | | } |
| | 0 | 140 | | catch (InvalidOperationException e) |
| | | 141 | | { |
| | 0 | 142 | | throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CommunicationException( |
| | 0 | 143 | | SR.Format(SR.SFxErrorSerializingHeader, messageDescription.MessageName, e.Message), e)); |
| | | 144 | | } |
| | 21 | 145 | | } |
| | | 146 | | |
| | | 147 | | protected override void GetHeadersFromMessage(Message message, MessageDescription messageDescription, object[] p |
| | | 148 | | { |
| | | 149 | | try |
| | | 150 | | { |
| | | 151 | | XmlSerializer serializer; |
| | | 152 | | MessageHeaderDescriptionTable headerDescriptionTable; |
| | | 153 | | MessageHeaderDescription unknownHeaderDescription; |
| | 21 | 154 | | if (isRequest) |
| | | 155 | | { |
| | 21 | 156 | | serializer = _requestMessageInfo.HeaderSerializer; |
| | 21 | 157 | | headerDescriptionTable = _requestMessageInfo.HeaderDescriptionTable; |
| | 21 | 158 | | unknownHeaderDescription = _requestMessageInfo.UnknownHeaderDescription; |
| | | 159 | | } |
| | | 160 | | else |
| | | 161 | | { |
| | 0 | 162 | | serializer = _replyMessageInfo.HeaderSerializer; |
| | 0 | 163 | | headerDescriptionTable = _replyMessageInfo.HeaderDescriptionTable; |
| | 0 | 164 | | unknownHeaderDescription = _replyMessageInfo.UnknownHeaderDescription; |
| | | 165 | | } |
| | 21 | 166 | | MessageHeaders headers = message.Headers; |
| | 21 | 167 | | ArrayList unknownHeaders = null; |
| | 21 | 168 | | XmlDocument xmlDoc = null; |
| | 21 | 169 | | if (unknownHeaderDescription != null) |
| | | 170 | | { |
| | 0 | 171 | | unknownHeaders = new ArrayList(); |
| | 0 | 172 | | xmlDoc = new XmlDocument(); |
| | | 173 | | } |
| | 21 | 174 | | if (serializer == null) |
| | | 175 | | { |
| | 20 | 176 | | if (unknownHeaderDescription != null) |
| | | 177 | | { |
| | 0 | 178 | | for (int headerIndex = 0; headerIndex < headers.Count; headerIndex++) |
| | | 179 | | { |
| | 0 | 180 | | AddUnknownHeader(unknownHeaderDescription, unknownHeaders, xmlDoc, null/*bufferWriter*/, hea |
| | | 181 | | } |
| | | 182 | | |
| | 0 | 183 | | parameters[unknownHeaderDescription.Index] = unknownHeaders.ToArray(unknownHeaderDescription.Typ |
| | | 184 | | } |
| | 20 | 185 | | return; |
| | | 186 | | } |
| | | 187 | | |
| | | 188 | | |
| | 1 | 189 | | MemoryStream memoryStream = new MemoryStream(); |
| | 1 | 190 | | XmlDictionaryWriter bufferWriter = XmlDictionaryWriter.CreateTextWriter(memoryStream); |
| | 1 | 191 | | message.WriteStartEnvelope(bufferWriter); |
| | 1 | 192 | | message.WriteStartHeaders(bufferWriter); |
| | 1 | 193 | | MessageHeaderOfTHelper messageHeaderOfTHelper = null; |
| | 14 | 194 | | for (int headerIndex = 0; headerIndex < headers.Count; headerIndex++) |
| | | 195 | | { |
| | 6 | 196 | | MessageHeaderInfo header = headers[headerIndex]; |
| | 6 | 197 | | XmlDictionaryReader headerReader = headers.GetReaderAtHeader(headerIndex); |
| | 6 | 198 | | MessageHeaderDescription matchingHeaderDescription = headerDescriptionTable.Get(header.Name, header. |
| | 6 | 199 | | if (matchingHeaderDescription != null) |
| | | 200 | | { |
| | 4 | 201 | | if (header.MustUnderstand) |
| | | 202 | | { |
| | 0 | 203 | | headers.UnderstoodHeaders.Add(header); |
| | | 204 | | } |
| | | 205 | | |
| | 4 | 206 | | if (matchingHeaderDescription.TypedHeader) |
| | | 207 | | { |
| | 0 | 208 | | if (messageHeaderOfTHelper == null) |
| | | 209 | | { |
| | 0 | 210 | | messageHeaderOfTHelper = new MessageHeaderOfTHelper(parameters.Length); |
| | | 211 | | } |
| | | 212 | | |
| | 0 | 213 | | messageHeaderOfTHelper.SetHeaderAttributes(matchingHeaderDescription, header.MustUnderstand, |
| | | 214 | | } |
| | | 215 | | } |
| | 6 | 216 | | if (matchingHeaderDescription == null && unknownHeaderDescription != null) |
| | | 217 | | { |
| | 0 | 218 | | AddUnknownHeader(unknownHeaderDescription, unknownHeaders, xmlDoc, bufferWriter, header, headerR |
| | | 219 | | } |
| | | 220 | | else |
| | | 221 | | { |
| | 6 | 222 | | bufferWriter.WriteNode(headerReader, false); |
| | | 223 | | } |
| | | 224 | | |
| | 6 | 225 | | headerReader.Dispose(); |
| | | 226 | | } |
| | 1 | 227 | | bufferWriter.WriteEndElement(); |
| | 1 | 228 | | bufferWriter.WriteEndElement(); |
| | 1 | 229 | | bufferWriter.Flush(); |
| | | 230 | | |
| | | 231 | | /* |
| | | 232 | | XmlDocument doc = new XmlDocument(); |
| | | 233 | | memoryStream.Position = 0; |
| | | 234 | | doc.Load(memoryStream); |
| | | 235 | | doc.Save(Console.Out); |
| | | 236 | | */ |
| | | 237 | | |
| | 1 | 238 | | memoryStream.Position = 0; |
| | 1 | 239 | | memoryStream.TryGetBuffer(out ArraySegment<byte> memoryBuffer); |
| | 1 | 240 | | XmlDictionaryReader bufferReader = XmlDictionaryReader.CreateTextReader(memoryBuffer.Array, 0, (int)memo |
| | | 241 | | |
| | 1 | 242 | | bufferReader.ReadStartElement(); |
| | 1 | 243 | | bufferReader.MoveToContent(); |
| | 1 | 244 | | if (!bufferReader.IsEmptyElement) |
| | | 245 | | { |
| | 1 | 246 | | bufferReader.ReadStartElement(); |
| | 1 | 247 | | object[] headerValues = (object[])serializer.Deserialize(bufferReader, _isEncoded ? GetEncoding(mess |
| | 1 | 248 | | int headerIndex = 0; |
| | 6 | 249 | | foreach (MessageHeaderDescription headerDescription in messageDescription.Headers) |
| | | 250 | | { |
| | 2 | 251 | | if (!headerDescription.IsUnknownHeaderCollection) |
| | | 252 | | { |
| | 2 | 253 | | object parameterValue = headerValues[headerIndex++]; |
| | 2 | 254 | | if (headerDescription.TypedHeader && parameterValue != null) |
| | | 255 | | { |
| | 0 | 256 | | parameterValue = messageHeaderOfTHelper.CreateMessageHeader(headerDescription, parameter |
| | | 257 | | } |
| | | 258 | | |
| | 2 | 259 | | parameters[headerDescription.Index] = parameterValue; |
| | | 260 | | } |
| | | 261 | | } |
| | 1 | 262 | | bufferReader.Dispose(); |
| | | 263 | | } |
| | 1 | 264 | | if (unknownHeaderDescription != null) |
| | | 265 | | { |
| | 0 | 266 | | parameters[unknownHeaderDescription.Index] = unknownHeaders.ToArray(unknownHeaderDescription.TypedHe |
| | | 267 | | } |
| | 1 | 268 | | } |
| | 0 | 269 | | catch (InvalidOperationException e) |
| | | 270 | | { |
| | | 271 | | // all exceptions from XmlSerializer get wrapped in InvalidOperationException, |
| | | 272 | | // so we must be conservative and never turn this into a fault |
| | 0 | 273 | | throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CommunicationException( |
| | 0 | 274 | | SR.Format(SR.SFxErrorDeserializingHeader, messageDescription.MessageName), e)); |
| | | 275 | | } |
| | 21 | 276 | | } |
| | | 277 | | |
| | | 278 | | private static void AddUnknownHeader(MessageHeaderDescription unknownHeaderDescription, ArrayList unknownHeaders |
| | | 279 | | { |
| | 0 | 280 | | object unknownHeader = xmlDoc.ReadNode(headerReader); |
| | 0 | 281 | | if (bufferWriter != null) |
| | | 282 | | { |
| | 0 | 283 | | ((XmlElement)unknownHeader).WriteTo(bufferWriter); |
| | | 284 | | } |
| | | 285 | | |
| | 0 | 286 | | if (unknownHeader != null && unknownHeaderDescription.TypedHeader) |
| | | 287 | | { |
| | 0 | 288 | | unknownHeader = TypedHeaderManager.Create(unknownHeaderDescription.Type, unknownHeader, header.MustUnder |
| | | 289 | | } |
| | | 290 | | |
| | 0 | 291 | | unknownHeaders.Add(unknownHeader); |
| | 0 | 292 | | } |
| | | 293 | | |
| | | 294 | | protected override void WriteBodyAttributes(XmlDictionaryWriter writer, MessageVersion version) |
| | | 295 | | { |
| | 21 | 296 | | if (_isEncoded && version.Envelope == EnvelopeVersion.Soap11) |
| | | 297 | | { |
| | 1 | 298 | | string encoding = GetEncoding(version.Envelope); |
| | 1 | 299 | | writer.WriteAttributeString("encodingStyle", version.Envelope.Namespace, encoding); |
| | | 300 | | } |
| | 21 | 301 | | writer.WriteAttributeString("xmlns", "xsi", null, XmlUtil.XmlSerializerSchemaInstanceNamespace); |
| | 21 | 302 | | writer.WriteAttributeString("xmlns", "xsd", null, XmlUtil.XmlSerializerSchemaNamespace); |
| | 21 | 303 | | } |
| | | 304 | | |
| | | 305 | | protected override void SerializeBody(XmlDictionaryWriter writer, MessageVersion version, string action, Message |
| | | 306 | | { |
| | 20 | 307 | | if (writer == null) |
| | | 308 | | { |
| | 0 | 309 | | throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException(nameof(writer))); |
| | | 310 | | } |
| | | 311 | | |
| | 20 | 312 | | if (parameters == null) |
| | | 313 | | { |
| | 0 | 314 | | throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException(nameof(parameters))) |
| | | 315 | | } |
| | | 316 | | |
| | | 317 | | try |
| | | 318 | | { |
| | | 319 | | MessageInfo messageInfo; |
| | 20 | 320 | | if (isRequest) |
| | | 321 | | { |
| | 0 | 322 | | messageInfo = _requestMessageInfo; |
| | | 323 | | } |
| | | 324 | | else |
| | | 325 | | { |
| | 20 | 326 | | messageInfo = _replyMessageInfo; |
| | | 327 | | } |
| | | 328 | | |
| | 20 | 329 | | if (messageInfo.RpcEncodedTypedMessageBodyParts == null) |
| | | 330 | | { |
| | 20 | 331 | | SerializeBody(writer, version, messageInfo.BodySerializer, messageDescription.Body.ReturnValue, mess |
| | 20 | 332 | | return; |
| | | 333 | | } |
| | | 334 | | |
| | 0 | 335 | | object[] bodyPartValues = new object[messageInfo.RpcEncodedTypedMessageBodyParts.Count]; |
| | 0 | 336 | | object bodyObject = parameters[messageDescription.Body.Parts[0].Index]; |
| | 0 | 337 | | if (bodyObject == null) |
| | | 338 | | { |
| | 0 | 339 | | throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.Format(SR |
| | | 340 | | } |
| | | 341 | | |
| | 0 | 342 | | int i = 0; |
| | 0 | 343 | | foreach (MessagePartDescription bodyPart in messageInfo.RpcEncodedTypedMessageBodyParts) |
| | | 344 | | { |
| | 0 | 345 | | MemberInfo member = bodyPart.MemberInfo; |
| | 0 | 346 | | FieldInfo field = member as FieldInfo; |
| | 0 | 347 | | if (field != null) |
| | | 348 | | { |
| | 0 | 349 | | bodyPartValues[i++] = field.GetValue(bodyObject); |
| | | 350 | | } |
| | | 351 | | else |
| | | 352 | | { |
| | 0 | 353 | | PropertyInfo property = member as PropertyInfo; |
| | 0 | 354 | | if (property != null) |
| | | 355 | | { |
| | 0 | 356 | | bodyPartValues[i++] = property.GetValue(bodyObject, null); |
| | | 357 | | } |
| | | 358 | | } |
| | | 359 | | } |
| | 0 | 360 | | SerializeBody(writer, version, messageInfo.BodySerializer, null/*returnPart*/, messageInfo.RpcEncodedTyp |
| | 0 | 361 | | } |
| | 0 | 362 | | catch (InvalidOperationException e) |
| | | 363 | | { |
| | 0 | 364 | | throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CommunicationException( |
| | 0 | 365 | | SR.Format(SR.SFxErrorSerializingBody, messageDescription.MessageName, e.Message), e)); |
| | | 366 | | } |
| | 20 | 367 | | } |
| | | 368 | | |
| | | 369 | | private void SerializeBody(XmlDictionaryWriter writer, MessageVersion version, XmlSerializer serializer, Message |
| | | 370 | | { |
| | 20 | 371 | | if (serializer == null) |
| | | 372 | | { |
| | 0 | 373 | | return; |
| | | 374 | | } |
| | | 375 | | |
| | 20 | 376 | | bool hasReturnValue = IsValidReturnValue(returnPart); |
| | 20 | 377 | | object[] bodyParameters = new object[bodyParts.Count + (hasReturnValue ? 1 : 0)]; |
| | 20 | 378 | | int paramIndex = 0; |
| | | 379 | | |
| | 20 | 380 | | if (hasReturnValue) |
| | | 381 | | { |
| | 16 | 382 | | bodyParameters[paramIndex++] = returnValue; |
| | | 383 | | } |
| | | 384 | | |
| | 54 | 385 | | for (int i = 0; i < bodyParts.Count; i++) |
| | | 386 | | { |
| | 7 | 387 | | bodyParameters[paramIndex++] = parameters[bodyParts[i].Index]; |
| | | 388 | | } |
| | | 389 | | |
| | 20 | 390 | | string encoding = _isEncoded ? GetEncoding(version.Envelope) : null; |
| | 20 | 391 | | serializer.Serialize(writer, bodyParameters, null, encoding); |
| | 20 | 392 | | } |
| | | 393 | | |
| | | 394 | | |
| | | 395 | | protected override object DeserializeBody(XmlDictionaryReader reader, MessageVersion version, string action, Mes |
| | | 396 | | { |
| | | 397 | | MessageInfo messageInfo; |
| | 20 | 398 | | if (isRequest) |
| | | 399 | | { |
| | 20 | 400 | | messageInfo = _requestMessageInfo; |
| | | 401 | | } |
| | | 402 | | else |
| | | 403 | | { |
| | 0 | 404 | | messageInfo = _replyMessageInfo; |
| | | 405 | | } |
| | | 406 | | |
| | 20 | 407 | | if (messageInfo.RpcEncodedTypedMessageBodyParts == null) |
| | | 408 | | { |
| | 20 | 409 | | return DeserializeBody(reader, version, messageInfo.BodySerializer, messageDescription.Body.ReturnValue, |
| | | 410 | | } |
| | | 411 | | |
| | 0 | 412 | | object[] bodyPartValues = new object[messageInfo.RpcEncodedTypedMessageBodyParts.Count]; |
| | 0 | 413 | | DeserializeBody(reader, version, messageInfo.BodySerializer, null/*returnPart*/, messageInfo.RpcEncodedTyped |
| | 0 | 414 | | object bodyObject = Activator.CreateInstance(messageDescription.Body.Parts[0].Type); |
| | 0 | 415 | | int i = 0; |
| | 0 | 416 | | foreach (MessagePartDescription bodyPart in messageInfo.RpcEncodedTypedMessageBodyParts) |
| | | 417 | | { |
| | 0 | 418 | | MemberInfo member = bodyPart.MemberInfo; |
| | 0 | 419 | | FieldInfo field = member as FieldInfo; |
| | 0 | 420 | | if (field != null) |
| | | 421 | | { |
| | 0 | 422 | | field.SetValue(bodyObject, bodyPartValues[i++]); |
| | | 423 | | } |
| | | 424 | | else |
| | | 425 | | { |
| | 0 | 426 | | PropertyInfo property = member as PropertyInfo; |
| | 0 | 427 | | if (property != null) |
| | | 428 | | { |
| | 0 | 429 | | property.SetValue(bodyObject, bodyPartValues[i++], null); |
| | | 430 | | } |
| | | 431 | | } |
| | | 432 | | } |
| | 0 | 433 | | parameters[messageDescription.Body.Parts[0].Index] = bodyObject; |
| | 0 | 434 | | return null; |
| | | 435 | | } |
| | | 436 | | |
| | | 437 | | private object DeserializeBody(XmlDictionaryReader reader, MessageVersion version, XmlSerializer serializer, Mes |
| | | 438 | | { |
| | | 439 | | try |
| | | 440 | | { |
| | 20 | 441 | | if (reader == null) |
| | | 442 | | { |
| | 0 | 443 | | throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException(nameof(reader))) |
| | | 444 | | } |
| | | 445 | | |
| | 20 | 446 | | if (parameters == null) |
| | | 447 | | { |
| | 0 | 448 | | throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException(nameof(parameter |
| | | 449 | | } |
| | | 450 | | |
| | 20 | 451 | | object returnValue = null; |
| | 20 | 452 | | if (serializer == null) |
| | | 453 | | { |
| | 0 | 454 | | return null; |
| | | 455 | | } |
| | 20 | 456 | | if (reader.NodeType == XmlNodeType.EndElement) |
| | | 457 | | { |
| | 0 | 458 | | return null; |
| | | 459 | | } |
| | | 460 | | |
| | 20 | 461 | | object[] bodyParameters = (object[])serializer.Deserialize(reader, _isEncoded ? GetEncoding(version.Enve |
| | | 462 | | |
| | 20 | 463 | | int paramIndex = 0; |
| | 20 | 464 | | if (IsValidReturnValue(returnPart)) |
| | | 465 | | { |
| | 0 | 466 | | returnValue = bodyParameters[paramIndex++]; |
| | | 467 | | } |
| | | 468 | | |
| | 86 | 469 | | for (int i = 0; i < bodyParts.Count; i++) |
| | | 470 | | { |
| | 23 | 471 | | parameters[bodyParts[i].Index] = bodyParameters[paramIndex++]; |
| | | 472 | | } |
| | | 473 | | |
| | 20 | 474 | | return returnValue; |
| | | 475 | | } |
| | 0 | 476 | | catch (InvalidOperationException e) |
| | | 477 | | { |
| | | 478 | | // all exceptions from XmlSerializer get wrapped in InvalidOperationException, |
| | | 479 | | // so we must be conservative and never turn this into a fault |
| | 0 | 480 | | string resourceKey = isRequest ? SR.SFxErrorDeserializingRequestBody : SR.SFxErrorDeserializingReplyBody |
| | | 481 | | |
| | 0 | 482 | | throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CommunicationException( |
| | 0 | 483 | | SR.Format(resourceKey, OperationName), e)); |
| | | 484 | | } |
| | 20 | 485 | | } |
| | | 486 | | |
| | | 487 | | internal static string GetEncoding(EnvelopeVersion version) |
| | | 488 | | { |
| | 13 | 489 | | if (version == EnvelopeVersion.Soap11) |
| | | 490 | | { |
| | 11 | 491 | | return soap11Encoding; |
| | | 492 | | } |
| | 2 | 493 | | else if (version == EnvelopeVersion.Soap12) |
| | | 494 | | { |
| | 2 | 495 | | return soap12Encoding; |
| | | 496 | | } |
| | | 497 | | else |
| | | 498 | | { |
| | 0 | 499 | | throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument(nameof(version), |
| | 0 | 500 | | SR.Format(SR.EnvelopeVersionNotSupported, version)); |
| | | 501 | | } |
| | | 502 | | } |
| | | 503 | | |
| | | 504 | | internal abstract class MessageInfo |
| | | 505 | | { |
| | | 506 | | internal abstract XmlSerializer BodySerializer { get; } |
| | | 507 | | internal abstract XmlSerializer HeaderSerializer { get; } |
| | | 508 | | internal abstract MessageHeaderDescriptionTable HeaderDescriptionTable { get; } |
| | | 509 | | internal abstract MessageHeaderDescription UnknownHeaderDescription { get; } |
| | | 510 | | internal abstract MessagePartDescriptionCollection RpcEncodedTypedMessageBodyParts { get; } |
| | | 511 | | } |
| | | 512 | | |
| | | 513 | | private class MessageHeaderOfTHelper |
| | | 514 | | { |
| | | 515 | | private readonly object[] _attributes; |
| | 0 | 516 | | internal MessageHeaderOfTHelper(int parameterCount) |
| | | 517 | | { |
| | 0 | 518 | | _attributes = new object[parameterCount]; |
| | 0 | 519 | | } |
| | | 520 | | internal object GetContentAndSaveHeaderAttributes(object parameterValue, MessageHeaderDescription headerDesc |
| | | 521 | | { |
| | 0 | 522 | | if (parameterValue == null) |
| | | 523 | | { |
| | 0 | 524 | | return null; |
| | | 525 | | } |
| | | 526 | | |
| | | 527 | | bool mustUnderstand; |
| | | 528 | | bool relay; |
| | | 529 | | string actor; |
| | 0 | 530 | | if (headerDescription.Multiple) |
| | | 531 | | { |
| | 0 | 532 | | object[] messageHeaderOfTArray = (object[])parameterValue; |
| | 0 | 533 | | MessageHeader<object>[] messageHeaderOfTAttributes = new MessageHeader<object>[messageHeaderOfTArray |
| | 0 | 534 | | Array tArray = Array.CreateInstance(headerDescription.Type, messageHeaderOfTArray.Length); |
| | 0 | 535 | | for (int i = 0; i < tArray.Length; i++) |
| | | 536 | | { |
| | 0 | 537 | | tArray.SetValue(GetContentOfMessageHeaderOfT(headerDescription, messageHeaderOfTArray[i], out mu |
| | 0 | 538 | | messageHeaderOfTAttributes[i] = new MessageHeader<object>(null, mustUnderstand, actor, relay); |
| | | 539 | | } |
| | 0 | 540 | | _attributes[headerDescription.Index] = messageHeaderOfTAttributes; |
| | 0 | 541 | | return tArray; |
| | | 542 | | } |
| | | 543 | | else |
| | | 544 | | { |
| | 0 | 545 | | object content = GetContentOfMessageHeaderOfT(headerDescription, parameterValue, out mustUnderstand, |
| | 0 | 546 | | _attributes[headerDescription.Index] = new MessageHeader<object>(null, mustUnderstand, actor, relay) |
| | 0 | 547 | | return content; |
| | | 548 | | } |
| | | 549 | | } |
| | | 550 | | |
| | | 551 | | internal void GetHeaderAttributes(MessageHeaderDescription headerDescription, out bool mustUnderstand, out b |
| | | 552 | | { |
| | 0 | 553 | | MessageHeader<object> matchingMessageHeaderOfTAttribute = null; |
| | 0 | 554 | | if (headerDescription.Multiple) |
| | | 555 | | { |
| | 0 | 556 | | MessageHeader<object>[] messageHeaderOfTAttributes = (MessageHeader<object>[])_attributes[headerDesc |
| | 0 | 557 | | for (int i = 0; i < messageHeaderOfTAttributes.Length; i++) |
| | | 558 | | { |
| | 0 | 559 | | if (messageHeaderOfTAttributes[i] != null) |
| | | 560 | | { |
| | 0 | 561 | | matchingMessageHeaderOfTAttribute = messageHeaderOfTAttributes[i]; |
| | 0 | 562 | | messageHeaderOfTAttributes[i] = null; |
| | 0 | 563 | | break; |
| | | 564 | | } |
| | | 565 | | } |
| | | 566 | | //assert(matchingMessageHeaderOfTAttribute != null); |
| | | 567 | | |
| | | 568 | | } |
| | | 569 | | else |
| | | 570 | | { |
| | 0 | 571 | | matchingMessageHeaderOfTAttribute = (MessageHeader<object>)_attributes[headerDescription.Index]; |
| | | 572 | | } |
| | | 573 | | |
| | 0 | 574 | | mustUnderstand = matchingMessageHeaderOfTAttribute.MustUnderstand; |
| | 0 | 575 | | relay = matchingMessageHeaderOfTAttribute.Relay; |
| | 0 | 576 | | actor = matchingMessageHeaderOfTAttribute.Actor; |
| | 0 | 577 | | } |
| | | 578 | | |
| | | 579 | | internal void SetHeaderAttributes(MessageHeaderDescription headerDescription, bool mustUnderstand, bool rela |
| | | 580 | | { |
| | 0 | 581 | | if (headerDescription.Multiple) |
| | | 582 | | { |
| | 0 | 583 | | if (_attributes[headerDescription.Index] == null) |
| | | 584 | | { |
| | 0 | 585 | | _attributes[headerDescription.Index] = new List<MessageHeader<object>>(); |
| | 0 | 586 | | } ((List<MessageHeader<object>>)_attributes[headerDescription.Index]).Add(new MessageHeader<object>( |
| | | 587 | | } |
| | | 588 | | else |
| | | 589 | | { |
| | 0 | 590 | | _attributes[headerDescription.Index] = new MessageHeader<object>(null, mustUnderstand, actor, relay) |
| | | 591 | | } |
| | 0 | 592 | | } |
| | | 593 | | internal object CreateMessageHeader(MessageHeaderDescription headerDescription, object headerValue) |
| | | 594 | | { |
| | 0 | 595 | | if (headerDescription.Multiple) |
| | | 596 | | { |
| | 0 | 597 | | IList<MessageHeader<object>> messageHeaderOfTAttributes = (IList<MessageHeader<object>>)_attributes[ |
| | 0 | 598 | | object[] messageHeaderOfTArray = (object[])Array.CreateInstance(TypedHeaderManager.GetMessageHeaderT |
| | 0 | 599 | | Array headerValues = (Array)headerValue; |
| | 0 | 600 | | for (int i = 0; i < messageHeaderOfTArray.Length; i++) |
| | | 601 | | { |
| | 0 | 602 | | MessageHeader<object> messageHeaderOfTAttribute = messageHeaderOfTAttributes[i]; |
| | 0 | 603 | | messageHeaderOfTArray[i] = TypedHeaderManager.Create(headerDescription.Type, headerValues.GetVal |
| | 0 | 604 | | messageHeaderOfTAttribute.MustUnderstand, messageH |
| | | 605 | | } |
| | 0 | 606 | | return messageHeaderOfTArray; |
| | | 607 | | } |
| | | 608 | | else |
| | | 609 | | { |
| | 0 | 610 | | MessageHeader<object> messageHeaderOfTAttribute = (MessageHeader<object>)_attributes[headerDescripti |
| | 0 | 611 | | return TypedHeaderManager.Create(headerDescription.Type, headerValue, |
| | 0 | 612 | | messageHeaderOfTAttribute.MustUnderstand, messageHeade |
| | | 613 | | } |
| | | 614 | | } |
| | | 615 | | } |
| | | 616 | | } |
| | | 617 | | } |