My blog.

15/04/2008

Connecting to a .NET Web Service from PHP

18:23 pm on 15th April 2008 / 1 comment

I ran into this problem last year while working on a website that required a web service call. I posted my solution in the PHP documentation, but a lot of people are having the same issue and can't resolve it, so I've decided to go over my solution in a bit more detail and how I got to it.

The Problem

The problem occured when I tried to make a web service call like so,

$username = "jbloggs";
$password = "banana7";

try {
	$client = new SoapClient ($wsdl);
	$client -> CheckUser ($username, $password);
	echo "Success!";
}
catch (Exception $e) {
	echo $e -> getMessage ();
}

The following error was given,

Server was unable to process request. --> Object reference not set to an instance of an object.

I was sat at my computer thinking "What the hell?!". All I was doing was passing a username string and a password string into a user authentication call. I couldn't work out why it was giving me errors about objects.

So, I decided to consult the documentation I got given for the web service. And it said right there the call 'CheckUser' required two parameters, 'Username' and 'Password'.

Naturally assuming my code was wrong I tried to fix it. After a few hours of tinkering and doing God knows how many vardumps, I gave up and asked my colleague to check if the web service actually worked by using it on his machine. Now, he was a .NET developer. I noticed something different when he was programming his web service call. He wasn't passing two strings into the call, he was passing an object containing two strings as properties. And low and behold, his call worked fine.

Getting Warmer

So, I went back to my computer and decided to look directly at the WSDL. This was confusing as hell considering it was my first encounter with a WSDL file, but I managed to notice something. The call 'CheckUser' did indeed require an object, called 'UserCredentials'. This object had two properties, 'Username' and 'Password'.

So, I altered my code to pass an object instead of 2 variables. It now looked like this,

class UserCredentials {
	public $Username;
	public $Password;
}

$parameters = new UserCredentials ();
$parameters -> Username = "jbloggs";
$parameters -> Password = "banana7";

try {
	$client = new SoapClient ($wsdl);
	$client -> CheckUser ($parameters);
	echo "Success!";
}
catch (Exception $e) {
	echo $e -> getMessage ();
}

Sadly this yielded an error as well, and I was fast running about of ideas.

The Solution

After more hours of research and frantic Googling, I discovered the optional parameters that can be passed when creating a instance of the SoapClient, specifically the 'classmap' option. Quoted from the PHP documentation,

"The 'classmap' option can be used to map some WSDL types to PHP classes. This option must be an array with WSDL types as keys and names of PHP classes as values."

In English, the 'classmap' option gives you the ability to tell the SoapClient which of your PHP classes relate to the objects specified in the WSDL. So I edited my code again and it now looked like this,

class LocalUserCredentials {
	public $Username;
	public $Password;
}

$parameters = new LocalUserCredentials ();
$parameters -> Username = "jbloggs";
$parameters -> Password = "banana7";

try {
	$client = new SoapClient ($wsdl, array ("classmap" => array ("UserCredentials" => "LocalUserCredentials")));
	$client -> CheckUser ($parameters);
	echo "Success!";
}
catch (Exception $e) {
	echo $e -> getMessage ();
}

And jackpot! My code worked, finally.

It is worth noting at this point that you can call the classes you create anything you want as long as you map them to their related objects in the web service. However, the properties within those classes have to be named exactly the same as the properties within the web service objects.

Comments

Thanks for the post, this will come in quite useful connecting to the web services at work using wordpress now.

Add Comment

You need to login or register to add comments.