So here is the method that does this job for CRM 2011 on-premise deployment.
private static CustomBinding GetServiceEndpointBinding(string bindingName) { var endpointBinding = new CustomBinding { Name = bindingName }; // Configure security binding var securityElement = SecurityBindingElement.CreateSspiNegotiationBindingElement(true); securityElement.DefaultAlgorithmSuite = SecurityAlgorithmSuite.Default; securityElement.KeyEntropyMode = SecurityKeyEntropyMode.CombinedEntropy; securityElement.MessageSecurityVersion = MessageSecurityVersion.WSSecurity11WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10; securityElement.MessageProtectionOrder = MessageProtectionOrder.SignBeforeEncryptAndEncryptSignature; securityElement.SecurityHeaderLayout = SecurityHeaderLayout.Strict; securityElement.IncludeTimestamp = true; var messageEncoding = new TextMessageEncodingBindingElement(); messageEncoding.ReaderQuotas.MaxStringContentLength = int.MaxValue; messageEncoding.ReaderQuotas.MaxArrayLength = int.MaxValue; messageEncoding.ReaderQuotas.MaxBytesPerRead = int.MaxValue; var transport = new HttpTransportBindingElement { MaxBufferSize = int.MaxValue, MaxReceivedMessageSize = int.MaxValue }; // Add the SymmetricSecurityBindingElement to the BindingElementCollection. endpointBinding.Elements.Add(securityElement); endpointBinding.Elements.Add(messageEncoding); endpointBinding.Elements.Add(transport); return endpointBinding; }
To use the above method, you can wire it up like this.
var endpoint = new EndpointAddress("http://CrmServerName/CrmOrgName/XRMServices/2011/Organization.svc"); var endpointBinding = GetServiceEndpointBinding("CustomBinding_IOrganizationService"); var organizationService = new OrganizationServiceClient(endpointBinding, endpoint); // Provide login credential, you should only need one of the following // If you are using integrated authentication organizationService.ChannelFactory.Credentials.Windows.ClientCredential = CredentialCache.DefaultNetworkCredentials; // if you are using named CRM account // organizationService.ClientCredentials.Windows.ClientCredential = new NetworkCredential("UserName", "Password", "Domain");This is a by-product of my SSIS Integration Toolkit development effort. As you may or may not appreciate, I took me quite some hours to get to the point that the code works for CRM on-premise deployment.
It should be noted that the above snippet works only for CRM on-premise deployment. CRM online or CRM federated deployments have vastly different WCF bindings from on-premise, which require quite some extra effort in order to be able to connect successfully.
Considering the majority of CRM installation is on-premise deployment, I hope this post helps some people in the community who have the same needs.
Thanks for the great post, I tried your code, but keep getting the exception below?
ReplyDeleteSecurity Support Provider Interface (SSPI) authentication failed. The server may not be running in an account with identity 'host/dotcrm'. If the server is running in a service account (Network Service for example), specify the account's ServicePrincipalName as the identity in the EndpointAddress for the server. If the server is running in a user account, specify the account's UserPrincipalName as the identity in the EndpointAddress for the server.
Hi rudgr, I am not sure about the cause of the exception. To verify my code, I have just tried another time, and it has worked for me. By any chance, you have configured IFD on your CRM server? The code snippet won't work for IFD, which I mentioned in the post. Not sure if that's the case.
ReplyDelete@rudgr, I added a bit more code to the second snippet, so that you can specify login credentials for the organization service. Not sure if that's the cause of your problem.
ReplyDeleteHi Daniel,
ReplyDeleteNot sure if my problem is related to binding (although it seems so...)
I have an Umbraco website, stored on Windows Azure, which connects to a CRM 2011 Online, for membership authentication. In the web.config of Umbraco, I just store the url of the CRM organization, username and password (also the device id). Everything seemed to work fine, but after a while, I got errors like:
"MessageSecurityException
Exception message: An unsecured or incorrectly secured fault was received from the other party.
Server stack trace:
at System.ServiceModel.Channels.SecurityChannelFactory`1.SecurityRequestChannel.ProcessReply(Message reply, SecurityProtocolCorrelationState correlationState, TimeSpan timeout)
at System.ServiceModel.Channels.SecurityChannelFactory`1.SecurityRequestChannel.Request(Message message, TimeSpan timeout)
at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)
at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)
If I restart the IIS on Windows Azure (by RDC), everything works ok for a while ...
@Mihai, for CRM Onine, there is a ticket token involved, which expires every few hours.
DeleteBTW, your problem doesn't seem to be related to this post. ;-)
Hi Daniel, thanks for the suggestion, but could you please exemplify ?
ReplyDeleteI'm simply creating a new OrganizationServiceProxy(organizationUri, homeRealm, creds, devCreds) (with parameters read from the web.config), after that, the OrganizationService, OrganizationServiceContext, where should I add this ticket token ?
Thank you.
@Mihai, one simple solution to get around this issue is to not reuse the service proxy object, instead you instantiate a new one every time you make the service call. It adds some small overhead, but it should be OK. The instantiation process should probably include the device credential as well.
DeleteHi Daniel,
DeleteThanks for the suggestion, I will do that.
Hi Daniel,
ReplyDeletei have developed one .net application which i was already hosted on windows azure.this application performs Create,Delete,Read,Update operation with CRM 2011 online.It is working perfect, but from the same application when i tried to connect to CRM 2011 on-premise.It throws an error like "Metadata contains a reference that cannot be resolved: ".please help me
@shag, it is most likely that your CRM application is not accessible from external network. You can try to access your on-premise CRM from public network to see if it is actually accessible.
DeleteHey Daniel,
DeleteI have checked my CRM 2011 on-premise is working properly..even if i will put the CRM crud operation code in web role of azure,it works fine but when i tried the same in worker role.It throws the above error..
@shag, I haven't done the same so I am not sure what the exact problem is. I suspect that there is infrastructure limitation with Azure Worker role, which probably prohibits service calls to external network (from Azure point of view, your on-premise CRM is an external application to them). You can possibly ask in an Azure forum to see if this is a known issue.
DeleteAgain, I don't have an environment to verify this, so the information may not help. I would apologize if that's the case.
I understand well about configuring my endpoint bindings in code and all. I have an issue now, where I referenced a WCF service into my Custom Workflow activity. All is well until I deploy the workflow and try to run in from CRM. I get the following error ----Type 'Microsoft.Crm.Extensibility.InprocessServiceProxy' cannot be serialized. Consider marking it with the DataContractAttribute attribute, and marking all of its members you want serialized with the DataMemberAttribute attribute. If the type is a collection, consider marking it with the CollectionDataContractAttribute. See the Microsoft .NET Framework documentation for other supported types.--- Any ideas?, it seems to not be able to serialize the objects properly. I have looked everywhere on the web but no luck at all.
ReplyDelete