1 //----------------------------------------------------------------------------- 2 // Copyright (c) Microsoft Corporation. All rights reserved. 3 //----------------------------------------------------------------------------- 4 5 namespace System.ServiceModel.Activities 6 { 7 using System.Activities; 8 using System.Activities.Validation; 9 using System.Collections; 10 using System.Collections.Generic; 11 using System.Runtime; 12 using System.ServiceModel.Description; 13 using System.Xml; 14 using System.Xml.Linq; 15 using System.Xml.Serialization; 16 using SR2 = System.ServiceModel.Activities.SR; 17 18 static class ContractValidationHelper 19 { ValidateReceiveWithReceive(Receive receive1, Receive receive2)20 public static void ValidateReceiveWithReceive(Receive receive1, Receive receive2) 21 { 22 Fx.Assert(receive1 != null && receive2 != null, "Validation argument cannot be null!"); 23 Fx.Assert(receive1.OperationName != null, "OperationName cannot be null in Receive"); 24 string receiveOperationName = receive1.OperationName; 25 26 if (receive1.Action != receive2.Action) 27 { 28 throw FxTrace.Exception.AsError(new ValidationException(SR2.TwoReceivesWithSameNameButDifferentAction(receiveOperationName))); 29 } 30 31 if (receive1.InternalContent is ReceiveMessageContent && receive2.InternalContent is ReceiveMessageContent) 32 { 33 ReceiveMessageContent receiveMessage1 = receive1.InternalContent as ReceiveMessageContent; 34 ReceiveMessageContent receiveMessage2 = receive2.InternalContent as ReceiveMessageContent; 35 36 ValidateReceiveWithReceive(receiveMessage1, receiveMessage2, receiveOperationName); 37 } 38 else if (receive1.InternalContent is ReceiveParametersContent && receive2.InternalContent is ReceiveParametersContent) 39 { 40 ReceiveParametersContent receiveParameters1 = receive1.InternalContent as ReceiveParametersContent; 41 ReceiveParametersContent receiveParameters2 = receive2.InternalContent as ReceiveParametersContent; 42 43 ValidateReceiveParametersWithReceiveParameters(receiveParameters1, receiveParameters2, receiveOperationName); 44 } 45 else 46 { 47 throw FxTrace.Exception.AsError(new ValidationException(SR2.ReceiveAndReceiveParametersHaveSameName(receiveOperationName))); 48 } 49 50 if (receive1.HasReply && receive2.HasReply) 51 { 52 ValidateSendReplyWithSendReply(receive1.FollowingReplies[0], receive2.FollowingReplies[0]); 53 } 54 else if ((receive1.HasReply || receive1.HasFault) != (receive2.HasReply || receive2.HasFault)) 55 { 56 throw FxTrace.Exception.AsError(new ValidationException(SR2.TwoReceivesWithSameNameButDifferentIsOneWay(receiveOperationName))); 57 } 58 59 if ((receive1.InternalReceive.AdditionalData.IsInsideTransactedReceiveScope != receive2.InternalReceive.AdditionalData.IsInsideTransactedReceiveScope) || 60 (receive1.InternalReceive.AdditionalData.IsFirstReceiveOfTransactedReceiveScopeTree != receive2.InternalReceive.AdditionalData.IsFirstReceiveOfTransactedReceiveScopeTree)) 61 { 62 throw FxTrace.Exception.AsError(new ValidationException(SR2.TwoReceivesWithSameNameButDifferentTxProperties(receiveOperationName))); 63 } 64 } 65 ValidateReceiveWithReceive(ReceiveMessageContent receive1, ReceiveMessageContent receive2, string receiveOperationName)66 static void ValidateReceiveWithReceive(ReceiveMessageContent receive1, ReceiveMessageContent receive2, string receiveOperationName) 67 { 68 Fx.Assert(receive1 != null && receive2 != null, "Validation argument cannot be null!"); 69 70 if (receive1.InternalDeclaredMessageType != receive2.InternalDeclaredMessageType) 71 { 72 throw FxTrace.Exception.AsError(new ValidationException(SR2.TwoReceivesWithSameNameButDifferentValueType(receiveOperationName))); 73 } 74 } 75 ValidateReceiveParametersWithReceiveParameters(ReceiveParametersContent receiveParameters1, ReceiveParametersContent receiveParameters2, string receiveOperationName)76 static void ValidateReceiveParametersWithReceiveParameters(ReceiveParametersContent receiveParameters1, ReceiveParametersContent receiveParameters2, string receiveOperationName) 77 { 78 Fx.Assert(receiveParameters1 != null && receiveParameters2 != null, "Validation argument cannot be null!"); 79 80 int count = receiveParameters1.ArgumentNames.Length; 81 if (count != receiveParameters2.ArgumentNames.Length) 82 { 83 throw FxTrace.Exception.AsError(new ValidationException(SR2.TwoReceiveParametersWithSameNameButDifferentParameterCount(receiveOperationName))); 84 } 85 for (int i = 0; i < count; i++) 86 { 87 if (receiveParameters1.ArgumentNames[i] != receiveParameters2.ArgumentNames[i]) 88 { 89 throw FxTrace.Exception.AsError(new ValidationException(SR2.TwoReceiveParametersWithSameNameButDifferentParameterName(receiveOperationName))); 90 } 91 if (receiveParameters1.ArgumentTypes[i] != receiveParameters2.ArgumentTypes[i]) 92 { 93 throw FxTrace.Exception.AsError(new ValidationException(SR2.TwoReceiveParametersWithSameNameButDifferentParameterType(receiveOperationName))); 94 } 95 } 96 } 97 ValidateSendReplyWithSendReply(SendReply sendReply1, SendReply sendReply2)98 public static void ValidateSendReplyWithSendReply(SendReply sendReply1, SendReply sendReply2) 99 { 100 Fx.Assert(sendReply1 != null && sendReply2 != null, "Validation argument cannot be null!"); 101 Fx.Assert(sendReply1.Request != null, "Request cannot be null in SendReply"); 102 string operationName = sendReply1.Request.OperationName; 103 104 if (sendReply1.Action != sendReply2.Action) 105 { 106 throw FxTrace.Exception.AsError(new ValidationException(SR2.TwoSendRepliesWithSameNameButDifferentAction(operationName))); 107 } 108 109 if (sendReply1.InternalContent is SendMessageContent && sendReply2.InternalContent is SendMessageContent) 110 { 111 SendMessageContent sendMessage1 = sendReply1.InternalContent as SendMessageContent; 112 SendMessageContent sendMessage2 = sendReply2.InternalContent as SendMessageContent; 113 114 if (sendMessage1.InternalDeclaredMessageType != sendMessage2.InternalDeclaredMessageType) 115 { 116 throw FxTrace.Exception.AsError(new ValidationException(SR2.TwoSendRepliesWithSameNameButDifferentValueType(operationName))); 117 } 118 } 119 else if (sendReply1.InternalContent is SendParametersContent && sendReply2.InternalContent is SendParametersContent) 120 { 121 SendParametersContent sendReplyParameters1 = sendReply1.InternalContent as SendParametersContent; 122 SendParametersContent sendReplyParameters2 = sendReply2.InternalContent as SendParametersContent; 123 124 int count = sendReplyParameters1.ArgumentNames.Length; 125 if (count != sendReplyParameters2.ArgumentNames.Length) 126 { 127 throw FxTrace.Exception.AsError(new ValidationException(SR2.TwoSendReplyParametersWithSameNameButDifferentParameterCount(operationName))); 128 } 129 for (int i = 0; i < count; i++) 130 { 131 if (sendReplyParameters1.ArgumentNames[i] != sendReplyParameters2.ArgumentNames[i]) 132 { 133 throw FxTrace.Exception.AsError(new ValidationException(SR2.TwoSendReplyParametersWithSameNameButDifferentParameterName(operationName))); 134 } 135 if (sendReplyParameters1.ArgumentTypes[i] != sendReplyParameters2.ArgumentTypes[i]) 136 { 137 throw FxTrace.Exception.AsError(new ValidationException(SR2.TwoSendReplyParametersWithSameNameButDifferentParameterType(operationName))); 138 } 139 } 140 } 141 else 142 { 143 throw FxTrace.Exception.AsError(new ValidationException(SR2.ReceivePairedWithSendReplyAndSendReplyParameters(operationName))); 144 } 145 } 146 ValidateFault(NativeActivityContext context, OperationDescription targetOperation, string overridingAction, Type faultType)147 public static void ValidateFault(NativeActivityContext context, OperationDescription targetOperation, string overridingAction, Type faultType) 148 { 149 bool faultTypeExistOnContract = false; 150 151 for (int index = 0; index < targetOperation.Faults.Count; index++) 152 { 153 FaultDescription targetFault = targetOperation.Faults[index]; 154 155 if (targetFault.DetailType == faultType) 156 { 157 string name = NamingHelper.TypeName(faultType) + TypeLoader.FaultSuffix; 158 string action = overridingAction ?? NamingHelper.GetMessageAction(targetOperation, false) + name; 159 160 if (targetFault.Action != action) 161 { 162 Constraint.AddValidationError(context, new ValidationError(SR2.PropertyMismatch(action, "Fault Action", targetFault.Action, targetOperation.Name, targetOperation.DeclaringContract.Name))); 163 } 164 if (targetFault.Name != NamingHelper.XmlName(name)) 165 { 166 Constraint.AddValidationError(context, new ValidationError(SR2.PropertyMismatch(NamingHelper.XmlName(name), "Fault Name", targetFault.Name, targetOperation.Name, targetOperation.DeclaringContract.Name))); 167 } 168 if (targetFault.Namespace != targetOperation.DeclaringContract.Namespace) 169 { 170 Constraint.AddValidationError(context, new ValidationError(SR2.PropertyMismatch(targetOperation.DeclaringContract.Namespace, "Fault Namespace", targetFault.Namespace, targetOperation.Name, targetOperation.DeclaringContract.Name))); 171 } 172 if (targetFault.HasProtectionLevel) 173 { 174 Constraint.AddValidationError(context, new ValidationError(SR2.ProtectionLevelNotSupported(targetOperation.Name, targetOperation.DeclaringContract.Name))); 175 } 176 177 // TypeLoader guarantees that fault types are unique in the Faults collection. 178 faultTypeExistOnContract = true; 179 break; 180 } 181 } 182 183 // It is OK to have fewer fault types than defined on the contract. 184 // But we do not allow workflow to define more fault types than specified on the contract. 185 if (!faultTypeExistOnContract) 186 { 187 Constraint.AddValidationError(context, new ValidationError(SR2.FaultTypeMismatch(faultType.FullName, targetOperation.Name, targetOperation.DeclaringContract.Name))); 188 } 189 } 190 ValidateAction(NativeActivityContext context, MessageDescription targetMessage, string overridingAction, OperationDescription targetOperation, bool isResponse)191 public static void ValidateAction(NativeActivityContext context, MessageDescription targetMessage, string overridingAction, 192 OperationDescription targetOperation, bool isResponse) 193 { 194 if (overridingAction == null && targetMessage.Action != NamingHelper.GetMessageAction(targetOperation, isResponse) 195 || overridingAction != null && overridingAction != targetMessage.Action) 196 { 197 Constraint.AddValidationError(context, new ValidationError(SR2.PropertyMismatch(overridingAction, "Action", targetMessage.Action, targetOperation.Name, targetOperation.DeclaringContract.Name))); 198 } 199 } 200 ValidateMessageContent(NativeActivityContext context, MessageDescription targetMessage, Type declaredMessageType, SerializerOption serializerOption, OperationDescription operation, bool isResponse)201 public static void ValidateMessageContent(NativeActivityContext context, MessageDescription targetMessage, Type declaredMessageType, 202 SerializerOption serializerOption, OperationDescription operation, bool isResponse) 203 { 204 // MessageContract is allowed only if the WCF contract interface specifies the same message contract type. 205 if (MessageBuilder.IsMessageContract(declaredMessageType)) 206 { 207 // if it is a typed message contract, we just validate the type of the message matches 208 if (targetMessage.MessageType != null ) 209 { 210 if (declaredMessageType != targetMessage.MessageType) 211 { 212 Constraint.AddValidationError(context, new ValidationError(SR2.PropertyMismatch(declaredMessageType.ToString(), "type", targetMessage.MessageType.ToString(), operation.Name, operation.DeclaringContract.Name))); 213 } 214 } 215 else 216 { 217 Constraint.AddValidationError(context, new ValidationError(SR2.PropertyMismatch(declaredMessageType.ToString(), "type", "null", operation.Name, operation.DeclaringContract.Name))); 218 } 219 return; 220 } 221 else if (declaredMessageType != null && declaredMessageType.IsAssignableFrom(typeof(System.ServiceModel.Channels.Message))) 222 { 223 //This is an untyped message contract 224 if (targetMessage.Body == null) 225 { 226 Constraint.AddValidationError(context, new ValidationError(SR2.BodyCannotBeNull)); 227 } 228 else 229 { 230 if (isResponse) 231 { 232 if (targetMessage.Body.ReturnValue == null) 233 { 234 Constraint.AddValidationError(context, new ValidationError(SR2.ExtraReturnValue)); 235 } 236 else if (!targetMessage.Body.ReturnValue.Type.IsAssignableFrom(typeof(System.ServiceModel.Channels.Message))) 237 { 238 Constraint.AddValidationError(context, new ValidationError(SR2.FirstParameterDoesnotMatchTheReturnValue(declaredMessageType.FullName, targetMessage.Body.ReturnValue.Type.Name, operation.Name, operation.DeclaringContract.Name))); 239 } 240 } 241 else 242 { 243 if (targetMessage.Body.Parts.Count == 0) 244 { 245 Constraint.AddValidationError(context, new ValidationError(SR2.ParameterNumberMismatch(declaredMessageType.FullName, operation.Name, operation.DeclaringContract.Name))); 246 } 247 else if (targetMessage.Body.Parts.Count > 1) 248 { 249 Constraint.AddValidationError(context, new ValidationError(SR2.MessageContentCannotHaveMoreThanOneParameter(operation.Name, operation.DeclaringContract.Name))); 250 } 251 else 252 { 253 if (!targetMessage.Body.Parts[0].Type.IsAssignableFrom(typeof(System.ServiceModel.Channels.Message))) 254 { 255 Constraint.AddValidationError(context, new ValidationError(SR2.MessageTypeMismatch(targetMessage.Body.Parts[0].Type.FullName, operation.Name, operation.DeclaringContract.Name))); 256 } 257 } 258 } 259 } 260 261 return; 262 } 263 264 // In case the WCF contract is a typed message, and the Receive activity also uses ReceiveMessageContent to infer a typed message, the contract needs to be matched 265 Fx.Assert(targetMessage.Body != null, "MessageDescription.Body is never null!"); 266 267 // MessageDescription: Headers, Properties, ProtectionLevel 268 // MessageBodyDescription: ReturnValue, WrapperName, WrapperNamespace 269 // MessagePartDescription: Name, Namespace, Type, ProtectionLevel, Multiple, Index 270 if (targetMessage.Headers.Count > 0) 271 { 272 Constraint.AddValidationError(context, new ValidationError(SR2.MessageHeaderNotSupported(operation.Name, operation.DeclaringContract.Name))); 273 } 274 if (targetMessage.Properties.Count > 0) 275 { 276 Constraint.AddValidationError(context, new ValidationError(SR2.MessagePropertyIsNotSupported(operation.Name, operation.DeclaringContract.Name))); 277 } 278 if (targetMessage.HasProtectionLevel) 279 { 280 Constraint.AddValidationError(context, new ValidationError(SR2.ProtectionLevelIsNotSupported(operation.Name, operation.DeclaringContract.Name))); 281 } 282 283 if (declaredMessageType == null || declaredMessageType == TypeHelper.VoidType) 284 { 285 if (!targetMessage.IsVoid) 286 { 287 Constraint.AddValidationError(context, new ValidationError(SR2.MessageCannotBeEmpty(operation.Name, operation.DeclaringContract.Name))); 288 } 289 } 290 else 291 { 292 string partName; 293 string partNamespace; 294 295 if (serializerOption == SerializerOption.DataContractSerializer) 296 { 297 XmlQualifiedName xmlQualifiedName = MessageBuilder.XsdDataContractExporter.GetRootElementName(declaredMessageType); 298 if (xmlQualifiedName == null) 299 { 300 xmlQualifiedName = MessageBuilder.XsdDataContractExporter.GetSchemaTypeName(declaredMessageType); 301 } 302 303 if (!xmlQualifiedName.IsEmpty) 304 { 305 partName = xmlQualifiedName.Name; 306 partNamespace = xmlQualifiedName.Namespace; 307 } 308 else 309 { 310 // For anonymous type, we assign CLR type name and contract namespace to MessagePartDescription 311 partName = declaredMessageType.Name; 312 partNamespace = operation.DeclaringContract.Namespace; 313 } 314 } 315 else 316 { 317 XmlTypeMapping xmlTypeMapping = MessageBuilder.XmlReflectionImporter.ImportTypeMapping(declaredMessageType); 318 partName = xmlTypeMapping.ElementName; 319 partNamespace = xmlTypeMapping.Namespace; 320 } 321 322 MessagePartDescription targetPart = null; 323 324 if (isResponse && targetMessage.Body.ReturnValue != null && targetMessage.Body.ReturnValue.Type != TypeHelper.VoidType) 325 { 326 if (targetMessage.Body.Parts.Count > 0) 327 { 328 Constraint.AddValidationError(context, new ValidationError(SR2.NotSupportMoreThanOneParametersInMessageContract(operation.Name, operation.DeclaringContract.Name))); 329 } 330 targetPart = targetMessage.Body.ReturnValue; 331 } 332 else if (!isResponse) 333 { 334 if (targetMessage.Body.WrapperName != null && targetMessage.Body.WrapperName != String.Empty) 335 { 336 Constraint.AddValidationError(context, new ValidationError(SR2.WrapperNotSupportedInMessageContract(operation.Name, operation.DeclaringContract.Name))); 337 } 338 339 if (targetMessage.Body.WrapperNamespace != null && targetMessage.Body.WrapperNamespace != String.Empty) 340 { 341 Constraint.AddValidationError(context, new ValidationError(SR2.WrapperNotSupportedInMessageContract(operation.Name, operation.DeclaringContract.Name))); 342 } 343 344 if (targetMessage.Body.Parts.Count == 0) 345 { 346 Constraint.AddValidationError(context, new ValidationError(SR2.ParameterNumberMismatch(declaredMessageType.FullName, operation.Name, operation.DeclaringContract.Name))); 347 } 348 else if (targetMessage.Body.Parts.Count > 1) 349 { 350 Constraint.AddValidationError(context, new ValidationError(SR2.MessageContentCannotHaveMoreThanOneParameter(operation.Name, operation.DeclaringContract.Name))); 351 } 352 else 353 { 354 targetPart = targetMessage.Body.Parts[0]; 355 } 356 } 357 358 if (targetPart != null) 359 { 360 if (partName != targetPart.Name) 361 { 362 Constraint.AddValidationError(context, new ValidationError(SR2.PropertyMismatch(partName, "parameter name", targetPart.Name, operation.Name, operation.DeclaringContract.Name))); 363 } 364 if (partNamespace != targetPart.Namespace) 365 { 366 Constraint.AddValidationError(context, new ValidationError(SR2.PropertyMismatch(partNamespace, "parameter namespace", targetPart.Namespace, operation.Name, operation.DeclaringContract.Name))); 367 } 368 if (declaredMessageType != targetPart.Type) 369 { 370 if (declaredMessageType != null) 371 { 372 Constraint.AddValidationError(context, new ValidationError(SR2.ParameterTypeMismatch(declaredMessageType.FullName, targetPart.Type.FullName, operation.Name, operation.DeclaringContract.Name))); 373 } 374 else 375 { 376 Constraint.AddValidationError(context, new ValidationError(SR2.ParameterTypeMismatch(TypeHelper.VoidType.FullName, targetPart.Type.FullName, operation.Name, operation.DeclaringContract.Name))); 377 } 378 } 379 if (targetPart.HasProtectionLevel) 380 { 381 Constraint.AddValidationError(context, new ValidationError(SR2.ProtectionLevelIsNotSupported(operation.Name, operation.DeclaringContract.Name))); 382 } 383 384 // Multiple and Index do not need to be validate because there is only one part in the message. 385 } 386 } 387 } 388 ValidateParametersContent(NativeActivityContext context, MessageDescription targetMessage, IDictionary parameters, OperationDescription targetOperation, bool isResponse)389 public static void ValidateParametersContent(NativeActivityContext context, MessageDescription targetMessage, IDictionary parameters, 390 OperationDescription targetOperation, bool isResponse) 391 { 392 // The following properties can only be set via message contract. Therefore, we do not need to validate them here. 393 // MessageDescription: Headers, Properties, ProtectionLevel 394 // MessagePartDescription: Namespace, ProtectionLevel, Multiple, Index 395 MessageBodyDescription targetMessageBody = targetMessage.Body; 396 Fx.Assert(targetMessageBody != null, "MessageDescription.Body is never null!"); 397 398 if (targetMessageBody.WrapperName == null) 399 { 400 Constraint.AddValidationError(context, new ValidationError(SR2.UnwrappedMessageNotSupported(targetOperation.Name, targetOperation.DeclaringContract.Name))); 401 } 402 if (targetMessageBody.WrapperNamespace == null) 403 { 404 Constraint.AddValidationError(context, new ValidationError(SR2.UnwrappedMessageNotSupported(targetOperation.Name, targetOperation.DeclaringContract.Name))); 405 } 406 407 IDictionaryEnumerator iterator = parameters.GetEnumerator(); 408 int benchmarkIndex = 0; 409 int hitCount = 0; 410 411 // Return value needs to be treated specially since ReceiveParametersContent does not have return value on the OM. 412 bool targetHasReturnValue = isResponse && targetMessageBody.ReturnValue != null && targetMessageBody.ReturnValue.Type != TypeHelper.VoidType; 413 if (targetHasReturnValue) 414 { 415 if (iterator.MoveNext() && (string)iterator.Key == targetMessageBody.ReturnValue.Name) 416 { 417 Argument argument = (Argument)iterator.Value; 418 if (argument != null && argument.ArgumentType != targetMessageBody.ReturnValue.Type) 419 { 420 Constraint.AddValidationError(context, new ValidationError(SR2.FirstParameterDoesnotMatchTheReturnValue(argument.ArgumentType.FullName, targetMessageBody.ReturnValue.Type.FullName, targetOperation.Name, targetOperation.DeclaringContract.Name))); 421 } 422 hitCount++; 423 } 424 else if (parameters.Contains(targetMessageBody.ReturnValue.Name)) 425 { 426 Constraint.AddValidationError(context, new ValidationError(SR2.ParameterPositionMismatch(targetMessageBody.ReturnValue.Name, targetOperation.Name, targetOperation.DeclaringContract.Name, "0"))); 427 hitCount++; 428 } 429 else 430 { 431 Constraint.AddValidationError(context, new ValidationError(SR2.ReturnValueMissing(targetMessageBody.ReturnValue.Type.FullName, targetOperation.Name, targetOperation.DeclaringContract.Name))); 432 } 433 434 benchmarkIndex++; 435 } 436 437 foreach (MessagePartDescription targetPart in targetMessageBody.Parts) 438 { 439 if (iterator.MoveNext() && (string)iterator.Key == targetPart.Name) 440 { 441 Argument argument = (Argument)iterator.Value; 442 if (argument != null && argument.ArgumentType != targetPart.Type) 443 { 444 Constraint.AddValidationError(context, new ValidationError(SR2.ParameterTypeMismatch(targetPart.Name, targetPart.Type.FullName, targetOperation.Name, targetOperation.DeclaringContract.Name))); 445 } 446 hitCount++; 447 } 448 else if (parameters.Contains(targetPart.Name)) 449 { 450 Constraint.AddValidationError(context, new ValidationError(SR2.ParameterPositionMismatch(targetPart.Name, targetOperation.Name, targetOperation.DeclaringContract.Name, benchmarkIndex))); 451 hitCount++; 452 } 453 else 454 { 455 Constraint.AddValidationError(context, new ValidationError(SR2.MissingParameter(targetPart.Name, targetOperation.Name, targetOperation.DeclaringContract.Name))); 456 } 457 458 benchmarkIndex++; 459 } 460 461 if (hitCount != parameters.Count) 462 { 463 foreach (string name in parameters.Keys) 464 { 465 XmlQualifiedName qName = new XmlQualifiedName(name, targetOperation.DeclaringContract.Namespace); 466 if (!targetMessageBody.Parts.Contains(qName)) 467 { 468 if (!targetHasReturnValue || targetHasReturnValue && name != targetMessageBody.ReturnValue.Name) 469 { 470 Constraint.AddValidationError(context, new ValidationError(SR2.ExtraParameter(name, targetOperation.Name, targetOperation.DeclaringContract.Name))); 471 } 472 } 473 } 474 } 475 } 476 477 // This method trying to validate if the receive message from the operation description should be Parameter content or Message Content IsReceiveParameterContent(OperationDescription operation)478 public static bool IsReceiveParameterContent(OperationDescription operation) 479 { 480 Fx.Assert(operation != null, "OperationDescription should not be null"); 481 MessageDescription message; 482 bool contentIsParameter = false; 483 bool noReceiveMessageContent = false; 484 485 message = operation.Messages[0]; 486 487 // MessageType is null indicating it is not typed message contract 488 if (message.MessageType == null) 489 { 490 if (message.Body.Parts != null) 491 { 492 if (message.Body.Parts.Count != 0) 493 { 494 foreach (MessagePartDescription messagePart in message.Body.Parts) 495 { 496 if (messagePart.Index > 0) 497 { 498 contentIsParameter = true; 499 break; 500 } 501 // Indicating it is a untyped message contract 502 if (!messagePart.Type.IsAssignableFrom(typeof(System.ServiceModel.Channels.Message))) 503 { 504 contentIsParameter = true; 505 break; 506 } 507 } 508 } 509 else 510 { 511 noReceiveMessageContent = true; 512 } 513 } 514 else 515 { 516 noReceiveMessageContent = true; 517 } 518 } 519 520 if (noReceiveMessageContent) 521 { 522 if ((message.Body.ReturnValue != null && message.Body.ReturnValue.Type.IsDefined(typeof(MessageContractAttribute), false)) 523 || (message.Body.ReturnValue != null && message.Body.ReturnValue.Type.IsAssignableFrom(typeof(System.ServiceModel.Channels.Message)))) 524 { 525 contentIsParameter = false; 526 } 527 else if (operation.Messages.Count > 1) 528 { 529 if (operation.Messages[1].MessageType != null || operation.Messages[1].Body.ReturnValue.Type.IsAssignableFrom(typeof(System.ServiceModel.Channels.Message))) 530 { 531 contentIsParameter = false; 532 } 533 else 534 { 535 contentIsParameter = true; 536 } 537 } 538 else 539 { 540 contentIsParameter = true; 541 } 542 } 543 544 return contentIsParameter; 545 } 546 IsSendParameterContent(OperationDescription operation)547 public static bool IsSendParameterContent(OperationDescription operation) 548 { 549 Fx.Assert(operation != null, "OperationDescription should not be null"); 550 if (operation.IsOneWay) 551 { 552 return false; 553 } 554 555 bool contentIsParameter = false; 556 bool isSendContentEmpty = false; 557 MessageDescription message; 558 559 if (operation.Messages.Count > 1) 560 { 561 message = operation.Messages[1]; 562 contentIsParameter = false; 563 564 if (message.MessageType == null) 565 { 566 if (message.Body.ReturnValue != null && message.Body.ReturnValue.Type != typeof(void)) 567 { 568 if (!message.Body.ReturnValue.Type.IsAssignableFrom(typeof(System.ServiceModel.Channels.Message))) 569 { 570 contentIsParameter = true; 571 } 572 573 isSendContentEmpty = true; 574 } 575 } 576 577 if (message.MessageType == null) 578 { 579 if (message.Body.Parts != null) 580 { 581 if (message.Body.Parts.Count > 0) 582 { 583 MessagePartDescriptionCollection parts = message.Body.Parts; 584 foreach (MessagePartDescription messagePart in parts) 585 { 586 if (messagePart.Index >= 0) 587 { 588 contentIsParameter = true; 589 break; 590 } 591 if (!messagePart.Type.IsAssignableFrom(typeof(System.ServiceModel.Channels.Message))) 592 { 593 contentIsParameter = true; 594 } 595 } 596 isSendContentEmpty = true; 597 } 598 } 599 } 600 601 if (!isSendContentEmpty) 602 { 603 if (message.MessageType != null && message.MessageType.IsDefined(typeof(MessageContractAttribute), false)) 604 { 605 contentIsParameter = false; 606 } 607 else if (operation.Messages[0].MessageType != null) 608 { 609 contentIsParameter = false; 610 } 611 else if (operation.Messages[0].Body.Parts != null 612 && operation.Messages[0].Body.Parts.Count == 1 613 && operation.Messages[0].Body.Parts[0].Type.IsAssignableFrom(typeof(System.ServiceModel.Channels.Message))) 614 { 615 contentIsParameter = false; 616 } 617 else 618 { 619 contentIsParameter = true; 620 } 621 } 622 } 623 624 return contentIsParameter; 625 } 626 GetErrorMessageEndpointName(string endpointName)627 public static string GetErrorMessageEndpointName(string endpointName) 628 { 629 return !string.IsNullOrEmpty(endpointName) ? endpointName : SR.NotSpecified; 630 } 631 GetErrorMessageEndpointServiceContractName(XName serviceContractName)632 public static string GetErrorMessageEndpointServiceContractName(XName serviceContractName) 633 { 634 return serviceContractName != null ? serviceContractName.LocalName : SR.NotSpecified; 635 } 636 GetErrorMessageOperationName(string operationName)637 public static string GetErrorMessageOperationName(string operationName) 638 { 639 return !string.IsNullOrEmpty(operationName) ? operationName : SR.NotSpecified; 640 } 641 } 642 } 643