WCF Tutorial: A Different Approach – Service Library

By | March 24, 2016

Service Library

Now that we have defined our service interface – It’s time to implement it. We implement the service contract interface (IMathService) just like we would any other C# interface and the result is our service library. See below for the service library source code:

using System.ServiceModel;
using MathServiceInterface;
using MathServiceInterface.DTOs;
using MathServiceInterface.Enumerations;
using MathServiceInterface.Faults;

namespace MathServiceLibrary
{
    public class MathService : IMathService
    {
        public double PerformBinaryOperation(BinaryOperation binaryOperation)
        {
            double result = 0;
            switch (binaryOperation.Operation)
            {
                case BinaryOpEnum.Add:
                    result = binaryOperation.Operand1 + binaryOperation.Operand2;
                    break;
                case BinaryOpEnum.Subtract:
                    result = binaryOperation.Operand1 - binaryOperation.Operand2;
                    break;
                case BinaryOpEnum.Multiply:
                    result = binaryOperation.Operand1 * binaryOperation.Operand2;
                    break;
                case BinaryOpEnum.Divide:
                    if (binaryOperation.Operand2 == 0)
                    {
                        throw new FaultException<BinaryOperationFault>(
                            new BinaryOperationFault(binaryOperation.Operation, 
                                "Divide By Zero"));
                    }
                    result = binaryOperation.Operand1 / binaryOperation.Operand2;
                    break;
                default:
                    throw new FaultException<BinaryOperationFault>(
                        new BinaryOperationFault(binaryOperation.Operation, 
                            "Undefined Operation Specified"));
            }

            if (double.IsNaN(result) || double.IsInfinity(result))
            {
                throw new FaultException<BinaryOperationFault>(
                    new BinaryOperationFault(binaryOperation.Operation, 
                        "Arithmetic Overflow"));
            }

            return result;
        }

        public double CalculateSlope(TwoDimensionalPoint point1, TwoDimensionalPoint point2)
        {
            if (point1.Equals(point2))
            {
                throw new FaultException<SlopeCalculationFault>(
                    new SlopeCalculationFault(
                        "Two distinct points must be provided"));
            }
            
            double deltaY = point2.Y - point1.Y;
            double deltaX = point2.X - point1.X;

            if (deltaX == 0)
            {
                throw new FaultException<SlopeCalculationFault>(
                    new SlopeCalculationFault("Undefined Slope"));
            }
                
            double slope = deltaY / deltaX;

            if (double.IsNaN(slope) || double.IsInfinity(slope))
            {
                throw new FaultException<SlopeCalculationFault>(
                        new SlopeCalculationFault(
                            "Slope Calculation Resulted in Arithmetic Overflow"));
            }

            return slope;
        }
    }
}

Throwing a FaultException from the Service Library

The only aspect specific to this implementation being a WCF service class (versus a standard class) is the throwing of a FaultException(TDetail) where TDetail is a serializable error object. This is how we communicate service operation errors to WCF clients. Throwing a FaultException from the service class will generate a SOAP fault to send back to the client. In order for a client to handle a SOAP fault, the serializable error type TDetail must be specified via the FaultContractAttribute applied to the service operation. The FaultContractAttribute must specify each SOAP fault type that could be returned when a service operation encounters a processing error. If a SOAP fault is not specified, then it will be impossible for a client application to handle the fault. The FaultContractAttribute is applied to the method in the service contact interface (IMathService) which was discussed in detail in the previous article of this series.

Throwing a fault using FaultException(TDetail) mimics throwing an exception in any other managed C# application. SOAP-based applications like WCF must communicate errors to a client via translating exceptions to SOAP fault messages. A general principle of service oriented architecture (SOA) is only to share the error information that a client must know and to minimize information disclosure. If a fault message gives up too much information, then this information could possibly be used maliciously. Therefore, SOAP fault information should only contain the minimum amount of information necessary for a client application. Lastly, the error type specified must be serializable by the DataContractSerializer.

Closing Comments

User defined types (classes, enumerations, etc.) used as arguments for or returned from the service operation(s) must be appropriately specified in the shared service contract assembly. Any built-in .NET types (int, string, etc.) which are used in a service operation signature require no such special consideration.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.