WCF异常处理#2

WCF异常处理#2,wcf,Wcf,我有N个WCF服务方法。我想实现异常处理。我的服务将被.net和非.net客户端使用。故障契约是实现异常处理的唯一方法吗?如果这意味着我如何避免实现我服务中的所有方法。如何在一个地方实现异常处理来处理服务中所有方法的异常。请提供一些代码集,以便在稳定状态下使用 这是我的示例代码 我的合同 我的服务合同 [服务合同] 公共界面设计 { [经营合同] [FaultContract(类型(FleetCustomException))] bool SaveAddress(字符串地址1、字符串地

我有N个WCF服务方法。我想实现异常处理。我的服务将被.net和非.net客户端使用。故障契约是实现异常处理的唯一方法吗?如果这意味着我如何避免实现我服务中的所有方法。如何在一个地方实现异常处理来处理服务中所有方法的异常。请提供一些代码集,以便在稳定状态下使用

这是我的示例代码


我的合同


我的服务合同


[服务合同]
公共界面设计
{  
[经营合同]
[FaultContract(类型(FleetCustomException))]
bool SaveAddress(字符串地址1、字符串地址2、字符串地址3、字符串城市、字符串省、字符串邮政编码、字符串国家、bool isDeleted、int createdBy、DateTime createdDate、int lastModifiedBy、DateTime lastModifiedDate);
[经营合同]
[FaultContract(类型(FleetCustomException))]
bool DeleteAddress(Int64地址ID,intlastModifiedBy);
[经营合同]
[FaultContract(类型(FleetCustomException))]
列出getAllAddresss();
}  
服务


公共类设置服务:IAddress
{  
#地区成员
public bool SaveAddress(字符串地址1、字符串地址2、字符串地址3、字符串城市、字符串省、字符串邮政编码、字符串国家、bool isDeleted、int createdBy、DateTime createdDate、int lastModifiedBy、DateTime lastModifiedDate)
{  
尝试
{  
地址地址=新地址(0,地址1,地址2,地址3,城市,省,邮政编码,国家,删除,创建日期,创建日期,最后修改日期,最后修改日期);
返回地址。Insert();
}  
捕获(FaultException-ex)
{  
FleetCustomException ex=新的FleetCustomException();
例如Title=“Error function:SaveAddress()”;
ex.ExceptionMessage=“执行保存地址功能时出错。”;
ex.InnerException=“来自服务的内部异常消息”;
ex.StackTrace=“来自服务的堆栈跟踪消息。”;
抛出新的FaultException(例如,“原因:测试故障契约”);
}  
}     
公共bool DeleteAddress(Int64地址ID,int lastModifiedBy)
{  
地址=新地址(地址ID,lastModifiedBy);
返回地址。删除();
}  
公共列表GetAllAddresses()
{  
地址=新地址();
返回地址。GetAllAddresses();
}  
#端区
}



消费方式
试试看
{  
MySettingsService.SettingsService代理=新建MySettingsService.SettingsService();
proxy.SaveAddress(Address1TextBox.Text,Address2TextBox.Text,“,”,“,”641025“,”,false,1,DateTime.Now,0,DateTime.Now);
}  
捕获(FaultException-ex)
{  
//处理异常
}  


我必须实现我所有的服务方法我有100多种方法有没有办法快速有效地实现它

FaultContract是处理错误的合适的“SOAP”方法。SOAP标准定义了故障消息元素

WCF中的缺点是,您需要在每个WCF服务操作上指定
[FaultContract]
,因此如果您有很多方法,那么您必须在很多地方定义它。 (实际上有一种方法可以在WCF服务启动时以编程方式添加故障契约,以避免在每个方法上都必须声明它,如果我可以在某处挖掘代码的话…)

此外,如果您希望在某个中心位置处理WCF服务中的错误,则可以实现在发生任何未处理的异常时WCF将调用的


或者,您可以将消息的结构设置为始终可以选择包含错误消息。例如:

[OperationContract]
SaveAddressResult SaveAddress(...);

[DataContract]
public class SaveAddressResult : Result
{
    [DataMember]
    public bool Success { get; set; }
}

[DataContract]
public class Result
{
    [DataMember]
    public string ErrorMessage { get; set; }
}

附加说明:将异常和堆栈跟踪发送回客户端是不好的做法!它可能包含堆栈跟踪信息或其他客户不应该知道的信息。例如,如果您有一个服务方法试图使用SQL查询验证登录,而DB本身导致了异常,那么客户端可能会在查询引发的异常消息中返回您的表名和列名,甚至DB名。您的异常消息应始终经过清理,并精简为客户所需的信息

一个很好的例子是进入数据库的任何字符串输入。做一些类似于:

public Save(string someData)
{
    sqlCommand.Statement = "insert into myTable (myColumn) values (" + someData + ")";
    sqlCommand.Execute();
}

如果插入的列是
VARCHAR(256)
,并且用户现在向您的服务发送一个500个字符的字符串,那么客户端将返回一条错误消息,其中包含类似“value too large for column myTable.myColumn”的内容。这是您的客户永远不应该知道的实现和内部细节。

实现
System.ServiceModel.Dispatcher.IErrorHandler
接口,以集中处理所有错误

我建议您阅读这篇文章:

你想实现什么目标?根本不处理异常有什么不对?嗨,john,如果我只处理异常的话。不在.net framework中的其他程序将无法理解此异常。因此,WCF fault contract将发送基于XML soap的异常。仍然会有一个soap错误,而不是一个详细的错误。在WCF中处理异常的最佳方法是什么。
public class SettingsService : IAddress  
{  

    #region IAddress Members  

    public bool SaveAddress(string address1, string address2, string address3, string city, string province,string postalCode,string country, bool isDeleted,int createdBy, DateTime createdDate, int lastModifiedBy, DateTime lastModifiedDate)  
    {  
        try  
        {  
            Address address = new Address(0, address1, address2, address3, city, province, postalCode, country, isDeleted,createdBy, createdDate, lastModifiedBy, lastModifiedDate);  
            return address.Insert();  

        }  
        catch (FaultException ex)  
        {  

          FleetCustomException ex = new FleetCustomException();  
          ex.Title = "Error Funtion:SaveAddress()";  
      ex.ExceptionMessage = "Error occur while doing save address function.";  
          ex.InnerException = "Inner exception message from serice";  
          ex.StackTrace = "Stack Trace message from service.";  
          throw new FaultException(ex,"Reason: Testing the Fault contract") ;  
        }  
    }     




    public bool DeleteAddress(Int64 addressID, int lastModifiedBy)  
    {  
        Address address = new Address(addressID, lastModifiedBy);  
        return address.Delete();  
    }  

    public List<Address> GetAllAddresses()  
    {  

        Address address = new Address();  
        return address.GetAllAddresses();  
    }  
    #endregion  
<serviceDebug includeExceptionDetailInFaults="true"/>  
   try  
   {  
      MySettingsService.SettingsService  proxy = new MySettingsService.SettingsService();
      proxy .SaveAddress(Address1TextBox.Text, Address2TextBox.Text, "", "", "", "641025", "", false, 1, DateTime.Now, 0, DateTime.Now);  
    }  
    catch (FaultException<MyCalculatorService.CustomException> ex)  
     {  
        //Process the Exception
     }  
[OperationContract]
SaveAddressResult SaveAddress(...);

[DataContract]
public class SaveAddressResult : Result
{
    [DataMember]
    public bool Success { get; set; }
}

[DataContract]
public class Result
{
    [DataMember]
    public string ErrorMessage { get; set; }
}
public Save(string someData)
{
    sqlCommand.Statement = "insert into myTable (myColumn) values (" + someData + ")";
    sqlCommand.Execute();
}