WCF DataContract 与 FaultException 详细信息





4.00/5 (3投票s)
WCF DataContract
引言
这是一个基于 Microsoft Enterprise Library 4.1 和 FaultException
处理的简单 WCF 服务和客户端应用程序。此应用程序基于 Inventory.Core
对象,用于说明如何在 WCF 服务上使用 DataContract
。
我有两个方法,一个方法从 Products
表中返回所有产品作为数组输出,另一个方法在 WCF 客户端发送 Product ID 作为输入参数时返回 Product
的 Name
。
背景
作为原生 ASP.NET 程序员,我们在开发 WCF Web 服务时必须考虑 SOA 方面。最初,我并不关心当 PHP、JSP 和 Perl 等非 Microsoft 技术实现客户端应用程序时,我的 WCF 服务将如何运行。
在设计 WCF 或 Web 服务 SOA 的架构时,一个好的做法是,开发人员必须充分注意到其他编程语言的数据类型及其类型和签名。
当我还是 WCF 服务的新手时,我犯了两个错误。我一直认为我的 WCF 服务只会由基于 ASP.NET 的应用程序使用。
简单来说,就是“广泛认可的数据类型”,这意味着通用数据类型,它为我的 WCF 和未知的客户端实现代码之间的顺畅协作铺平了道路。
第二个是异常处理部分。我将所有 WCF 相关的异常放在我的 WCF 服务应用程序中,例如 CommunicationException
和 TimeoutException
等。即使我在我的消费者应用程序上测试这个 WCF 服务时,尽管它是 WCF 的 ASP.NET 客户端实现,但异常也没有被彻底捕获。
我不知道当基于 JSP 或 PHP 的客户端应用程序在我的 WCF 服务运行时会抛出什么样的异常。
这两个因素在我的开发过程中一直困扰着我。我通过制作其他技术可以理解的自定义错误消息来纠正这些问题。
Using the Code
[FaultContractAttribute(typeof(FaultContractExceptionTest))]
// This will converts the system or application level exception into SOAP header format.
string[] AvailableProducts(); //Instead of returning the CLR data type
//DataSet return the array type
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using System.Data;
using System.Data.Common;
using Microsoft.Practices.EnterpriseLibrary.Data;
using Microsoft.Practices.EnterpriseLibrary.Data.Sql;
using System.Collections;
ArrayList al = new ArrayList();
string s = "";
Database db = DatabaseFactory.CreateDatabase();
DbCommand cmd = db.GetSqlStringCommand("SELECT * from Products");
DataSet ds = db.ExecuteDataSet(cmd);
foreach (DataRow dRow in ds.Tables[0].Rows)
{
al.Add(dRow);
}
foreach (Object row in al)
{
s = s + ((DataRow)row)["ProductName"].ToString() + ",";
}
string rawString = s.TrimEnd(',').ToString();
string[] result = rawString.Split(',');
return result;
在我可用的 Products
实现中,我强制将 DataSet
转换为 ArrayList
类型,然后是 DataRow
和 string
数组。这是因为我的目的是让基于 JSP 和 PHP 的消费者应用程序应该了解将从 WCF 服务接收什么类型的数据。
第二个值得注意的代码片段如下
catch (FaultException<FaultContractExceptionTest> fx)
{
fx.Detail.ErrorMessage = "Internal Server Error " + fx.Reason.ToString();
throw new FaultException<FaultContractExceptionTest>
(new FaultContractExceptionTest(fx.Detail.ErrorMessage));
}
对于 FaultException
类,使用此实现
[DataContractAttribute]
public class FaultContractExceptionTest
{
private string Msg;
public FaultContractExceptionTest(string msg)
{
this.Msg = msg;
}
[DataMember]
public string ErrorMessage
{
get { return this.Msg; }
set { this.Msg = value; }
}
对于 SOAP 标头消息级别的异常处理,我使用了 FaultContractExceptionTest
类作为 DataContract
,正如你可以在我的 WSDL 代码段中看到的那样
<wsdl:operation name="AvailableProducts">
<soap12:operation soapAction=http://tempuri.org/IService/AvailableProducts
style="document" />
- <wsdl:input>
<wsp:PolicyReference URI="#WSHttpBinding_IService_AvailableProducts_Input_policy" />
<soap12:body use="literal" />
</wsdl:input>
- <wsdl:output>
<wsp:PolicyReference URI="#WSHttpBinding_IService_AvailableProducts_output_policy" />
<soap12:body use="literal" />
</wsdl:output>
- <wsdl:fault name="FaultContractExceptionTestFault">
<wsp:PolicyReference
URI="#WSHttpBinding_IService_AvailableProducts_FaultContractExceptionTestFault_Fault" />
<soap12:fault name="FaultContractExceptionTestFault" use="literal" />
</wsdl:fault>
</wsdl:operation>
历史
- 2009 年 6 月 24 日:初始发布