Created
February 4, 2013 14:27
-
-
Save mfenniak/4707000 to your computer and use it in GitHub Desktop.
Snippet to create and read a System.ServiceModel.Channels.Message object representing a WCF operation invocation containing multiple parameters. This is how you would use DataContractSerializer to make an entire operation call, including each individual parameter, rather than just serializing one object at a time.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.IO; | |
using System.Linq; | |
using System.Runtime.Serialization; | |
using System.ServiceModel.Channels; | |
using System.ServiceModel.Description; | |
using System.Text; | |
using System.Xml; | |
public static class SoapUtilities | |
{ | |
class RequestMessageBodyWriter : BodyWriter | |
{ | |
private MessageBodyDescription bodyDescription; | |
private object[] parameters; | |
public RequestMessageBodyWriter(MessageBodyDescription bodyDescription, object[] parameters) | |
: base(false) | |
{ | |
this.bodyDescription = bodyDescription; | |
this.parameters = parameters; | |
} | |
protected override void OnWriteBodyContents(XmlDictionaryWriter writer) | |
{ | |
// Can't Dispose this xmlWriter, 'cause it will close 'writer'. | |
var xmlWriter = XmlWriter.Create(writer); | |
xmlWriter.WriteStartElement(bodyDescription.WrapperName, bodyDescription.WrapperNamespace); | |
foreach (var part in bodyDescription.Parts) | |
{ | |
var dcs = new DataContractSerializer(part.Type, part.Name, part.Namespace); | |
dcs.WriteObject(xmlWriter, parameters[part.Index]); | |
} | |
xmlWriter.WriteEndElement(); | |
} | |
} | |
/// <summary> | |
/// Creates a SOAP message representing an operation call. | |
/// </summary> | |
/// <param name="parameters">An array of objects representing the parameters of the operation.</param> | |
/// <param name="serviceContractType">The Type object of the service contract definition.</param> | |
/// <param name="operationContractName">The name of the operation method.</param> | |
public static string WriteOperationRequest(object[] parameters, Type serviceContractType, string operationContractName) | |
{ | |
var serviceDescription = ContractDescription.GetContract(serviceContractType); | |
var operationDescription = serviceDescription.Operations.Single(op => op.Name == operationContractName); | |
var inputMessage = operationDescription.Messages.Single(msgDescription => msgDescription.Direction == MessageDirection.Input); | |
var body = inputMessage.Body; | |
var soapMessage = Message.CreateMessage( | |
MessageVersion.Soap12, | |
serviceDescription.Namespace + serviceDescription.Name + "/" + operationDescription.Name, | |
new RequestMessageBodyWriter(body, parameters) | |
); | |
var sb = new StringBuilder(); | |
using (var xmlWriter = XmlWriter.Create(sb)) | |
soapMessage.WriteMessage(xmlWriter); | |
return sb.ToString(); | |
} | |
/// <summary> | |
/// Reads a SOAP message for a specific operation and deserializes the operation parameters. This is the | |
/// inverse of WriteOperationRequest. | |
/// </summary> | |
/// <param name="message">The message content.</param> | |
/// <param name="serviceContractType">The Type object of the service contract definition.</param> | |
/// <param name="operationContractName">The name of the operation method.</param> | |
public static object[] ReadOperationParameters(string message, Type serviceContractType, string operationContractName) | |
{ | |
var serviceDescription = ContractDescription.GetContract(serviceContractType); | |
var operationDescription = serviceDescription.Operations.Single(op => op.Name == operationContractName); | |
var inputMessage = operationDescription.Messages.Single(msgDescription => msgDescription.Direction == MessageDirection.Input); | |
var bodyDescription = inputMessage.Body; | |
object[] parameters = new object[inputMessage.Body.Parts.Count]; | |
using (var stringReader = new StringReader(message)) | |
using (var messageReader = XmlReader.Create(stringReader)) | |
{ | |
var soapMessage = System.ServiceModel.Channels.Message.CreateMessage( | |
messageReader, | |
1024 * 1024, | |
System.ServiceModel.Channels.MessageVersion.Soap12 | |
); | |
var bodyReader = soapMessage.GetReaderAtBodyContents(); | |
bodyReader.ReadStartElement(bodyDescription.WrapperName, bodyDescription.WrapperNamespace); | |
foreach (var part in bodyDescription.Parts) | |
{ | |
var dcs = new DataContractSerializer(part.Type, part.Name, part.Namespace); | |
parameters[part.Index] = dcs.ReadObject(bodyReader); | |
} | |
bodyReader.ReadEndElement(); | |
} | |
return parameters; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment