2

一般的な障害例外を作成しFaultException<MyWebServiceFaultDetail> 、MessageFault としてメッセージ インスペクター パイプラインに戻す場合、クライアントはその catch(FaultException<MyWebServiceFaultDetail> ex)ブロックで一般的な障害を受信せず、ブロック内でのみキャッチされcatch (FaultException ex)ます。

MyWebServiceFaultDetailと含意はどちらも、単一のプロジェクト内のIClientMessageInspectorクライアント WCF Web 参照と同じプロジェクト内にありますMyProjects.MyWebService

WebService は、プロジェクトへの参照を持つ別のプロジェクトによって呼び出されますMyProjects.MyWebService

*簡潔にするためにコメントを削除しました

データ コントラクト:

[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 );
    }
}

メッセージ インスペクター。reply.Headers.Actionこのメソッドの実行時にそれが nullであることを追加します。CreateMessage() の呼び出しでアクション値を設定しても影響はありませんでした。私が試した値。

.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;
    }
}

FaultExceptionを受信して​​いるが、を受信して​​いないクライアント コード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;
    }
4

2 に答える 2

0

2 つのフォーマット引数を指定し、1 つだけを指定しているため、ここで問題が発生する可能性があります。

public override string ToString()
{
    return string.Format("Detail[MessageDetail={0}] [MessageType={1}] [TransactionComplete={1}] [TransactionSuccess={1}]", MessageDetail);
}

したがって、実際には、ではなくFormatExceptionによってスローされます。string.FormatFaultException<JoBlogsWebServiceFaultDetail>

于 2012-11-06T14:29:18.667 に答える
0

メッセージインスペクターFaultException<MyWebServiceFaultDetail>から新しいタイプをスローするだけです。AfterReceiveReply

FaultException ex = new FaultException<MyWebServiceFaultDetail>(
                new MyWebServiceFaultDetail
                {
                    TransactionComplete = transactionComplete,
                    TransactionSuccess = transactionSuccess,
                    MessageDetail = messageDetail,
                    MessageType = messageType
                },
                new FaultReason(messageBrief));
throw ex;

DataContract詳細クラスがクライアント側で宣言されている場合は、属性で装飾する必要さえありません。

于 2012-11-09T10:30:10.380 に答える