程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> 關於.NET >> WCF示例(4) - 異常處理

WCF示例(4) - 異常處理

編輯:關於.NET

異常處理(Exception、FaultException、FaultException、IErrorHandler)

介紹

WCF(Windows Communication Foundation) - 異常處理:一般Exception的處理,FaultException和FaultException的拋出和處理,使用IErrorHandler處理異常。

示例

1、服務

IHello.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
  
using System.ServiceModel;
  
namespace WCF.ServiceLib.Exception
{
  /**//// <summary>
  /// IHello接口
  /// </summary>
  [ServiceContract]
  public interface IHello
  {
    /**//// <summary>
    /// 拋出Exception異常
    /// </summary>
    [OperationContract]
    void HelloException();
  
    /**//// <summary>
    /// 拋出FaultException異常
    /// </summary>
    [OperationContract]
    void HelloFaultException();
  
    /**//// <summary>
    /// 拋出FaultException<T>異常
    /// </summary>
    [OperationContract]
    [FaultContract(typeof(FaultMessage))]
    void HelloFaultExceptionGeneric();
  
    /**//// <summary>
    /// IErrorHandler處理異常
    /// </summary>
    [OperationContract]
    void HelloIErrorHandler();
  }
}

FaultMessage.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
  
using System.ServiceModel;
using System.Runtime.Serialization;
  
namespace WCF.ServiceLib.Exception
{
  /**//// <summary>
  /// 錯誤信息實體類(用於錯誤契約FaultContract)
  /// </summary>
  [DataContract]
  public class FaultMessage
  {
    /**//// <summary>
    /// 錯誤信息
    /// </summary>
    [DataMember]
    public string Message { get; set; }
  
    /**//// <summary>
    /// 錯誤代碼
    /// </summary>
    [DataMember]
    public int ErrorCode { get; set; }
  }
}

FaultErrorHandler.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
  
using System.ServiceModel.Dispatcher;
using System.Configuration;
using System.ServiceModel;
using System.ServiceModel.Channels;
  
namespace WCF.ServiceLib.Exception
{
  /**//// <summary>
  /// 自定義錯誤處理器(繼承自System.ServiceModel.Dispatcher.IErrorHandler)
  /// </summary>
  public class FaultErrorHandler : IErrorHandler
  {
    /**//// <summary>
    /// 在異常返回給客戶端之後被調用
    /// </summary>
    /// <param name="error">異常</param>
    /// <returns></returns>
    public bool HandleError(System.Exception error)
    {
      System.IO.StreamWriter sw = new System.IO.StreamWriter(@"C:\WCF_Log.txt", true);
      sw.Write("IErrorHandler - HandleError測試。錯誤類型:{0};錯誤信息:{1}", error.GetType().ToString(), error.Message);
      sw.WriteLine();
      sw.Flush();
      sw.Close();
  
      // true - 已處理
      return true;
    }
  
    /**//// <summary>
    /// 在異常發生後,異常信息返回前被調用
    /// </summary>
    /// <param name="error">異常</param>
    /// <param name="version">SOAP版本</param>
    /// <param name="fault">返回給客戶端的錯誤信息</param>
    public void ProvideFault(System.Exception error, System.ServiceModel.Channels.MessageVersion version, ref System.ServiceModel.Channels.Message fault)
    {
      if (error is System.IO.IOException)
      {
        FaultException ex = new FaultException("IErrorHandler - ProvideFault測試");
  
        MessageFault mf = ex.CreateMessageFault();
  
        fault = Message.CreateMessage(version, mf, ex.Action);
  
        // InvalidOperationException error = new InvalidOperationException("An invalid operation has occurred.");
        // MessageFault mfault = MessageFault.CreateFault(new FaultCode("Server", new FaultCode(String.Format("Server.{0}", error.GetType().Name))), new FaultReason(error.Message), error);
        // FaultException fe = FaultException.CreateFault(mfault, typeof(InvalidOperationException));
      }
    }
  }
}

Hello.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
  
using System.ServiceModel;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;
  
namespace WCF.ServiceLib.Exception
{
  /**//// <summary>
  /// Hello類
  /// </summary>
  public class Hello : IHello, IDisposable, IServiceBehavior
  {
    /**//// <summary>
    /// 拋出Exception異常
    /// </summary>
    public void HelloException()
    {
      throw new System.Exception("拋出Exception異常");
    }
  
    /**//// <summary>
    /// 拋出FaultException異常
    /// </summary>
    public void HelloFaultException()
    {
      throw new FaultException("拋出FaultException異常", new FaultCode("服務"));
    }
  
    /**//// <summary>
    /// 拋出FaultException<T>異常
    /// </summary>
    public void HelloFaultExceptionGeneric()
    {
      throw new FaultException<FaultMessage>(new FaultMessage { Message = "拋出FaultException<T>異常", ErrorCode = -1 }, "為了測試FaultException<T>用的");
    }
  
    /**//// <summary>
    /// IErrorHandler處理異常
    /// </summary>
    public void HelloIErrorHandler()
    {
      throw new System.IO.IOException("拋出異常,用IErrorHandler處理");
    }
  
    /**//// <summary>
    /// 實現IDisposable接口的Dispose()方法
    /// </summary>
    public void Dispose()
    {
  
    }
  
    /**//// <summary>
    /// 為契約增加自定義綁定參數
    /// </summary>
    /// <param name="serviceDescription">服務描述</param>
    /// <param name="serviceHostBase">服務宿主</param>
    /// <param name="endpoints">服務端點</param>
    /// <param name="bindingParameters">需要增加的自定義綁定參數</param>
    public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, System.Collections.ObjectModel.Collection<ServiceEndpoint> endpoints, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
    {
  
    }
  
    /**//// <summary>
    /// runtime時修改屬性值或增加自定義擴展對象
    /// </summary>
    /// <param name="serviceDescription">服務描述</param>
    /// <param name="serviceHostBase">服務宿主</param>
    public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
    {
      IErrorHandler handler = new FaultErrorHandler();
  
      foreach (ChannelDispatcher dispatcher in serviceHostBase.ChannelDispatchers)
      {
        // 增加錯誤處理器
        dispatcher.ErrorHandlers.Add(handler);
      }
    }
  
    /**//// <summary>
    /// 檢查服務描述和服務宿主,以確認服務可以成功運行
    /// </summary>
    /// <param name="serviceDescription">服務描述</param>
    /// <param name="serviceHostBase">服務宿主</param>
    public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
    {
  
    }
  }
}

2、宿主

Hello.svc

<%@ ServiceHost Language="C#" Debug="true" Service="WCF.ServiceLib.Exception.Hello" %>

Web.config

<?xml version="1.0"?>
<configuration>
 <system.serviceModel>
  <behaviors>
   <serviceBehaviors>
    <behavior name="ExceptionBehavior">
     <!--httpGetEnabled - 使用get方式提供服務-->
     <serviceMetadata httpGetEnabled="true" />
     <serviceDebug includeExceptionDetailInFaults="true"/>
    </behavior>
   </serviceBehaviors>
  </behaviors>
  <services>
   <!--name - 提供服務的類名-->
   <!--behaviorConfiguration - 指定相關的行為配置-->
   <service name="WCF.ServiceLib.Exception.Hello" behaviorConfiguration="ExceptionBehavior">
    <!--address - 服務地址-->
    <!--binding - 通信方式-->
    <!--contract - 服務契約-->
    <endpoint address="" binding="wsHttpBinding" contract="WCF.ServiceLib.Exception.IHello" />
   </service>
  </services>
 </system.serviceModel>
</configuration>

3、客戶端

Hello.aspx

<%@ Page Language="C#" MasterPageFile="~/Site.master" AutoEventWireup="true" CodeFile="Hello.aspx.cs"
  Inherits="Exception_Hello" Title="異常處理(Exception、FaultException、FaultException&lt;T&gt;、IErrorHandler)" %>
  
<asp:Content ID="Content1" ContentPlaceHolderID="head" runat="Server">
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" runat="Server">
  <div>
    <asp:Label ID="lblMsg" runat="server" />
  </div>
  <br />
  <div>
    <asp:Button ID="btnHelloException" runat="server" Text="HelloException" OnClick="btnHelloException_Click" />
  </div>
  <div>
    <asp:Button ID="btnHelloFaultException" runat="server" Text="HelloFaultException"
      OnClick="btnHelloFaultException_Click" />
  </div>
  <div>
    <asp:Button ID="btnHelloFaultExceptionGeneric" runat="server" Text="HelloFaultExceptionGeneric"
      OnClick="btnHelloFaultExceptionGeneric_Click" />
  </div>
  <div>
    <asp:Button ID="btnHelloIErrorHandler" runat="server" Text="HelloIErrorHandler" OnClick="btnHelloIErrorHandler_Click" />
  </div>
</asp:Content>

Hello.aspx.cs

using System;
using System.Collections;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
  
using System.ServiceModel;
  
public partial class Exception_Hello : System.Web.UI.Page
{
  protected void Page_Load(object sender, EventArgs e)
  {
  
  }
  
  protected void btnHelloException_Click(object sender, EventArgs e)
  {
    ExceptionService.HelloClient proxy = new ExceptionService.HelloClient();
    try
    {
      proxy.HelloException();
    }
    catch (Exception ex)
    {
      lblMsg.Text = ex.Message;
    }
    finally
    {
      try
      {
        proxy.Close();
      }
      catch (Exception ex)
      {
        lblMsg.Text += "<br />" + ex.Message;
      }
    }
  }
  
  protected void btnHelloFaultException_Click(object sender, EventArgs e)
  {
    ExceptionService.HelloClient proxy = new ExceptionService.HelloClient();
    try
    {
      proxy.HelloFaultException();
    }
    catch (FaultException ex)
    {
      lblMsg.Text = string.Format("錯誤編碼:{0};錯誤原因:{1}",
        ex.Code.Name,
        ex.Reason.ToString());
    }
    finally
    {
      proxy.Close();
    }
  }
  
  protected void btnHelloFaultExceptionGeneric_Click(object sender, EventArgs e)
  {
    ExceptionService.HelloClient proxy = new ExceptionService.HelloClient();
    try
    {
      proxy.HelloFaultExceptionGeneric();
    }
    catch (System.ServiceModel.FaultException<ExceptionService.FaultMessage> ex)
    {
      lblMsg.Text = string.Format("錯誤代碼:{0};錯誤信息:{1};錯誤原因:{2}",
        ex.Detail.ErrorCode.ToString(),
        ex.Detail.Message,
        ex.Reason.ToString());
    }
    finally
    {
      proxy.Close();
    }
  }
  
  protected void btnHelloIErrorHandler_Click(object sender, EventArgs e)
  {
    ExceptionService.HelloClient proxy = new ExceptionService.HelloClient();
    try
    {
      proxy.HelloIErrorHandler();
    }
    catch (Exception ex)
    {
      System.ServiceModel.FaultException faultException = ex as System.ServiceModel.FaultException;
  
      if (faultException != null)
      {
        lblMsg.Text = string.Format("錯誤信息:{0}", faultException.Message);
      }
      else
      {
        lblMsg.Text = ex.ToString();
      }
    }
    finally
    {
      proxy.Close();
    }
  }
}

Web.config

<?xml version="1.0"?>
<configuration>
 <system.serviceModel>
  <client>
   <!--address - 服務地址-->
   <!--binding - 通信方式-->
   <!--contract - 服務契約-->
   <endpoint address="http://localhost:3502/ServiceHost/Exception/Hello.svc" binding="wsHttpBinding" contract="ExceptionService.IHello" />
  </client>
 </system.serviceModel>
</configuration>

運行結果:

單擊"btnHelloException"後顯示

拋出Exception異常

The communication object, System.ServiceModel.Channels.ServiceChannel, cannot be used for communication because it is in the Faulted state.

單擊"btnHelloFaultException"後顯示

錯誤編碼:服務;錯誤原因:拋出FaultException異常

單擊"btnHelloFaultExceptionGeneric"後顯示

錯誤代碼:-1;錯誤信息:拋出FaultException異常;錯誤原因:為了測試FaultException用的

單擊"btnHelloIErrorHandler"後顯示

錯誤信息:IErrorHandler - ProvideFault測試

OK

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved