WCF FaultException

时间:2014-02-27 15:08:07

标签: c# .net wcf faultexception

在构建WCF服务时,如果我不包含我在服务中的FaultException合同,我可以在客户端上创建一个包含所有成员的WCF服务引用在Reference.cs文件中。

如果我包含我的FaultException合同,则会发生两件事。

  1. 在WCF测试客户端中,合约名称(CreateFaultMessage)旁边有一个红色的“X”

  2. 当我创建WCF服务引用时,并非所有成员都是     包含在Reference.cs文件中的

  3. 我希望有人能够告诉我在创建FaultException合同时我做错了什么,因为我不是WCF专家。

    下面是我在合同中的代码声明。

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

2 个答案:

答案 0 :(得分: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();
    }
}

查看更多:Fault Contract

答案 1 :(得分: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;
}

我相信这会解决你的问题。 :-)