Writing a webpart to work inside and outside Sharepoint when talking to WCF

I have posted in the past on porting our ASP.NET bug tracking systems into Sharepoint and also linking it to TFS. The idea being that the initial customer support contact is tracked in the call tracking system e.g. is it switched on, is there paper in it….., and then escalated to TFS when development effort is required. To do this escalation my webpart calls a WCF service to access the TFS API – why you ask? The TFS API is 32bit only and you cannot call it directly inside a Sharepoint 64bit server farm.

It is good to be able to test this webpart/wcf setup outside of Sharepoint, it is faster and avoids any deployment issues. However, I did hit upon an issue when doing this. When running in Visual Studio it reports a problem that it cannot step into the WCF code; in fact this is a bit of a red herring you cannot even connect in any way.

The fix is simple, you need to set the WSHttoBinding settings, that you use to pass the AD authenticated user, differently in Sharepoint and outside it in Visual Studio running the webpart on Cassini. Basically the default is fine for Cassini (assuming the WCF service web.config is set for WIndows authentication), but you need to set some extra settings if hosted in Sharepoint.

For us I fixed it by using the DEBUG compilation flag, so when running locally it uses the Cassini settings (or lack of them) and when built for deployment (via a WSP) the extra SharePoint settings are used.

var binding = new WSHttpBinding();
#if !DEBUG
     // we were using the following lines but these cause debug to fail
     // but we need them get the AD context for connection to TFS if in Sharepoint
    // As we only deploy a release build this #if is OK
    binding.Security.Mode = SecurityMode.None;
    binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.None;
    binding.Security.Message.EstablishSecurityContext = false;
#endif

var tfsClient = new BlackMarble.Sabs.WebParts.SabsTfsLinkReference.WorkItemLinkClient(binding, new EndpointAddress(tfsLinkURL));