How to Get the Xml Soap Request of an Wcf Web Service Request

How do I capture incoming and outgoing XML from WCF service end

The error was caused because xmlRequest/xmlResponse have not been initialized when you access them. Hence, try to check null, or create default instances for them.

From your code they are only initialized in the ProcessMessage(SoapMessage message){}, make sure that the method is called before you call

 var soapRequest = SoapLogger.TraceExtension.XmlRequest.InnerXml;
var soapResponse = SoapLogger.TraceExtension.XmlResponse.InnerXml;

Hope this helps.

EDIT:

After closely examining your code, I realized that the extension you wrote (SoapExtension) was for ASP.NET XML web services, and it had no business with a WCF service.

To inspect the request and reply in a WCF service, you can extend your dispatcher on the service side by implementing System.ServiceModel.Dispatcher.IDispatchMessageInspector.

You can find the example here http://msdn.microsoft.com/en-us/library/ms733104%28v=vs.100%29.aspx

See SOAP/XML returned by WCF

One of the main benefits WCF has to offer is abstracting you from any serialization/transport issues. Since your service contract returns CompositeType you get an instance of it automatically reconstructed from the underlying XML message on the client side.

However, if you want to get a raw XML you can still do that by performing direct call depending on what transport is supported by your WCF server. if it's basicHttpBinding/wsHttpBinding you can perform HTTP request and read a response which will be pure XML. Of course, all the dirty work like authentication and security is on you.

If you need this just for debugging/studying purposes you can enable message logging or use standard WcfTestClient.exe utility.

Is there an easy way to get the soap message for the request and the soap message for the response, when invoking the web service?

Based on the MSDN article WCF Extensibility – Message Inspectors from Carlos Figueira one option is using a MessageInspector.

Create an class that implements an EndBehavior and ClientMessageInspector. Buffer the request and reply message so you can use them later on. In this example I print them in the Console.

Here is the combined implementation:

// using System.ServiceModel.Description;
// using System.ServiceModel.Dispatcher;
// using System.ServiceModel.Channels;
// using System.ServiceModel
public class InspectBehaviorAndnspector : IEndpointBehavior, IClientMessageInspector
{

public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
clientRuntime.MessageInspectors.Add(this);
}

public MessageBuffer RequestBuffer;
public MessageBuffer ReplyBuffer;

public void AfterReceiveReply(ref Message reply, object correlationState){
// messages are read only
ReplyBuffer = reply.CreateBufferedCopy(2048);
// so recreate the message after it was buffered
reply = ReplyBuffer.CreateMessage();
}

public object BeforeSendRequest(ref Message request, IClientChannel channel){
// messages are read only
RequestBuffer = request.CreateBufferedCopy(2048);
// so recreate the message after it was buffered
request = RequestBuffer.CreateMessage();
return "42";
}

// not needed for client
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
{
}

public void Validate(ServiceEndpoint sep)
{
}
public void AddBindingParameters(ServiceEndpoint sep, BindingParameterCollection bpc)
{
}
}

Now on your client instance, assuming it derives from ClientBase, you can do:

var inspector = new InspectBehaviorAndnspector();
client.Endpoint.Behaviors.Add(inspector);

// this is your call
var response = client.invoke(parameter);

// either do a ToString
Console.WriteLine(inspector.RequestBuffer.CreateMessage().ToString());
// or Write it with XmlWriter
var sb = new StringBuilder();
using(var xw = XmlWriter.Create(sb, new XmlWriterSettings {Indent =true})) {
inspector.ReplyBuffer.CreateMessage().WriteMessage(xw);
}
Console.WriteLine(sb.ToString());

I have run this on an example with an Add service and this was my result:

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Header>
<Action s:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">http://tempuri.org/ISelfHostTest/Add</Action>
</s:Header>
<s:Body>
<Add xmlns="http://tempuri.org/">
<x>3</x>
<y>2</y>
</Add>
</s:Body>
</s:Envelope>

<?xml version="1.0" encoding="utf-16"?>
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body>
<AddResponse xmlns="http://tempuri.org/">
<AddResult>5</AddResult>
</AddResponse>
</s:Body>
</s:Envelope>

request soap wcf webService with android retrofit

There were plenty of wrong with your classes.
I have modified and tested. I Was able to convert xml to object.

Envelope Class.

    /**
* Created by kbiradar on 7/26/2018.
*/

@Root(name = "Envelope")
@Order(elements = {"Header", "Body"})
@Namespace(prefix = "s", reference = "http://schemas.xmlsoap.org/soap/envelope/")
public class Envelope {

@Element(name = "Header")
@Namespace(prefix = "s", reference = "http://schemas.xmlsoap.org/soap/envelope/")
private Header header;

@Element(name = "Body")
@Namespace(prefix = "s", reference = "http://schemas.xmlsoap.org/soap/envelope/")
private Body body;

public Body getBody() {
return body;
}

public void setBody(Body body) {
this.body = body;
}

public Header getHeader() {
return header;
}

public void setHeader(Header body) {
this.header = body;
}
}

Header Class.

/**
* Created by kbiradar on 7/26/2018.
*/

@Root(name = "Header", strict = false)
public class Header {

static class ActivityId
{
@Attribute
String CorrelationId;

@Text
private String ActivityId;
}

@Element(name = "ActivityId")
ActivityId ActivityId;
}

Body Class.

/**
* Created by kbiradar on 7/26/2018.
*/
@Root(name = "Body", strict = false)
public class Body {

@Element(name = "QueryMessage")
//@Namespace(prefix = "s", reference = "http://schemas.xmlsoap.org/soap/envelope/")
@Namespace(reference = "http://tempuri.org/")
private QueryMessage queryMessage;

public QueryMessage getQueryMessage() {
return queryMessage;
}

public void setQueryMessage(QueryMessage queryMessage) {
this.queryMessage = queryMessage;
}
}

QueryMessage Class.

/**
* Created by kbiradar on 7/26/2018.
*/

@Root(name = "QueryMessage")
public class QueryMessage {

@Element(name = "messageSet")
@NamespaceList({ @Namespace( prefix = "a", reference = "http://schemas.datacontract.org/2004/07/Sanay.Suip.Library"),
@Namespace( prefix = "i", reference = "http://www.w3.org/2001/XMLSchema-instance") })
private MessageSet messageSet;

public MessageSet getMessageSet() {
return messageSet;
}

public void setMessageSet(MessageSet messageSet) {
this.messageSet = messageSet;
}
}

MessageSet Class.

/**
* Created by kbiradar on 7/26/2018.
*/

@Root(name = "messageSet")
public class MessageSet {

static class ActionId
{
@Attribute
@Namespace(prefix = "i", reference = "http://www.w3.org/2001/XMLSchema-instance")
String nil;

@Text
private String actionId;
}

@Element(name = "ActionId")
@Namespace(prefix = "a", reference = "http://schemas.datacontract.org/2004/07/Sanay.Suip.Library")
ActionId actionId;

@Element(name = "Ip")
@Namespace(prefix = "a", reference = "http://schemas.datacontract.org/2004/07/Sanay.Suip.Library")
private String ip;

@ElementList(name = "Parameters")
@Namespace(prefix = "a", reference = "http://schemas.datacontract.org/2004/07/Sanay.Suip.Library")
private List<ModelParameter> modelParameterList;

@Element(name = "Title")
@Namespace(prefix = "a", reference = "http://schemas.datacontract.org/2004/07/Sanay.Suip.Library")
private String title;

@Element(name = "Token",required = false)
@Namespace(prefix = "a", reference = "http://schemas.datacontract.org/2004/07/Sanay.Suip.Library")
private String token;

@Element(name = "Username")
@Namespace(prefix = "a", reference = "http://schemas.datacontract.org/2004/07/Sanay.Suip.Library")
private String username;


public String getActionId() {
return actionId.actionId;
}

public void setActionId(String actionId) {
this.actionId.actionId = actionId;
}

public String getIp() {
return ip;
}

public void setIp(String ip) {
this.ip = ip;
}

public List<ModelParameter> getModelParameterList() {
return modelParameterList;
}

public void setModelParameterList(List<ModelParameter> modelParameterList) {
this.modelParameterList = modelParameterList;
}

public String getTitle() {
return title;
}

public void setTitle(String title) {
this.title = title;
}

public String getToken() {
return token;
}

public void setToken(String token) {
this.token = token;
}

public String getUsername() {
return username;
}

public void setUsername(String username) {
this.username = username;
}
}

Message Parameter class.

/**
* Created by kbiradar on 7/26/2018.
*/

@Root(name = "Parameter")
@Namespace(prefix = "a", reference = "http://schemas.datacontract.org/2004/07/Sanay.Suip.Library")
public class ModelParameter {


static class value
{
@Attribute
@Namespace(prefix = "i", reference = "http://www.w3.org/2001/XMLSchema-instance")
String type;

@Text
private String value;
}

@Element(name = "Name")
@Namespace(prefix = "a", reference = "http://schemas.datacontract.org/2004/07/Sanay.Suip.Library")
private String name;


@Element(name = "Value")
@Namespace(prefix = "a", reference = "http://schemas.datacontract.org/2004/07/Sanay.Suip.Library")
@NamespaceList({@Namespace(prefix = "a", reference = "http://schemas.datacontract.org/2004/07/Sanay.Suip.Library"),
@Namespace(prefix = "b", reference = "http://www.w3.org/2001/XMLSchema")})
private value value;


public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getValue() {
return value.value;
}

public void setValue(String value) {
this.value.value = value;
}
}

Post soap message over http to WCF service error 400

I think the issue was how the XML data was being attached to the request. This is the working example I have for WebGet. This also works for WebInvoke methods also, but of course, just need to modify the soap body with expected paramters

Console app

private static void TestGet()
{
Console.WriteLine("[TestGet]\n");

const string soapMsg = @"<SOAP-ENV:Envelope xmlns:SOAP-ENV=""http://schemas.xmlsoap.org/soap/envelope/""
xmlns:xsi=""http://www.w3.org/1999/XMLSchema-instance""
xmlns:xsd=""http://www.w3.org/1999/XMLSchema"">
<SOAP-ENV:Body>
<TestGet xmlns=""http://tempuri.org/"" SOAP-ENV:encodingStyle=""http://schemas.xmlsoap.org/soap/encoding/"" />
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>";

PerformSOAPRequest(URL, "TestGet", soapMsg);
}

public static void PerformSOAPRequest(string _url, string _method, string xml_message)
{
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(_url);
webRequest.Accept = "text/xml";
webRequest.ContentType = "text/xml;charset=\"utf-8\"";
webRequest.Headers.Add(@"SOAPAction", string.Format("http://tempuri.org/IService1/{0}", _method));
webRequest.Method = "POST";

byte[] bytes = Encoding.UTF8.GetBytes(xml_message);

webRequest.ContentLength = bytes.Length;

using (Stream putStream = webRequest.GetRequestStream())
{
putStream.Write(bytes, 0, bytes.Length);
}

using (WebResponse response = webRequest.GetResponse())
using (StreamReader rd = new StreamReader(response.GetResponseStream()))
{
string soapResult = rd.ReadToEnd();

Console.WriteLine(soapResult);
}
}

IService1 in WCF

[ServiceContract]
public interface IService1
{
[OperationContract]
[WebGet(BodyStyle = WebMessageBodyStyle.Wrapped,
RequestFormat = WebMessageFormat.Xml,
ResponseFormat = WebMessageFormat.Xml,
UriTemplate = "/TestGet")]
string TestGet();
}

WCF service, response in SOAP or plain XML, how?

The service you have here will return a SOAP message - which will contain the "CompositeType" as its "payload".

WCF by default uses SOAP - any of the basicHttpBinding, wsHttpBinding, netTcpBinding etc. all work with SOAP as their basis.

If you want to return straight XML, you need to check out the REST capabilities of WCF - this works with the webHttpBinding (and only that binding).

Also, how to produce an XML like this (based on data contract):

<CompositeType BoolValue = 0 StringValue = "">

rather than this:

<CompositeType>
<BoolValue>0</BoolValue>
<StringValue></StringValue>
</CompositeType>

This is a limitation of the WCF DataContract serializer. For performance reasons, it does not support attributes, e.g. you cannot create the first fragment of XML that you want.

If you absolutely must have the first XML, you'll need to use the XmlSerializer instead (which has its own set of limitations / problems).

Marc

UPDATE: if you just want to return a given XML, then you're probably better off with the REST approach.

Check out the Pluralsight website for an excellent series of screencasts on using REST and in particular, one screencast on how to create a plain-old XML (POX) REST service.

Can't send WCF Service request as SOAP+XML

BasicHttpBinding uses SOAP 1.1 so you cannot send request in SOAP 1.2 to the endpoint using this binding. HTTP status code 415 means unsupported media type which also implies this because SOAP 1.1 uses text/xml content type whereas SOAP 1.2 uses application/soap+xml content type.

If you want BasicHttpBinding equivalent with SOAP 1.2 without any other WS-* stuff included in WsHttpBinding you need to create custom binding. The simplest version looks like:

<bindings>
<customBinding>
<binding name="soap12">
<textMessageEncoding messageVersion="Soap12" />
<httpTransport />
</binding>
</customBinding>
</bindings>

Then you must manually define the endpoint for your service (at the moment you are using default endpoint):

<services>
<service name="YourNamespace.YourServiceClass">
<endpoint address="" binding="customBinding" bindingConfiguration="soap12"
contract="YourNamespace.YourServiceContractInterface" />
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</service>
</services>

Anyway I hardly believe that reconfiguring the SOAP version for consuming your service in Oracle SOA middleware takes more then few minutes.

WCF: Send SOAP request with custom header

If you want to add a custom header on the server-side, just implement the IDispatchMessageInspector interface.

Here is my Demo:

  public class CustomMessageInspector : IDispatchMessageInspector
{
public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
{
MessageHeader header = MessageHeader.CreateHeader("Testrequest", "http://Test", "Test");
OperationContext.Current.IncomingMessageHeaders.Add(header);
Console.WriteLine("request"+request);
return null;
}

public void BeforeSendReply(ref Message reply, object correlationState)
{
MessageHeader header = MessageHeader.CreateHeader("Testreply", "http://Test", "Test");
OperationContext.Current.OutgoingMessageHeaders.Add(header);
Console.WriteLine("reply"+reply);
}
}

CustomMessageInspector implements the IDispatchMessageInspector interface, and adds a custom header to the message after getting the message, and also adds a custom header before sending the message.

 [AttributeUsage(AttributeTargets.Interface)]
public class CustomBehavior : Attribute, IContractBehavior
{
public void AddBindingParameters(ContractDescription contractDescription, ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
{
return;
}

public void ApplyClientBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
return;
}
public void ApplyDispatchBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, DispatchRuntime dispatchRuntime)
{
dispatchRuntime.MessageInspectors.Add(new CustomMessageInspector());
}

public void Validate(ContractDescription contractDescription, ServiceEndpoint endpoint)
{
return;
}
}

We add this interceptor to the behavior of the service.

Sample Image

Finally we apply Custombehavior to our service.

UPDATE

My project:

namespace Test
{

public class CustomMessageInspector : IDispatchMessageInspector
{
public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
{
MessageHeader header = MessageHeader.CreateHeader("Testrequest", "http://Test", "Test");
OperationContext.Current.IncomingMessageHeaders.Add(header);
Console.WriteLine("request"+request);
return null;
}

public void BeforeSendReply(ref Message reply, object correlationState)
{
MessageHeader header = MessageHeader.CreateHeader("Testreply", "http://Test", "Test");
OperationContext.Current.OutgoingMessageHeaders.Add(header);
Console.WriteLine("reply"+reply);
}
}

[AttributeUsage(AttributeTargets.Interface)]
public class CustomBehavior : Attribute, IContractBehavior
{
public void AddBindingParameters(ContractDescription contractDescription, ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
{
return;
}

public void ApplyClientBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
return;
}

public void ApplyDispatchBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, DispatchRuntime dispatchRuntime)
{
dispatchRuntime.MessageInspectors.Add(new CustomMessageInspector());
}

public void Validate(ContractDescription contractDescription, ServiceEndpoint endpoint)
{
return;
}
}
class Program
{

[ServiceContract]
[CustomBehavior]
public interface IService1
{
[OperationContract]
string hello();
}
public class Service1 : IService1
{
public string hello()
{
return "hi";
}
}

static void Main(string[] args)
{
// Step 1: Create a URI to serve as the base address.
Uri baseAddress = new Uri("http://localhost:8000/GettingStarted/");

// Step 2: Create a ServiceHost instance.
ServiceHost selfHost = new ServiceHost(typeof(Service1), baseAddress);

try
{
// Step 3: Add a service endpoint.
selfHost.AddServiceEndpoint(typeof(IService1), new BasicHttpBinding(), "CalculatorService");

// Step 4: Enable metadata exchange.
ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
smb.HttpGetEnabled = true;
selfHost.Description.Behaviors.Add(smb);

// Step 5: Start the service.
selfHost.Open();
Console.WriteLine("The service is ready.");

// Close the ServiceHost to stop the service.
Console.WriteLine("Press <Enter> to terminate the service.");
Console.WriteLine();
Console.ReadLine();
selfHost.Close();
}
catch (CommunicationException ce)
{
Console.WriteLine("An exception occurred: {0}", ce.Message);
selfHost.Abort();
}
}
}
}


Related Topics



Leave a reply



Submit