public static void ValidateMessageContent(NativeActivityContext context, MessageDescription targetMessage, Type declaredMessageType, SerializerOption serializerOption, OperationDescription operation, bool isResponse) { // MessageContract is allowed only if the WCF contract interface specifies the same message contract type. if (MessageBuilder.IsMessageContract(declaredMessageType)) { // if it is a typed message contract, we just validate the type of the message matches if (targetMessage.MessageType != null) { if (declaredMessageType != targetMessage.MessageType) { Constraint.AddValidationError(context, new ValidationError(SR2.PropertyMismatch(declaredMessageType.ToString(), "type", targetMessage.MessageType.ToString(), operation.Name, operation.DeclaringContract.Name))); } } else { Constraint.AddValidationError(context, new ValidationError(SR2.PropertyMismatch(declaredMessageType.ToString(), "type", "null", operation.Name, operation.DeclaringContract.Name))); } return; } else if (declaredMessageType != null && declaredMessageType.IsAssignableFrom(typeof(System.ServiceModel.Channels.Message))) { //This is an untyped message contract if (targetMessage.Body == null) { Constraint.AddValidationError(context, new ValidationError(SR2.BodyCannotBeNull)); } else { if (isResponse) { if (targetMessage.Body.ReturnValue == null) { Constraint.AddValidationError(context, new ValidationError(SR2.ExtraReturnValue)); } else if (!targetMessage.Body.ReturnValue.Type.IsAssignableFrom(typeof(System.ServiceModel.Channels.Message))) { Constraint.AddValidationError(context, new ValidationError(SR2.FirstParameterDoesnotMatchTheReturnValue(declaredMessageType.FullName, targetMessage.Body.ReturnValue.Type.Name, operation.Name, operation.DeclaringContract.Name))); } } else { if (targetMessage.Body.Parts.Count == 0) { Constraint.AddValidationError(context, new ValidationError(SR2.ParameterNumberMismatch(declaredMessageType.FullName, operation.Name, operation.DeclaringContract.Name))); } else if (targetMessage.Body.Parts.Count > 1) { Constraint.AddValidationError(context, new ValidationError(SR2.MessageContentCannotHaveMoreThanOneParameter(operation.Name, operation.DeclaringContract.Name))); } else { if (!targetMessage.Body.Parts[0].Type.IsAssignableFrom(typeof(System.ServiceModel.Channels.Message))) { Constraint.AddValidationError(context, new ValidationError(SR2.MessageTypeMismatch(targetMessage.Body.Parts[0].Type.FullName, operation.Name, operation.DeclaringContract.Name))); } } } } return; } // 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 Fx.Assert(targetMessage.Body != null, "MessageDescription.Body is never null!"); // MessageDescription: Headers, Properties, ProtectionLevel // MessageBodyDescription: ReturnValue, WrapperName, WrapperNamespace // MessagePartDescription: Name, Namespace, Type, ProtectionLevel, Multiple, Index if (targetMessage.Headers.Count > 0) { Constraint.AddValidationError(context, new ValidationError(SR2.MessageHeaderNotSupported(operation.Name, operation.DeclaringContract.Name))); } if (targetMessage.Properties.Count > 0) { Constraint.AddValidationError(context, new ValidationError(SR2.MessagePropertyIsNotSupported(operation.Name, operation.DeclaringContract.Name))); } if (targetMessage.HasProtectionLevel) { Constraint.AddValidationError(context, new ValidationError(SR2.ProtectionLevelIsNotSupported(operation.Name, operation.DeclaringContract.Name))); } if (declaredMessageType == null || declaredMessageType == TypeHelper.VoidType) { if (!targetMessage.IsVoid) { Constraint.AddValidationError(context, new ValidationError(SR2.MessageCannotBeEmpty(operation.Name, operation.DeclaringContract.Name))); } } else { string partName; string partNamespace; if (serializerOption == SerializerOption.DataContractSerializer) { XmlQualifiedName xmlQualifiedName = MessageBuilder.XsdDataContractExporter.GetRootElementName(declaredMessageType); if (xmlQualifiedName == null) { xmlQualifiedName = MessageBuilder.XsdDataContractExporter.GetSchemaTypeName(declaredMessageType); } if (!xmlQualifiedName.IsEmpty) { partName = xmlQualifiedName.Name; partNamespace = xmlQualifiedName.Namespace; } else { // For anonymous type, we assign CLR type name and contract namespace to MessagePartDescription partName = declaredMessageType.Name; partNamespace = operation.DeclaringContract.Namespace; } } else { XmlTypeMapping xmlTypeMapping = MessageBuilder.XmlReflectionImporter.ImportTypeMapping(declaredMessageType); partName = xmlTypeMapping.ElementName; partNamespace = xmlTypeMapping.Namespace; } MessagePartDescription targetPart = null; if (isResponse && targetMessage.Body.ReturnValue != null && targetMessage.Body.ReturnValue.Type != TypeHelper.VoidType) { if (targetMessage.Body.Parts.Count > 0) { Constraint.AddValidationError(context, new ValidationError(SR2.NotSupportMoreThanOneParametersInMessageContract(operation.Name, operation.DeclaringContract.Name))); } targetPart = targetMessage.Body.ReturnValue; } else if (!isResponse) { if (targetMessage.Body.WrapperName != null && targetMessage.Body.WrapperName != String.Empty) { Constraint.AddValidationError(context, new ValidationError(SR2.WrapperNotSupportedInMessageContract(operation.Name, operation.DeclaringContract.Name))); } if (targetMessage.Body.WrapperNamespace != null && targetMessage.Body.WrapperNamespace != String.Empty) { Constraint.AddValidationError(context, new ValidationError(SR2.WrapperNotSupportedInMessageContract(operation.Name, operation.DeclaringContract.Name))); } if (targetMessage.Body.Parts.Count == 0) { Constraint.AddValidationError(context, new ValidationError(SR2.ParameterNumberMismatch(declaredMessageType.FullName, operation.Name, operation.DeclaringContract.Name))); } else if (targetMessage.Body.Parts.Count > 1) { Constraint.AddValidationError(context, new ValidationError(SR2.MessageContentCannotHaveMoreThanOneParameter(operation.Name, operation.DeclaringContract.Name))); } else { targetPart = targetMessage.Body.Parts[0]; } } if (targetPart != null) { if (partName != targetPart.Name) { Constraint.AddValidationError(context, new ValidationError(SR2.PropertyMismatch(partName, "parameter name", targetPart.Name, operation.Name, operation.DeclaringContract.Name))); } if (partNamespace != targetPart.Namespace) { Constraint.AddValidationError(context, new ValidationError(SR2.PropertyMismatch(partNamespace, "parameter namespace", targetPart.Namespace, operation.Name, operation.DeclaringContract.Name))); } if (declaredMessageType != targetPart.Type) { if (declaredMessageType != null) { Constraint.AddValidationError(context, new ValidationError(SR2.ParameterTypeMismatch(declaredMessageType.FullName, targetPart.Type.FullName, operation.Name, operation.DeclaringContract.Name))); } else { Constraint.AddValidationError(context, new ValidationError(SR2.ParameterTypeMismatch(TypeHelper.VoidType.FullName, targetPart.Type.FullName, operation.Name, operation.DeclaringContract.Name))); } } if (targetPart.HasProtectionLevel) { Constraint.AddValidationError(context, new ValidationError(SR2.ProtectionLevelIsNotSupported(operation.Name, operation.DeclaringContract.Name))); } // Multiple and Index do not need to be validate because there is only one part in the message. } } }