Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web / IIS

Common issues in WCF

4.69/5 (29 votes)
24 Apr 2014CDDL7 min read 82K  
Common issues faced while implementing WCF in Project

Introduction

When we (my team) implemented WCF in our project, which was not SOA-based at first, we faced some issues, those tested our patience. We have to dig a lot to for each and every issue we faced. That's why I decided to write this article which will help others who are implementing WCF in their project. This article comprises of solutions for commonly occurring issues while implementing WCF.

Background

This article is not about basic guidelines about how to implement WCF, this article helps to resolve issues faced by team implementing WCF in their project. This article will not teach you basics of WCF, on the contrary it'll assume that you are familiar with WCF basics and ready to take your WCF knowledge to one level higher.

Using the code

I will include code snippets whenever I'll be explaining the solution for the issues. You can make changes accordingly in your WCF application.

1. Readonly Shorthand Property Declaration

Whenever you are using Readonly Shorthand Property Declaration with 'DataMember' attribute, make sure you keep both getter and setter part. Readonly property declaration (without setter, as we normally do) will not work. Data member will not be accessible to the client.

One alternative to this is define set block with empty curly brackets. Please note that user will be able use '=' operator with such property to assign data, but it will not affect the value.

C++
//Data Contract attribute applied to class to make it available to client.
//Data Member attribute applied to the 'MyVar' readonly property.
    [DataContract]
    public class MyValueObject
    {
        [DataMember]
        public int MyVar
        {
            get;
        //This will not work, as WCF needs both getter and setter to access property.
        }
    }  

    //Correct version with both getters and setter defined.
    [DataContract]
    public class MyValueObject
    {
        [DataMember]
        public int MyVar
        {
            get; 
            set {}
            //Empty setter block is supplied for readonly property. 
        }
    }

2. Value Object which does not return by any Service Contract

Generally we defined all the value objects used by project under one namespaces. This namespace is accessible to client via service reference. Please note that we can't add reference of this namespace directly to the client as it will generate conflict (and each time we have to use full fledged name of the it, which is not very convenient), as same value objects will be available via service reference as well.

But there is one catch, client only gets those value objects via service reference which are returned by at least one operation contract. So, what if client wants to use any particular value object which no service contract returns. Add such value objects as known type on any service contract, preferably first service contract (there can be multiple service contracts in one project).

C++
//Value object does not return by any operation contract
[DataContract]
public class MyNonReturnVO
{
    [DataMember]
    public int MyVar
    {
        get;
        set;
    }
}

//Value object return by an operation contract
[DataContract]
public class MyReturnVO
{
    [DataMember]
    public int MyProp
    {
        get;
        set;
    }
} 


//Adding MyNonReturnVO as KnownType to make it avaialble to the client
[ServiceContract] 
[KnownType(TypeOf(MyNonReturnVO))]
interface IMyInterface
{     
    [OperaionContract]     
    MyReturnVO getMyVO(); 
}

In above example two value object have been defined namely, MyReturnVO, which is return by an OperationContract getMyVO(), and MyNonReturnVO, which is not return by any OperationContract, so we added it to the KnowType attribute. Now MyNonReturnVO is also accessible to the client.

3. Out Parameters in WCF Service

If there is only one out parameter in any operation contract method with void as return type, contract will convert that parameter into return type for that contract.

If operation contract method has some other return type than void then out parameter must be the first parameter in the method signature.

C++
//Original method with void return type and single out parameter
[OperationContract]
void MyMethod(int myId, out string myName);

//This method will end up in service reference as
string MyMethod(int myId);


//Method with other return type than void and out parameter
[OperationContract]
string MyMethod(out string myFirstName, int myId);
//Out must be first parameter

WCF operation contract method cannot have more than one out parameter. And parameter must be the first parameter in method signature.

4. Method Overloading in WCF

WCF recognizes each method with operation contract uniquely by its name. In case of method overloading we provide same name to methods. So how to use overloaded methods as client?

Solution to this issues is very simple, using alias. We can provide alias to methods while defining operation contract, and method will be available to the client by its alias, and not by original name. Of course alias for each overloaded method should be different. Yeah, even I can see that we lost our very own overloading feature here!!!

C++
[ServiceContract]
interface IMyCalculator
{
    //Providing alias AddInt, to avoid naming conflict at Service Reference
    [OperationContract(Name = "AddInt")]
    public int Add(int numOne, int numTwo);

    //Providing alias AddDobule, to avoid naming conflict at Service Reference
    [OperationContract(Name = "AddDouble")]
    public double Add(int numOne, double numTwo); 
}

In above example, these methods can be accessed at client site by using their alias; which are AddInt and AddDouble.

5. Exposing enums to client

This can be done in more than one ways:

  1. Apply [DataContract] and [EnumMember] attributes as you apply on value object classes and then add this enum on class as knowntypes.
    [DataContract]
    public class MyClass
    {
        [DataMember]
        public string
        {
            get;
            set;   
        }
    
        //Enum as datamember
        [DataMember]
        public MyEnum condition;
    
    } 
     
    
    //Applying DataContract attribute to enum itself
    [DataContract]
    public enum MyEnum
    {
        //Applying EnumMember attribute to each enum attribute
        [EnumMember]
        First,
        [EnumMember]
        Second,
        [EnumMember]
        Third
    }

    In above example DataContract and EnumMember attributes have been applied to the enum MyEnum. Now it is accessible to client.

  2. Secondly we can also apply [Flags] attribute along with [DataContract], this will allow you to send and receive enum values.
    [DataContract]
    public class Car
    {
        [DataMember]
        public string
        {
        get;
            set;   
        }
        [DataMember]
        public MyEnum condition;
    
    } 
     
    //Applying Flags attribute to enum
    [DataContract]
    [Flags]
    public enum MyEnum
    {
        [EnumMember]
        First,
        [EnumMember]
        Second,
        [EnumMember]
        Third
     }

    In above example I have applied Flags attribute along with the DataContract over enum prototype, this enables a list of zero or more enumeration values can be sent or received simultaneously.

6. Converting Collection into Arrays or Lists

This is comparatively trivial issue, but sometimes can come into the picture. The issue is, whatever collections: Lists, ArrayLists, etc, comes from service should be represented as Array or List at client. This options come right at the time of creating Service Reference. While creating Service Reference you can select the option from available dropdown choices

7. Handling Exceptions

Exceptions cannot pass from service to the client as it is, because exceptions are .NET specific and one of the main design principle of WCF is interoperability. So, WCF provides another mechanisms to passed runtime exceptions over service, that is, FaultContracts.

Before getting to FaultException let me explain forehand settings needed for exception details to be included in Faults:

C++
<behaviors>
    <serviceBehaviors>
    <behavior>
        <serviceDebug includeExceptionDetailInFaults="true">
    </behavior>
    </serviceBehaviors>
</behaviors>

Add this settings in your service behaviors to get the exact details of exceptions at client site.

Now let's get back to FaultContracts:

First of all you need to define one class which will hold all the exception details for you.

C++
[DataContract]
public class FaultHandle
{
   FaultHandle(int id, int enumType)
   {
        faultId = id;
        faultType = (FaultType) enumType 
   } 
   
   [DataMember] 
   public int faultId; 

   [DataMember]
   public FaultType faultType;
} 

[DataContract] 
public enum FaultType
{ 
    [EnumMember] 
    NullReferenceExcpetion, 

    [EnumMember]
    ArithmaticException, 

    [EnumMember] 
    SQLException
}

The Enum defined in above example contains generally occurring exceptions, you can define as many as you want according to your requirement. The FaultHandle class contains Id and enum variable to pass the details of exceptions.

Now let's consider particular method which throws one of these exceptions

C++
[ServiceContract]
interface IMyService
{
    [OperationContract]
    [FaultContract(typeOf(FaultHandle))]
    public string canOccurException();
} 



public class MyService: IMyService
{
    
   public void myMethod()
   {   
       int num = 10;
       try
       {
           num/0;
       }
       catch(ArithmaticException)
       {  
          throw new FaultException<FaultHandle>(new FaultHandle(1, 2));
       }  
   }
}

Thus above method throws fault exception. This exception can be caught at client site and based on its enum type we can decide the required action.

8. When to update Service Reference

Updating Service Reference is tedious task. So we want to avoid it as many times as possible. So, we should know when it is mandatory to update service reference. We need to update service reference only in one of the following cases:

  1. If DataContract has been changed: We have added any extra DataMember or removed any so that it is no more available to client.
  2. If ServiceContract has been changed: Operation Contract has been added to new method or any method signature has been changed, or any method has been removed from Service Contract.

If we have just changed body of any operation method, we need not to update service reference. Just building changed class and publishing (assuming you are using IIS hosting) it will help. Then build the class which contains service reference and changes made by you will reflect without updating Service Reference.

9. Update Service Reference

Updating Service Reference is very tedious task. So, if all team members are accessing service hosted at server for development, not all need to update service reference individually. One team member can update the service reference and check-in (we used TFS for check-ins) the same. Rest of the members can download that reference and continue working.

10. Debug Service hosted on Same machine using IIS

While implementing new functionality developer needs to debug the code usually. So in development environment if service is hosted on same machine using IIS, developer can debug the application with attaching w3wp process to the application. If this process is not visible at first, check the option for displaying processes from all users.

* Basic Points(Principles) for Services

This point I'll add in this article as bonus for you. Please keep this basic points in mind while designing and coding WCF service:

  1. Combine all service calls into one per operation, or try to reduce it as less as possible.
  2. Reduce the size of data to be transfer across the service boundaries.
  3. Reduce the number of parameters in methods to 4 or less.
  4. Avoid using "out" parameters.
  5. Implement service using facade layer, implement all service contract interface in one class and create service reference using this class.
  6. Don't call service with faulty data, do basic data validation at client site itself.

License

This article, along with any associated source code and files, is licensed under The Common Development and Distribution License (CDDL)