Introduction
This is a simple WCF service and client application based on Microsoft Enterprise Library 4.1. and FaultException
handling. The assumption based on Inventory.Core
object for this application is how to use DataContract
on the WCF service.
I have two methods, one returns all the products from the Products
table as Array output and another one returns Name
of the Product
when WCF client sends the Product ID as input parameter.
Background
As native ASP.NET programmers, we must consider the SOA aspects when developing the WCF Webservice. Initially I did not care about how my WCF service was going to be functioning when non Microsoft technologies such as PHP, JSP and Perl implement the client application.
It's a good practice while designing the architecture of WCF or Webservice SOA that the developer must give considerable notice to other programming's data types and their type and signatures.
I made two mistakes when I was a newbie to WCF service. I always thought that my WCF service is going to be consumed by only an ASP.NET based application.
Simply we put it this way, "widely recognizable data types" that means general data type which paves way to smooth collaboration between my WCF and unknown client implementation code.
The second was the Exception handling part. I put all WCF related exceptions in my WCF service application such as CommunicationException
and TimeoutException
, etc. Even when I tested this WCF service on my consumer application, exceptions were not caught thoroughly despite being an ASP.NET client implementation for the WCF.
I don't know what kind of exception will be thrown when JSP or PHP based client application while my WCF service was on the wire.
These two factors were annoying me a lot in my development time. I rectified these problems by making customized error messages as understandable by other technologies.
Using the Code
[FaultContractAttribute(typeof(FaultContractExceptionTest))]
string[] AvailableProducts();
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;
In my available Products
implementation, I forcibly convert the DataSet
into ArrayList
type, then DataRow
and array of string
. This is because my intention was that JSP and PHP based consumer application should understand what type of data would be received from the WCF Service.
The second notifiable code snippet is as follows:
catch (FaultException<FaultContractExceptionTest> fx)
{
fx.Detail.ErrorMessage = "Internal Server Error " + fx.Reason.ToString();
throw new FaultException<FaultContractExceptionTest>
(new FaultContractExceptionTest(fx.Detail.ErrorMessage));
}
For FaultException
class, use this implementation:
[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; }
}
For SOAP header message level exception handling purpose, I used the FaultContractExceptionTest
class as DataContract
as you can see here in my WSDL snippet:
<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>
History
- 24th June, 2009: Initial post