Today, I had to consume a WCF Service in my SharePoint Feature. I was sure of not using svcutil or Visual Studio 2008's Add Service Reference because that adds extra files that I might need to consider deploying along with my SharePoint solution. So, how do we consume our service ?
Below are the basic steps if you want to create your WCF Client manually via the code:
Put the necessary web.config entries into your SharePoint's application's web.config . A typical example would be:
1: <system.serviceModel>
2: <bindings>
3: <wsHttpBinding>
4: <binding name="insert-your-binding-configuration">
5: <security mode="Message">
6: <transport clientCredentialType="Windows"
7: proxyCredentialType="None" realm="" />
8: <message clientCredentialType="Windows"
9: negotiateServiceCredential="true"
10: algorithmSuite="Default"
11: establishSecurityContext="true" />
12: </security>
13: </binding>
14: </wsHttpBinding>
15: </bindings>
16: <client>
17: <endpoint
18: address="insert-your-address"
19: binding="wsHttpBinding"
20: bindingConfiguration="insert-your-binding-configuration"
21: contract="insert-your-contract-description"
22: name="insert-your-endpoint-name">
23: </endpoint>
24: </client>
25: </system.serviceModel>
Create a Service Client Channel from your ServiceContract
public interface IMyServiceChannel : IMyService, IClientChannel {}
The IMyService is my service contract
Create a Channel Factory and associate with the endpoint configuration name
ChannelFactory<IMyServiceChannel> channelFactory =
new ChannelFactory<IMyServiceChannel>("insert-your-endpoint-name")
With the factory, now we can create our Proxy
IMyServiceChannel proxy = channelFactory.CreateChannel()
You are now ready! Wrap these in a using statement and invoke your service methods using the proxy created above :)
In my last post, we saw how we can handle Errors using FaultContracts and FaultExceptions. WCF framework is always extendable and thus we can extend the behavior of a service too. This leads us to the question – “So, Can I extend the service to accept all the Exceptions and possibly send back some meaningful exceptions based on the Exception to the client?”
Yes, sure we can! We can make use of IErrorHandler to handle Exceptions and create our own custom error messages, and then we can extend the behavior of the service using IServiceBehavior to pump in this custom error handler. Cool, so how it is done?
1) We first create our custom error handler which is derived from IErrorHandler
1: public class ServiceGlobalExceptionHandler
2: : IErrorHandler
3: {
4:
5: /// <summary>
6: /// HandleError. Log an error, then allow the error to be handled as usual.
7: /// </summary>
8: /// <param name="ex"></param>
9: /// <returns></returns>
10: public bool HandleError(Exception ex)
11: {
12: // Log the exception
13: // Return true to indicate the Exception has been handled
14: return true;
15: }
16:
17: /// <summary>
18: /// Provide a fault. The MessageFault fault parameter can be replaced
19: /// or set to null to suppress reporting a fault.
20: /// </summary>
21: /// <param name="error"></param>
22: /// <param name="version"></param>
23: /// <param name="fault"></param>
24: public void ProvideFault(Exception error, MessageVersion version,
25: ref System.ServiceModel.Channels.Message fault)
26: {
27: // You can set the fault to something more meaningful to the client.
28: // Client's can handle this fault without the channel faulting
29:
30: //Decide whether to provide a fault.Shield the unknown exception
31: }
2) Next we create an attribute which will add this custom error handler into the service’s error handlers
(For a clear understanding, I would recommend to download the code sample which is at the end of this post)
1: public class ErrorBehaviorAttribute : Attribute, IServiceBehavior
2: {
3: Type _errorHandlerType;
4:
5: public ErrorBehaviorAttribute(Type errorHandlerType)
6: {
7: this._errorHandlerType = errorHandlerType;
8: }
9:
10: .......
11: .......
12:
13: void IServiceBehavior.ApplyDispatchBehavior
14: (ServiceDescription description,
15: ServiceHostBase serviceHostBase)
16: {
17: IErrorHandler errorHandler;
18:
19: try
20: {
21: errorHandler
22: = (IErrorHandler)Activator
23: .CreateInstance(_errorHandlerType);
24: }
25: catch (MissingMethodException e)
26: {
27: throw new
28: ArgumentException("The errorHandlerType must have a public empty constructor.", e);
29: }
30: catch (InvalidCastException e)
31: {
32: throw new
33: ArgumentException("The errorHandlerType must implement System.ServiceModel.Dispatcher.IErrorHandler.", e);
34: }
35:
36: foreach (ChannelDispatcherBase channelDispatcherBase in serviceHostBase.ChannelDispatchers)
37: {
38: ChannelDispatcher channelDispatcher
39: = channelDispatcherBase as ChannelDispatcher;
40: channelDispatcher
41: .ErrorHandlers
42: .Add(errorHandler);
43: }
44: }
45: }
3) We now inform our service that this is the error behavior you have to look for
1: [ServiceBehavior]
2: [ErrorBehavior(typeof(ServiceGlobalExceptionHandler))]
3: public class MyService : IMyService
4: {
5: .....
6: .....
7: }
Great! Now we have a common place where you can handle the exceptions! :)
So now our WCF project architecture changes a bit to include this global error handler
You can download the code sample below:
Earlier in my post, I discussed how you can structure WCF projects. Few things are still missing in that structure, especially Error Handling. With the current architecture, which is shown below, we can handle Errors and send meaningful information back to the Client. This is done using FaultExceptions.
Using FaultContracts is pretty easy. We specify what FaultContract each OperationContract is associated with. We don’t specify any fault if the OperationContract does not have any FaultContract.
1: [ServiceContract]
2: public interface IMyService
3: {
4: [OperationContract]
5: [FaultContract(typeof(MyServiceFault))]
6: string GetData(Nullable<int> value);
7:
8: [OperationContract]
9: CompositeType GetDataUsingDataContract(CompositeType composite);
10: }
And throw it when we want to:
1: throw new FaultException<MyServiceFault>(
2: new MyServiceFault()
3: {
4: FaultName="ArgumentFault",
5: FaultMessage="Please supply a valid value"
6: });
The Client can catch this FaultException and get the ‘friendly’ exception messages:
1: try
2: {
3: string strValue = proxy.GetData(nValue);
4:
5: Console.WriteLine("You supplied : {0}", nValue.ToString());
6: Console.WriteLine("Service Returned : {0}", strValue);
7: }
8: catch (FaultException<MyServiceFault> serviceFault)
9: {
10: Console.WriteLine("Oops..Some error occured!");
11: Console.WriteLine("Error Name : {0}",
12: serviceFault.Detail.FaultName);
13: Console.WriteLine("Error Message : {0}",
14: serviceFault.Detail.FaultMessage);
15: }
Even though this seems to be a simple and easy method, it is not that efficient. Some of the problems or issues that we can highlight immediately reading the code above are:
1) There is no generic FaultContract, We need to specify a FaultContract for each of the OperationContract
2) As you can notice in the Client, we are explicitly catching the FaultException of our FaultContract type. This again can be different based on the FaultContract on that particular OperationContract
3) There isn’t a way where the errors are logged in the Service. It can be logged before throwing the FaultException, but again you have to do it each time you throw!
4) The Client has to anyhow catch other Exceptions that are not FaultExceptions!
So, do we have a good method where we can handle all the errors and send back meaningful messages back to the Client? Yes, we do!
I would go in detail about that in Part 2 :)
You can download the Part 1 sample below:
WCF projects do not always tend to stay in one project solution. As the business requirement grows, we see that we might need to break up our WCF solution into various bits. Here is a way I handle my WCF projects.
I break up my WCF project into the following bits (each being a class library in Visual Studio):
- DataContracts
- MessageContracts
- FaultContracts
- ServiceContracts
- ServiceImplementation
- ServiceHost
The ServiceHost project can be a self hosted application or a WCF Service Application hosted in IIS. This can change according to your business requirements. This breakup helps me to handle each of the component more efficiently.

There is still one thing that we need to address here – How do we plan to handle Service Errors(and possibly return them back to the Client)? Again, there are many ways to accomplish this, but best is to go with your business needs.I will be writing more about this soon.
I am very much interested to know how you handle your WCF projects and the structure you use for WCF projects. Feel free to share your thoughts
I am currently building a WCF service that has some Sharepoint code in it. The service uses wsHttpBinding. The service is hosted in Windows Server 2003 running IIS 6 with integrated windows authentication mode.
It was really strange to me when the service threw this (really a weird) exception:
The Web application at http://localhost/ could not be found. Verify that you have typed the URL correctly. If the URL should be serving existing content, the system administrator may need to add a new request URL mapping to the intended application
The code which was throwing this exception was none other than:
1: using(
2: SPSite hostSite =
3: new SPSite(request.SiteCollectionUrl))
4: { ... }
Searching the web led me here
The solution was to set the the WCF Service's application pool's Identity to the same account Sharepoint website's application pool uses. Do not try to set the application pool to the same of Sharepoint as it might bring down the Sharepoint website when something goes wrong with the service!

How to verify this?
Good question :)
If you open up your WCF client configuration file, look for the <identity> tag inside the Endpoint configuration
1: <identity>
2: <userPrincipalName
3: value="mossservicedev@BUILD.DEV" />
4: </identity>
You can see that the identity is set to an account in the domain. Verify that with your application pool in IIS

If they both look the same, your Sharepoint code in the web service should work :)