4

WCF サービスを構築するときに、サービスに FaultException のコントラクトを含めないと、Reference.cs ファイルに含まれるすべてのメンバーを使用して、クライアントで WCF サービス参照を作成できます。

FaultException コントラクトを含めると、2 つのことが起こります。

  1. WCF テスト クライアントでは、コントラクト名 (CreateFaultMessage) の横に赤い "X" があります。

  2. WCF サービス参照を作成すると、すべてのメンバーがReference.cs ファイルに含まれているわけではありません。

私は WCF の専門家ではないので、FaultException コントラクトを作成する限り、誰かが私が間違っていることを教えてくれることを願っています。

以下は、インターフェイスでの私のコントラクトのコード宣言です。

[OperationContract]
        [FaultContractAttribute(typeof(LogEventArgs), ProtectionLevel = ProtectionLevel.None)]
        Exception CreateFaultMessage(Exception ex, string method);

以下は、インターフェイスを実装するクラスのメソッドです。PostTransmissionRecord メソッドの catch ブロックでの CreateFaultMessage メソッドの呼び出しに注意してください。

public bool PostTransmissionRecord(TransmissionRecord transmissionRecord)
{
    bool blnUpdated = false;

    try
    {
        blnUpdated = TransmissionRecordGateway.InsertData(transmissionRecord);
        LogMessage.WriteEventLog("Transmission records updated successfully", "Ryder.ShopProcessService.SOA", 3, null);

        return blnUpdated;
    }
    catch (Exception ex)
    {
        LogMessage.WriteEventLog("Class: ShopProcessService" + CrLf + "Method: PostTransmissionRecord" + CrLf + "Error: " + ex.Message + CrLf + "InnerException: " + ex.InnerException + CrLf + "Source: " + ex.Source + CrLf + "StackTrace: " + ex.StackTrace, "Ryder.ShopProcessService.SOA", 1, null);
        IssueRemedyTicket("Class: ShopProcessService" + CrLf + "Method: PostTransmissionRecord" + CrLf + "Error: " + ex.Message + CrLf + "InnerException: " + ex.InnerException + CrLf + "Source: " + ex.Source + CrLf + "StackTrace: " + ex.StackTrace);
        CreateFaultMessage(ex, "UpdateSearchInventory");
        return blnUpdated;
    }
}

public Exception CreateFaultMessage(Exception ex, string method)
{
    LogEventArgs detail = new LogEventArgs();

    detail.ApplicationID = "ShopProcessService";
    detail.ExceptionMessage = ex.Message;
    detail.LogEventType = LogEventTypeEnum.Error;
    detail.Method = method;
    detail.Source = ex.Source;
    detail.StackTrace = ex.StackTrace;
    if (ex.InnerException != null)
        detail.InnerExceptionMessage = ex.InnerException.ToString();
    else
        detail.InnerExceptionMessage = null;

    throw new FaultException<LogEventArgs>(detail);
}

更新されたコード

DataContract クラス

namespace Ryder.Enterprise.DataTransferObjects
{
    [Serializable, DataContract(Name = "LogEventArgs", Namespace = "http://www.Ryder.com/SOA/DataContracts/2014/02/17")]
    public class LogEventArgs
    {
        private string applicationID;
        private string method;
        private LogEventTypeEnum logEventType;
        private string exceptionMessage;
        private string innerExceptionMessage;
        private string stackTrace;
        private string source;

        [DataMember(Name = "ApplicationID")]
        public string ApplicationID
        {
            get
            {
                return applicationID;
            }
            set
            {
                applicationID = value;
            }
        }
.
.
.

FAULTEXCEPTION をスローするサービス メソッド

public bool UpdateSpotCheckInventory(SpotCheck transferObject)
        {
            bool blnUpdated = false;

            try
            {
                blnUpdated = SpotCheckCollectionGateway.UpdateData(transferObject);
                LogMessage.WriteEventLog("SpotCheck records updated successfully", "Ryder.ShopProcessService.SOA", 3, null);

                return blnUpdated;
            }
            catch (Exception ex)
            {
                //throw fault exception here on service
                return blnUpdated;
            }
        }

FAULTEXCEPTION をキャッチするクライアント コード

catch (FaultException<LogEventArgs> ex)
            {                   ex.Detail.ApplicationID = "ShopProcessService";
                ex.Detail.LogEventType = LogEventTypeEnum.Error;
                serviceClient.Abort();
            } 
4

2 に答える 2

1

次のように、CustomFault (この例では MathFault) を操作コントラクトではなくデータ コントラクトとして定義してみてください。

[DataContract]
public class MathFault
{    
    //...
}

クライアント側で:

static void Main(string[] args)
{
    ServiceReference1.Service1Client client = new ServiceReference1.Service1Client();
    try
    {
        int value1 = 22;
        int value2 = 0;
        int result = client.Divide(value1, value2);
        Console.WriteLine("Divide({0},{1}) = {2}", value1, value2, result);
        client.Close();
    }
    catch (FaultException<MathFault> e)
    {
        Console.WriteLine("FaultException<MathFault>: Math fault while doing " + e.Detail.Operation + ". Problem: " + e.Detail.ProblemType);
        client.Abort();
        Console.ReadLine();
    }
}

もっと見る:障害契約

于 2014-02-28T07:11:31.857 に答える
1

FaultExceptionサービスから をスローし、クライアント側でキャッチして処理するアプローチを簡素化するには、次のコードに従ってください。

サービス:

public bool UpdateSpotCheckInventory(SpotCheck transferObject)
{
    bool blnUpdated = false;
    try
    {
        blnUpdated = SpotCheckCollectionGateway.UpdateData(transferObject);
        LogMessage.WriteEventLog("SpotCheck records updated successfully", "Ryder.ShopProcessService.SOA", 3, null);
        return blnUpdated;
    }
    catch (Exception ex)
    {
        //throw fault exception here on service
        throw new FaultException("A fatal exception occurred while processing your request", new FaultCode("1000"))
    }
}

クライアント:

catch (FaultException ex)
{
    ex.Detail.ApplicationID = "ShopProcessService";
    ex.Detail.LogEventType = LogEventTypeEnum.Error;
    serviceClient.Abort();

    // You can also access the custom message and error code sent from the service...
    String customErrorCode = ex.Code.Name;
    String customErrorMessage = ex.Reason;
}

私はこれがあなたの問題を解決すると確信しています。:-)

于 2014-02-28T15:06:35.430 に答える