When creating a generic fault exception FaultException<MyWebServiceFaultDetail>
and passing it back to the message inspector pipeline as a MessageFault, the client will not receive the generic fault in its catch (FaultException<MyWebServiceFaultDetail> ex)
block, it is only caught within the catch (FaultException ex)
block.
The MyWebServiceFaultDetail
and IClientMessageInspector
implication both live within the same project as the client WCF web reference in a single project MyProjects.MyWebService
.
The WebService is called by another project which has a reference to the MyProjects.MyWebService
project.
*Comments have been removed for brevity
The data contract:
[DataContract]
public class MyWebServiceFaultDetail
{
[DataMember]
public string MessageDetail { get; set; }
[DataMember]
public string MessageType { get; set; }
[DataMember]
public string TransactionComplete { get; set; }
[DataMember]
public string TransactionSuccess { get; set; }
public override string ToString()
{
return string.Format("Detail[MessageDetail={0}] [MessageType={1}] [TransactionComplete={2}] [TransactionSuccess={3}]", MessageDetail,MessageType ,TransactionComplete ,TransactionSuccess );
}
}
The message inspector. I would just add that reply.Headers.Action
is null when this method runs. Setting the action value on the call to CreateMessage() has had no affect. Values I have tried.
.CreateMessage(reply.Version, ex.CreateMessageFault(), "*");
.CreateMessage(reply.Version, ex.CreateMessageFault(), reply.Headers.Action);
.CreateMessage(reply.Version, ex.CreateMessageFault(), ex.Action);
internal class ResponseMessageInspector : System.ServiceModel.Dispatcher.IClientMessageInspector
{
private static NLog.Logger _logger = NLog.LogManager.GetCurrentClassLogger();
public void AfterReceiveReply(ref Message reply, object correlationState)
{
MessageBuffer bufferedMessage = null;
try
{
bufferedMessage = reply.CreateBufferedCopy(Int32.MaxValue);
Message replacedMessage = bufferedMessage.CreateMessage();
if (bufferedMessage.MessageContentType != "application/soap+msbin1" || reply.IsEmpty || reply.IsFault)
{
reply = replacedMessage;
return;
}
bool isErrorMessage;
var messageReader = replacedMessage.GetReaderAtBodyContents();
isErrorMessage = (messageReader.Name == "TransactionReport");
if (isErrorMessage)
{
string transactionComplete = "",
transactionSuccess = "",
messageType = "",
messageDetail = "",
messageBrief = "";
while (messageReader.Read())
{
if (messageReader.NodeType == XmlNodeType.Element && !messageReader.IsEmptyElement)
{
switch (messageReader.Name)
{
case "TransactionComplete":
transactionComplete = messageReader.ReadString();
break;
case "TransactionSuccess":
transactionSuccess = messageReader.ReadString();
break;
case "MessageType":
messageType = messageReader.ReadString();
break;
case "MessageDetail":
messageDetail = messageReader.ReadString();
break;
case "MessageBrief":
messageBrief = messageReader.ReadString();
break;
default:
break;
}
}
}
if (string.IsNullOrEmpty(messageBrief))
{
messageBrief = "My response processing fault: {Unable to obtain error message from My response, enable WCF message tracing for more detailed information}";
_logger.Warn(messageBrief);
}
FaultException ex = new FaultException<MyWebServiceFaultDetail>(
new MyWebServiceFaultDetail
{
TransactionComplete = transactionComplete,
TransactionSuccess = transactionSuccess,
MessageDetail = messageDetail,
MessageType = messageType
},
new FaultReason(messageBrief));
Message faultMessage = Message.CreateMessage(reply.Version, ex.CreateMessageFault(), null);
faultMessage.Headers.CopyHeadersFrom(reply.Headers);
faultMessage.Properties.CopyProperties(reply.Properties);
reply = faultMessage;
}
else
reply = bufferedMessage.CreateMessage();
}
finally
{
if (bufferedMessage != null)
bufferedMessage.Close();
}
}
public object BeforeSendRequest(ref Message request, System.ServiceModel.IClientChannel channel)
{
return null;
}
}
The client code that is reciving the FaultException
but not a FaultException<MyWebServiceFaultDetail>
internal static T TrySendToMyWebService<T>(
CallWebServiceDelegate<T> callWebService,
bool expectResponce,
out MessageProcessorResult result) where T : class
{
T MyWebServiceResponce = null;
result = new MessageProcessorResult();
using (ServiceRequestConnectorServiceSoapClient ws =
new ServiceRequestConnectorServiceSoapClient())
{
try
{
MyWebServiceWebServiceHelper.LogOn(ws);
MyWebServiceResponce = callWebService(ws);
if (expectResponce && MyWebServiceResponce == null)
{
result.ShouldRetry = true;
result.RetryReason = "Unexpected MyWebService web service response. The response was null";
}
}
catch (FaultException<MyWebServiceFaultDetail> ex)
{
// I never get called :(
result.Exception = ex;
result.ShouldRetry = true;
result.RetryReason = string.Format("An Exception was raised calling the MyWebService web service: Reason:{0} /r/nDetails: {1}", ex.Reason, ex.Detail.ToString());
_logger.ErrorException(result.RetryReason, ex);
}
catch (FaultException ex)
{
result.Exception = ex;
result.ShouldRetry = true;
result.RetryReason = string.Format("An Exception was raised calling the MyWebService web service: {0}", ex.Message);
_logger.ErrorException(ex.Message, ex);
}
finally
{
MyWebServiceWebServiceHelper.LogOff(ws);
}
}
return MyWebServiceResponce;
}