WCF一步一步往前爬(三)

第三步:

在客户端捕获WCF服务异常。

如果是Debug过程,简单的方法就是在宿主项目ProductsServiceHost中的app.config文件中,设置<serviceDebug includeExceptionDetailInFaults="true"/>,或则直接在service

的实现类上添加ServiceBehavior特性,如下

[ServiceBehavior(IncludeExceptionDetailInFaults=true)]
public class ProductsServiceImpl : IProductsService
{
   ......
}

但是对于Release后的部署的系统,为了增加健壮性。建议在Service端抛出SOAP Faults,客户端捕获。拿上一步的ProductsServiceLibrary项目为示例。

public List<string> ListProducts()
        {
            List<string> p;
            try
            {
                 p = ps.Select(item => item.ProductNumber).ToList();

                 int i = 0;
                 int j = 100 / i;
            }
            catch (Exception e)
            {
                // Edit the Initial Catalog in the connection string in app.config
                // to trigger this exception
                if (e.InnerException is System.DivideByZeroException)
                {
                    throw new FaultException(
                    "Exception Divide By Zero: " +
                    e.InnerException.Message, new FaultCode("Divide"));
                }
                else
                {
                    throw new FaultException(
                    "Exception reading product numbers: " +
                    e.Message, new FaultCode("Iterate through products"));
                }
            }

            return p;
        }

客户端:


try
{
    // Obtain a list of all products
    ...
    // Fetch the details for a specific product
    ...
    // Query the stock level of this product
    ...
    // Modify the stock level of this product
    ...
    // Disconnect from the service
    ...
}
catch (FaultException e)
{
    Console.WriteLine("{0}: {1}", e.Code.Name, e.Reason);
}


如何实现强类型的Faults呢?

namespace ProductsService
{
    // Classes for passing fault information back to client applications
    [DataContract]
    public class SystemFault
    {
        [DataMember]
        public string SystemOperation { get; set; }
        [DataMember]
        public string SystemReason { get; set; }
        [DataMember]
        public string SystemMessage { get; set; }
    }
    [DataContract]
    public class DatabaseFault
    {
        [DataMember]
        public string DbOperation { get; set; }
        [DataMember]
        public string DbReason { get; set; }
        [DataMember]
        public string DbMessage { get; set; }
    }
    // Data contract describing the details of a product
    ....
    // Service contract describing the operations provided by the WCF service
    ....
}

namespace ProductsService
{
    // Service contract describing the operations provided by the WCF service
    [ServiceContract]
    public interface IProductsService
    {
        // Get the product number of every product
        [FaultContract(typeof(SystemFault))]
        [FaultContract(typeof(DatabaseFault))]
        [OperationContract]
        List<string> ListProducts();
        // Get the details of a single product
        ....
        // Get the current stock level for a product
        ....
        // Change the stock level for a product
        ....
    }
}


  public List<string> ListProducts()
        {
            try
            {
                ......
            }
            catch (Exception e)
            {
                // Edit the Initial Catalog in the connection string in app.config
                // to trigger this exception
                if (e.InnerException is System.Data.SqlClient.SqlException)
                {
                    DatabaseFault dbf = new DatabaseFault
                    {
                        DbOperation = "Connect to database",
                        DbReason = "Exception accessing database",
                        DbMessage = e.InnerException.Message
                    };
                    throw new FaultException<DatabaseFault>(dbf);
                }
                else
                {
                    SystemFault sf = new SystemFault
                    {
                        SystemOperation = "Iterate through products",
                        SystemReason = "Exception reading product numbers",
                        SystemMessage = e.Message
                    };
                    throw new FaultException<SystemFault>(sf);
                }
            }
        }


客户端--

   static void Main(string[] args)
        {
            ...
            try
            {
                ...
            }
            catch (FaultException<SystemFault> sf)
            {
                Console.WriteLine("SystemFault {0}: {1}\n{2}",
                sf.Detail.SystemOperation, sf.Detail.SystemMessage,
                sf.Detail.SystemReason);
            }
            catch (FaultException<DatabaseFault> dbf)
            {
                Console.WriteLine("DatabaseFault {0}: {1}\n{2}",
                dbf.Detail.DbOperation, dbf.Detail.DbMessage,
                dbf.Detail.DbReason);
            }
            catch (FaultException e)
            {
                Console.WriteLine("{0}: {1}", e.Code.Name, e.Reason);
            }
            ...
        }

宿主应用程序中ServiceHost的状态,如图

在宿主应用程序中处理Faults

 // ServiceHost object for hosting a WCF service
ServiceHost productsServiceHost;
productsServiceHost = new ServiceHost(...);
...
// Subscribe to the Faulted event of the productsServiceHost object
productsServiceHost.Faulted += (eventSender, eventArgs) =>
{
    // FaultHandler method
    // Runs when productsServiceHost enters the Faulted state
    // Examine the properties of the productsServiceHost object
    // and log the reasons for the fault
    ...
    // Abort the service
   productsServiceHost.Abort();
   // Recreate the ServiceHost object
   productsServiceHost = new ServiceHost(...);
   // Start the service
    productsServiceHost.Open();
};
...

在宿主应用程序中处理客户端发送过来未知的message

// ServiceHost object for hosting a WCF service
ServiceHost productsServiceHost;
productsServiceHost = new ServiceHost(...);
...
// Subscribe to the UnknownMessageReceived event of the
// productsServiceHost object
productsServiceHost.UnknownMessageReceived += (eventSender, eventArgs) =>
{
    // UnknownMessageReceived event handler
    // Log the unknown message
    ...
    // Display a message to the administrator
    MessageBox.Show(string.Format(
    "A client attempted to send the message: {0} ",
    eventArgs.Message.Headers.Action));
};
...

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

leesmn

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值