Reputation: 3261
I am passing in a SOAP request, that prior to making some changes to look at changing the out going prefix from s:Envelop to soap-env:Envelope as per this example https://www.vanacosmin.ro/Articles/Read/WCFEnvelopeNamespacePrefix I am passing
<soap-env:Envelope
xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:pro="http://www.xxxx">
<soap-env:Header/>
<soap-env:Body>
<pro:getProposalList version="6.66">
<pro:code>323232</pro:code>
</pro:getProposalList>
</soap-env:Body>
and was getting
<s:Envelope
xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<ProposalList Version="3.22"
xmlns="http://xxxxx">
<ProposalHeader>
<RefNum>1</RefNum>
<Size>24</Size>
<DateSubmitted>2020-06-18</DateSubmitted>
</ProposalHeader>
</ProposalList>
</s:Body>
However I need something like this
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<SOAP-ENV:Body>
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<ProposalList Version="3.22"
xmlns="http://www.xxxx">
<ProposalHeader>
<RefNum>1</RefNum>
<Size>24</Size>
<DateSubmitted>2020-06-18</DateSubmitted>
</ProposalHeader>
</ProposalList>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
When I pass in an object that then instantiates this class
public class ProposalMessageFormatter : IDispatchMessageFormatter
{
private readonly IDispatchMessageFormatter formatter;
public ProposalMessageFormatter(IDispatchMessageFormatter formatter)
{
this.formatter = formatter;
}
public void DeserializeRequest(Message message, object[] parameters)
{
this.formatter.DeserializeRequest(message, parameters);
}
public Message SerializeReply(MessageVersion messageVersion, object[] parameters, object result)
{
var message = this.formatter.SerializeReply(messageVersion, parameters, result);
return new ProposalMessage(message);
}
}
IDispatchMessageFormatter formatter
is null
I suspect that this could be the cause of the issue
I am using autofac for my DI and my global.asax.cs and have had this not referenced and referenced as these examples
builder.RegisterType<ProposalMessageFormatter>().As<IDispatchMessageFormatter>();
builder.RegisterType<ProposalMessageFormatter>().SingleInstance();
builder.RegisterType<ProposalMessageFormatter>().UsingConstructor(typeof(IDispatchMessageFormatter));
The error that comes back is
The server was unable to process the request due to an internal error. For more information about the error, either turn on IncludeExceptionDetailInFaults (either from ServiceBehaviorAttribute or from the <serviceDebug> configuration behavior) on the server in order to send the exception information back to the client, or turn on tracing as per the Microsoft .NET Framework SDK documentation and inspect the server trace logs.
a bit more detail on this error now
<s:Envelope
xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body>
<s:Fault>
<faultcode
xmlns:a="http://schemas.microsoft.com/net/2005/12/windowscommunicationfoundation/dispatcher">a:InternalServiceFault
</faultcode>
<faultstring xml:lang="en-GB">Object reference not set to an instance of an object.</faultstring>
<detail>
<ExceptionDetail
xmlns="http://schemas.datacontract.org/2004/07/System.ServiceModel"
xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<HelpLink i:nil="true"/>
<InnerException i:nil="true"/>
<Message>Object reference not set to an instance of an object.</Message>
<StackTrace> at TQ.LPAConnector.Service.MessageFormatter.ProposalMessageFormatter.DeserializeRequest(Message message, Object[] parameters) in C:\Projects\xxx.Service\MessageFormatter\ProposalMessageFormatter.cs:line 17
at System.ServiceModel.Dispatcher.DispatchOperationRuntime.DeserializeInputs(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.DispatchOperationRuntime.InvokeBegin(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage5(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage41(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage4(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage31(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage3(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage2(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage11(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage1(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.MessageRpc.Process(Boolean isOperationContextSet)</StackTrace>
<Type>System.NullReferenceException</Type>
</ExceptionDetail>
</detail>
</s:Fault>
</s:Body>
</s:Envelope>
As you can see from the request, this is not null, and was working prior to the change so wonder what I may have missed.
Upvotes: 0
Views: 454
Reputation: 3954
Here is my demo:
public class ProposalMessageFormatter : IDispatchMessageFormatter
{
private readonly IDispatchMessageFormatter formatter;
public ProposalMessageFormatter(IDispatchMessageFormatter formatter)
{
this.formatter = formatter;
}
public void DeserializeRequest(Message message, object[] parameters)
{
this.formatter.DeserializeRequest(message, parameters);
}
public Message SerializeReply(MessageVersion messageVersion, object[] parameters, object result)
{
var message = this.formatter.SerializeReply(messageVersion, parameters, result);
return new ProposalMessage(message);
}
}
This is ProposalMessageFormatter.
public class MyOperationBehavior : IOperationBehavior
{
public void AddBindingParameters(OperationDescription operationDescription, BindingParameterCollection bindingParameters)
{
return;
}
public void ApplyClientBehavior(OperationDescription operationDescription, ClientOperation clientOperation)
{
return;
}
public void ApplyDispatchBehavior(OperationDescription operationDescription, DispatchOperation dispatchOperation)
{
dispatchOperation.Formatter = new ProposalMessageFormatter(dispatchOperation.Formatter);
}
public void Validate(OperationDescription operationDescription)
{
return;
}
}
This is MyOperationBehavior.
[AttributeUsage(AttributeTargets.Interface, AllowMultiple = false)]
public class MyContractBehaviorAttribute : 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)
{
OperationDescription op = contractDescription.Operations[0];
op.Behaviors.Add(new MyOperationBehavior());
}
public void Validate(ContractDescription contractDescription, ServiceEndpoint endpoint)
{
return;
}
}
This is MyContractBehaviorAttribute.Add MyOperationBehavior to the endpoint through MyContractBehaviorAttribute.
Finally, we add this attribute to the WCF service.
Upvotes: 1