Showing posts with label WCF. Show all posts
Showing posts with label WCF. Show all posts

Sunday, December 2, 2012

Method not found exception with WCF

I had a WCF client for a web service, it was working fine from my machine, when I deployed my application to other machines, I was getting the below exception

System.MissingMethodException: Method not found: 'Void System.ServiceModel.Channels.SecurityBindingElement.set_AllowInsecureTransport(Boolean)'.

When I searched online I found out that this could happen when .NET framework is not installed. I tried installing .NET framework 3.5 SP1 on these machines, but it was always failing since this machines OS is windows 7, and I was getting error that I should use “Turn windows features on or off” to install .NET framework 3.5, which was already installed by this way

I searched more, and I found out that there is hot fix for WCF that adds AllowInsecureTransport  property to the SecurityBindingElement class, and i was using this on my WCF client

http://social.msdn.microsoft.com/Forums/en-US/wcfprerelease/thread/c12cf16f-20b9-4204-b05c-342fc33d0727/

I found couple of updates for .NET framework 3.5 SP1, non of them installed successfully, there were errors in setup, either product not found, or things like this

Finally I found one that I was able to install from the link below

http://support.microsoft.com/kb/976462/en-us

I downloaded the x86 file Windows6.1-KB976462-v2-x86.msu from https://connect.microsoft.com/VisualStudio/Downloads/DownloadDetails.aspx?DownloadID=23806 , installed it on the machines, then the application worked without any exceptions

Saturday, November 24, 2012

WCF client to java web service with username token, timestamp and nonce

I was trying to call a java web service that is implementing username token
My first attempt to call the service, I was getting errors about missing username and password
I followed the steps in several articles online to add it like below
client.ClientCredentials.UserName.UserName = "username";
client.ClientCredentials.UserName.Password = "password";
doing so, I was getting another error about missing timestamp
I followed some other steps from another article  here to add it
#region Begin Magic
BindingElementCollection elements = bean.Endpoint.Binding.CreateBindingElements();
elements.Find<SecurityBindingElement>().IncludeTimestamp = true;
bean.Endpoint.Binding = new CustomBinding(elements);
#endregion
Still I was getting errors
Lastly i found very useful information here and here
I downloaded the sample code from MSDN blog, from this link
Then I used 2 projects from this sample code, the Common project, and the UsernameTokenLibrary, called the java service as exactly in the client project
                Binding userNameBinding = BindingHelper.userNameBinding();
                EndpointAddress serviceAddress = new EndpointAddress("http://localhost/servicemodelsamples/service.svc");

                // Create a client with given client endpoint configuration
                channelFactory = new ChannelFactory<IEchoService>(userNameBinding, serviceAddress);

                // configure the username credentials on the channel factory 
                UsernameClientCredentials credentials = new UsernameClientCredentials(new UsernameInfo("User1", "P@ssw0rd"));

                // replace ClientCredentials with UsernameClientCredentials
                channelFactory.Endpoint.Behaviors.Remove(typeof(ClientCredentials));
                channelFactory.Endpoint.Behaviors.Add(credentials);

                client = channelFactory.CreateChannel();


Doing that, I was getting another error this time “PasswordDigest was supplied, but only http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText is supported”

I then modified the code little bit to send password instead of password digest, in the function WriteTokenCore in UsernameSecurityTokenSerializer.cs in UsernameTokenLibrary project

Commented the lines that writes the password digest

writer.WriteStartElement(Constants.UsernameTokenPrefix, Constants.PasswordElementName, Constants.UsernameTokenNamespace);
writer.WriteAttributeString(Constants.TypeAttributeName, Constants.PasswordDigestType);
writer.WriteValue(c.GetPasswordDigestAsBase64());
writer.WriteEndElement();

And added new line to write the password

so the code would look like this

                writer.WriteStartElement(Constants.UsernameTokenPrefix, Constants.UsernameTokenName, Constants.UsernameTokenNamespace);
                writer.WriteAttributeString(Constants.WsUtilityPrefix, Constants.IdAttributeName, Constants.WsUtilityNamespace, token.Id);
                writer.WriteElementString(Constants.UsernameElementName, Constants.UsernameTokenNamespace, c.UsernameInfo.Username);
                writer.WriteElementString(Constants.PasswordElementName, Constants.UsernameTokenNamespace, c.UsernameInfo.Password);
                writer.WriteElementString(Constants.NonceElementName, Constants.UsernameTokenNamespace, c.GetNonceAsBase64());
                writer.WriteElementString(Constants.CreatedElementName, Constants.WsUtilityNamespace, c.GetCreatedAsString());
                writer.WriteEndElement();

After doing the above modifications, I was able to call the java web service successfully complying with username token