本帖示范在 WCF 中,如何用 FaultContractAttribute 指定 SOAP 错误,并搭配泛型的 FaultException<自订类> 去封装自订的错误讯息,以回传给客户端。本帖提供 WCF + ASP.NET 3.5 的示例下载。
-------------------------------------------------
本帖的示例代码下载点:
http://files.cnblogs.com/WizardWu/090103.zip
(执行本示例,需要 Visual Studio 2008 + SP1,不需要数据库)
-------------------------------------------------
用 VS 2008 + SP1,双击 WcfServiceLibrary1.sln 打开 solution 后,直接按 F5 执行示例,可看到下图 1 的画面。当您在 TextBox 输入数字并按 Button 时,WCF Service 会用 int.Parse 方法,将输入的字符串转型成数字;当您输入的非数字时,就会在 WCF 中引发转型错误,接着会在 Service1.cs 中抛回一个 FaultException<TDetial>。
图 1
FaultContract attribute 可将一个 operation 宣告成可输出错误,并可指定用哪种 type 来封装 fault 细节信息 (注意,fault 不等于 exception)。本帖下载示例的 IService1.cs 中,我们将接口中的 GetData 方法,用 FaultContract attribute 宣告成遇到 SOAP 错误时,可传回这些错误,如下:
namespace WcfServiceLibrary1
{
[DataContract(Namespace = "http://wizardwu.cnblogs.com/")]
public class FaultInfo
{
[DataMember()]
public string Reason = null; // 自订要传回的错误信息
}
[ServiceContract]
public interface IService1
{
[OperationContract]
[FaultContract(typeof(FaultInfo))]
int GetData(string value);
}
}
上方代码中,我们还看到一个自订类 FaultInfo,是用来提供相关的错误信息,并要在实作 IService1 接口的 Service1 类中,将自订的错误信息封装在泛型 FaultException 类中,亦即 FaultException<FaultInfo>,以便在发生转型错误时,将信息抛出至客户端的 Code-Behind 程序中 (Default.aspx.cs),如下:
namespace WcfServiceLibrary1
{
public class Service1 : IService1
{
public int GetData(string value)
{
int intReturn = 0;
try
{
// 故意用旧式的 int.Parse() 做字符串转型数字,而不用不会引发错误的新式 int.TryParse()
intReturn = int.Parse(value);
}
catch
{
FaultInfo fi = new FaultInfo(); // 自訂 class 的 instance
fi.Reason = "您输入的数字: " + value + "<br>不合理,请重新输入"; // 自订要传回的错误信息
// 要在 WCF 客户端应用程序中,拦截特定合约的 SOAP 失败时,就会使用 FaultException<TDetail> 例外状况
throw new FaultException<FaultInfo>(fi);
// ms-help://MS.MSDNQTR.v90.cht/fxref_system.servicemodel/html/bb03a521-d12b-606f-5f62-dca0c1fe23aa.htm
// FaultException<TDetail> 泛型类
// 客户端应用程序中,用于拦截以合约方式指定的 SOAP 错误。
}
return intReturn; // 经过 WCF 转型后,所抛回的数字
}
}
}
当然,您也可用旧式非泛型的 FaultException 类,或 FaultException<string> 直接指派自订的错误讯息,如下:
throw new FaultException<string>("您输入的数字不合理");
此外,我们自订的 GetData 方法,MEP (Message Exchange Patterns) 不可宣告为 one-way,如下:
[OperationContract(IsOneWay = true)]
[FaultContract(typeof(FaultInfo))]
int GetData(string value);
否则客户端项目在引用这个 WCF Service 会引发「无法更新服务参考」的错误,因此我们用 MEP 的默认值「Request/Response」。
引用这个 WCF Service 的客户端 ASP.NET 项目,其 Default.aspx.cs 代码如下:
using System.ServiceModel;
using WcfServiceLibrary1;
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
protected void Button1_Click(object sender, EventArgs e)
{
this.transferWCF();
}
private void transferWCF()
{
ServiceReference1.Service1Client prox = new ServiceReference1.Service1Client();
int i = 0;
try
{
i = prox.GetData(TextBox1.Text);
Response.Write(i);
}
catch (FaultException<FaultInfo> fault)
{
Response.Write(fault.Detail.Reason);
}
catch (Exception ex)
{
Response.Write(ex.ToString());
}
}
}
上方代码中的 Detail 属性,为 FaultException<TDetail> 泛型类所特有的属性,里然包含错误的详细信息,但旧式非泛型的 FaultException 类没有这个属性。
建置 solution 完成后,若您去浏览 WSDL,会发现里面有 fault contract 的相关信息。
-----------------------------------
参考书籍:
[1] Microsoft .NET Framework 3.5-Windows Communication Foundation, MCTS EXAM 70-503 Training Kit
http://www.microsoft.com/learning/en/us/Books/12486.aspx
http://www.amazon.com/MCTS-Self-Paced-Training-70-503-PRO-Certification/dp/0735625654
-----------------------------------
参考文件:
[2] MSDN Library
FaultContractAttribute 类:
http://msdn.microsoft.com/zh-cn/library/system.servicemodel.faultcontractattribute.aspx
FaultException<TDetail> 泛型类:
http://msdn.microsoft.com/zh-cn/library/ms576199.aspx
FaultException<TDetail>Detail 属性:
http://msdn.microsoft.com/zh-cn/library/ms575596.aspx
[3] WCF学习----我的第一个WCF程序
http://www.cnblogs.com/ASPNET2008/archive/2008/06/01/1211613.html
-----------------------------------