10
votes

I would like to call an external WCF Service from within SharePoint. Using normal WCF calls immediately causes a SocketException (An existing connection was forcibly closed by the remote host), which can be circumvented with SPSecurity.RunWithElevatePrivileges.

[SocketException (0x2746): An existing connection was forcibly closed by the remote host]
System.Net.Sockets.Socket.Receive(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags) +85
System.ServiceModel.Channels.SocketConnection.ReadCore(Byte[] buffer, Int32 offset, Int32 size, TimeSpan timeout, Boolean closing) +204

[CommunicationException: The socket connection was aborted. This could be caused by an error processing your message or a receive timeout being exceeded by the remote host, or an underlying network resource issue. Local socket timeout was '00:00:58.7210000'.]
System.ServiceModel.Channels.SocketConnection.ReadCore(Byte[] buffer, Int32 offset, Int32 size, TimeSpan timeout, Boolean closing) +15307563
System.ServiceModel.Channels.SocketConnection.Read(Byte[] buffer, Int32 offset, Int32 size, TimeSpan timeout) +90
System.ServiceModel.Channels.DelegatingConnection.Read(Byte[] buffer, Int32 offset, Int32 size, TimeSpan timeout) +34
System.ServiceModel.Channels.ConnectionStream.Read(Byte[] buffer, Int32 offset, Int32 count, TimeSpan timeout) +34
System.ServiceModel.Channels.ConnectionStream.Read(Byte[] buffer, Int32 offset, Int32 count) +88
System.Net.FixedSizeReader.ReadPacket(Byte[] buffer, Int32 offset, Int32 count) +58
System.Net.Security.NegotiateStream.StartFrameHeader(Byte[] buffer, Int32 offset, Int32 count, AsyncProtocolRequest asyncRequest) +62
System.Net.Security.NegotiateStream.StartReading(Byte[] buffer, Int32 offset, Int32 count, AsyncProtocolRequest asyncRequest) +54
System.Net.Security.NegotiateStream.ProcessRead(Byte[] buffer, Int32 offset, Int32 count, AsyncProtocolRequest asyncRequest) +402

[IOException: The read operation failed, see inner exception.]
System.Net.Security.NegotiateStream.ProcessRead(Byte[] buffer, Int32 offset, Int32 count, AsyncProtocolRequest asyncRequest) +704
System.Net.Security.NegotiateStream.Read(Byte[] buffer, Int32 offset, Int32 count) +154
System.ServiceModel.Channels.StreamConnection.Read(Byte[] buffer, Int32 offset, Int32 size, TimeSpan timeout) +87

[CommunicationException: The socket connection was aborted. This could be caused by an error processing your message or a receive timeout being exceeded by the remote host, or an underlying network resource issue. Local socket timeout was '00:00:58.7210000'.]
System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg) +10257978
System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type) +539
MyApp.FunctionThatCallsService()

That got me thinking: SharePoint does it, and they do it in a nice way where they have individual service configurations in 14\WebClients.

I reflected and cloned a lot of it (The Extension Methods on the ChannelFactory are used internally all over the place - SPChannelFactoryOperations), but I wonder: Are the "proper" APIs that SharePoint uses to call it's own WCF Services exposed to external code, so that I can call my non-SharePoint WCF Services from custom SharePoint code?

(This is a farm solution deployed to the GAC, so neither CAS nor Sandboxing applies)

2
Is this SharePoint 2007 or 2010?Glenn Ferrie
disregard I saw the tag... better questions to follow.Glenn Ferrie
You can use Business Connectivity Services (BCS) for connecting to your WCF service check this simple article [link] (msdn.microsoft.com/en-us/library/ff953200.aspx)alnaji
What function does your WCF service provide? if it is bringing additional data into SharePoint for consumption, you should consider creating a 'external content type' and BCS (business connectivity services). This is the preferred method for interoperating with external data.Glenn Ferrie
This appears to be a timeout issue that can be mitigated with the correct binding. are you setting the WCF Address and Binding in code or in the web.config?Glenn Ferrie

2 Answers

2
votes

Ended up keeping the SPSecurity.RunWithElevatedPrivileges section. Microsoft's SPChannelFactoryOperations at some point hit a NullReferenceException, most likely due to Claims required to be setup within the service even when not using it (SPServiceAuthenticationMode only has SPServiceAuthenticationMode.Claims as a member. The fact that CreateChannelActingAsLoggedOnUser() immediately throws an ArgumentException is a signal that the SPChannelFactoryOperations aren't meant to be used by non-Microsoft code.

0
votes

I recommend trying to ignore certificates.

http://www.fryan0911.com/2006/07/vbnet-how-to-accept-web-service-ssl.html

Perhaps you need a proxy? Are you having some type of port block problem?