Silverlight & PHP

Silverlight 2 Beta 2 enables significantly improved interop with SOAP based web-services. Web service proxy class end-point URLs can now be configured without recompiling applications. Visual Studio also now has a new “Silverlight-enabled WCF Service” project item template that you can add to ASP.NET web projects to publish services to clients.

It is uncommon to use Silverlight in conjunction with PHP, but sometimes you may need this. In this post I will show you how easy it can be using Silverlight SOAP based web-services support. Actually it is really very simple. All we need is a PHP web service. Than we just add a Service reference to our Silverlight app, and voila.

There are a few ways to create a PHP SOAP web service. In this example I will use NuSOAP library. The NuSOAP project is hosted by SourceForge. NuSOAP is a group of PHP classes that allow developers to create and consume SOAP web services. It does not require any special PHP extensions. The current release version (0.7.3) of NuSOAP supports SOAP 1.1 specification. It can generate WSDL 1.1 and also consume it for use in serialization. Both rpc/encoded and document/literal services are supported.

Creating the Web Service

Our web service will return a list of employees in XML format. So let’s begin. First, create a file, named EmployeeService.php. This file will hold the web service. We need to create a function, which returns a list of employees.

The result of this function looks like this:

Then we need to create & configure the SOAP server, which will hold the service. Using NuSOAP lib this is very easy.

$ns is the namespace of our service. The register method registers a function to our web service. You can either register an oridinary function or a function inside a class. The first parameter is the name of the function, the second one is an array of the input parameters, the third parameter is an array of the returned values and the last one is the namespace. For each parameter (input or output) you should specify name and type. Finally, you have to call service method, which processes the service. You can read more about NuSOAP here.

Our web service is ready to be consumed. You can view it capabilities here. Now we are going to create the Silverlight client. Let’s name it PHPLight.

Using the Web Service

PHPLight Create New Project

The design is very simple. We have just a ListBox to show the employees. Now we have to add a Web Service reference to our project.

When you do this, Add Service Reference dialog appears. In the address field you type the URL of the web service. Notice, you have to write the path to the WSDL of your service. In our case (and in most of cases) you have to add ?wsdl after the service address. When you press GO button, the wizard gets the content of your service. Let’s change the namespace of our service EmployeeService and press OK.

Visual Studio will create the necessary helper files for you. Now we have to add a few other references to our project. First of them is a reference to Xml Linq. We will use it to manipulate the returned XML data from the service. The second one is a reference to Xml Serialization. When you add a web service reference it creates a file, named Reference.cs. This file uses XmlSerializerFormatAttribute. If you don’t add this reference, you get the following errors:

  • ‘System.ServiceModel.XmlSerializerFormatAttribute’ is inaccessible due to its protection level
  • The type or namespace name ‘XmlSerializerFormatAttributeAttribute’ does not exist in the namespace ‘System.ServiceModel’ (are you missing an assembly reference?)

There is something else that you should do to enable your service working properly. When you add a reference to Xml Serialization, you get another error, which says:

  • ‘System.ServiceModel.XmlSerializerFormatAttribute’ does not contain a definition for ‘Use’

You should open Reference.cs file and change the following line:

to

Now all you have to do is to call the web service. In Loaded event of the UserControl write the following:

As you can see, the calls to the web service are made asynchronously. When you make calls to a component, which won’t return the results immediately, you must put the calls in another thread. In getEmployeesCompleted method we will parse the results and pass it to the ListBox.

We are ready! Here is the result of our work.

[ Online demo ] [ Project Source ]

41 thoughts on “Silverlight & PHP

  1. Check out WebORB: the product supports integration between Silverlight and PHP without all the complexity of SOAP/REST/XML. The deployment model is very simple – deploy your PHP class into a designated directory and use a Silverlight component we offer to invoke remote PHP functions. There’s absolutely nothing special you need to do or learn on the server side, the classes can be plain PHP classes. There’s an overview of an example at:
    http://www.themidnightcoders.com/weborb/php/silverlight_and_php.shtm

    The product is free and open source. WebORB home page is available at:
    http://www.themidnightcoders.com/weborb/php

  2. Great article, really helped out. Have you come across a way to return complex data types ? .net always complains about the SOAP encoding and I havn’t found a work around yet (issue with System.Xml.Serialization.SoapTypeAttribute not being included).

  3. John Phillips: Actually, I haven’t had problems with this. If you use UTF-8 I think there won’t be any problem with the encoding.

  4. I was trying to run through this tutorial and I hit a snag:
    “Contract ‘EmployeesManagerPortType’ is not compatible with Silverlight 2 because it contains one or more operations with SOAP Encoding (use=’encoded’). Only the non-encoded operations will be generated.”

    Then I get an error because getEmployeesCompletedEventArgs doesn’t exist and it’s asking me for a reference.

    Could all this weirdness be due to the fact that I’m trying to use the “Express Edition” of Visual Studio 2008? I don’t know.

    Any ideas would be helpful.

    (Also, I’m using your web service… a little more explanation about how you set that up would be very helpful to me.)

    Thanks.

  5. It seems like Silverlight 2 doesn’t like RPC/encoded style. I changed use=”encoded” to use=”literal” in my web service and now it should work properly.

  6. I saw a php website with a silverlight player integrated

  7. Thomas Domenig

    Very intuitive tutorial! However, I fail in implementing it as I’m missing getEmployeesCompleted() and getEmployeesAsync() from EmployeesManagerPortTypeClient. Should they be generated automatically by Visual Studio or how can I enable them?

    Instead, I tried with client.OpenCompleted += new EventHandler(client_OpenCompleted); client.OpenAsync();

    But this doesn’t have a Result variable. It would be nice to have this very question explained to a Web Service noob like me 😉 …

  8. Hi Thomas! When you add a service reference (Project -> Add Service Reference), you write the URL of the WSDL of the service. Then Visual Studio automatically reads this WSDL and creates the methods for you. So getEmployeesCompleted() and getEmployeesAsync() should be automatically created for you when you add the service reference.

  9. Thomas Domenig

    Hi! I tried it again, but it didn’t change: Including the service is okay and I can generate a service object in C#, but the needed methods are not provided. I used your example and changed it just in the namespace

    $ns = “http://localhost/pro5/test”;

    All nusoap include files are in the same directory as the php file. And the rest is similar just as you have written in your above tutorial. I even see the getEmployees-method, when adding the Web Service to the project in Visual Studio. Do I maybe have to do something special with WSDL (because that’s the technology part I’m not very familiar to)?

  10. Thomas Domenig

    Sorry, I’ve missed something in my last post: After clicking on ServiceReferences.ClientConfig in Visual Studio I get the same warning as Michael Kelsey got (see posting #4). However, I don’t know, what you mean with

    “I changed use=”encoded” to use=”literal” in my web service”

    Where can I do this. I haven’t found such a line – neither in the PHP file nor in Visual Studio. Most probably this is a dummy’s question, but apparently I just can’t figure it out by myself 🙁

  11. Hi Thomas! Try to open the following link: http://localhost/PATH_TO_YOUR_SERVICE/EmployeesWebService.php?wsdl And you can see the methods provided by your service. If you do not see , you probably have error constructing the service.

    I have forgotten to rebuild the source package with the change of the web service. In the php file, you have to change the following line:

    $server->register(‘getEmployees’, array(), array(’employeeList’ => ‘xsd:string’), $ns, false, false, ‘literal’);

  12. Hello can somebody tell me how can i use single element od this structure :
    var employeeList = from emp in doc.Descendants(“Employee”)
    select new Employee
    {
    FirstName = emp.Element(“FirstName”).Value,
    LastName = emp.Element(“LastName”).Value,
    Salary = emp.Element(“Salary”).Value
    };
    For examle i want to show first person’s first name in text block.

  13. @Chris: You can use one of the following methods: Single(), First(), Last(), SingleOrDefault(), FirstOrDefault(), LastOrDefault(). Here is an example:

    var employeeList = from emp in doc.Descendants(”Employee”) ….
    Employee emp = employeeList.First(e => e.Salary < 10.5);

  14. Thank you for your reply but i get an error when I try this for example :
    Employee emp = employeeList.First(e => e.FirstName.Contains(“Peter”));

    Error :
    A local variable named ‘e’ cannot be declared in this scope because it would give a different meaning to ‘e’, which is already used in a ‘parent or current’ scope to denote something else

  15. @Chris: This error usually comes out when you put this line into an event handler where the variable ‘e’ is already used for the corresponding EventArgs. Just use another name for the variable:

    Employee emp = employeeList.First(em => em.FirstName.Contains(”Peter”));

  16. It works great, thank you very much for help. I have another question for you becouse i can’t find it : Do you know how i can change encoding in NuSOAP becouse I am reading data from Mysql database and i get an error when field contains some letters. I would like change it for expamle windows-1250. Thank you for your patience.

  17. @Chris: To specify a different encoding, you set the soap_defencoding property.

  18. When i try :
    $server->soap_defencoding = ‘latin2’;
    or
    $server->soap_defencoding = ‘windows-1250’;
    runs code in:
    catch (Exception)
    {
    this.SetError(“Data parse error”);
    }
    It works olny with :
    $server->soap_defencoding = ‘utf-8’;

  19. Hello Everyone !

    I do the same tutorial but i don’t use Nusoap if you want to see go to :

    http://www.chuubi.com/?p=86 ( it’s in french sorry )

  20. Akim Merabet

    Hi all,

    I have an exception when i launch the application. The same exception when i click on the “Online Demo” link on this page.
    Here the Details of the exception:
    at System.ComponentModel.AsyncCompletedEventArgs.RaiseExceptionIfNecessary()

    Anyone can tell what i have done wrong?

  21. Akim Merabet

    hi again,

    All work fine now.
    I have made a mistake when defining the webservice.

    Thanks to Boyan for this great tutorial.

  22. This is the best description I have found on Silverlight/PHP Integraiton.
    Unfortunately I am having porbelms, even with simple Hello World, in that all I get returned is e.Result being null. Even after I have removed SOAP encoding.

    Anyone get null results ?

  23. Anyway to allow webservice to return a list of data?

    I cant work it with ComplexData with SOAP-ENC:ArrayType as it works only when it is encoded but not literal

    How to consume a webservice which is encoded (the method are not be generated by VS)

    Thanks!

  24. U may delete this comment

    In case if you wan to see my php code, here it is

    function search()
    {
    $r = array(‘PlayerName’ => ‘asd’, ‘Score’ => 23 );
    return array($r,$r);
    }

    $NAMESPACE = “http://issoserious.com/GameClassLib/nusoap”;
    $server = new soap_server;

    $server->debug_flag=false;
    $server->configureWSDL(‘SearchResults’, $NAMESPACE);
    $server->wsdl->schemaTargetNamespace = $NAMESPACE;
    $server->soap_defencoding = ‘utf-8’;

    // ==== WSDL TYPES DECLARATION ==============================================

    // —- Result —————————————————————-
    $server->wsdl->addComplexType(‘Player’,
    ‘complexType’,
    ‘struct’,
    ‘all’,
    ”,
    array(‘PlayerName’ => array(‘name’ => ‘PlayerName’,
    ‘type’ => ‘xsd:string’),
    ‘Score’ => array(‘name’ => ‘Score’,
    ‘type’ => ‘xsd:int’)
    )
    );

    // —- Result[] ————————————————————–

    $server->wsdl->addComplexType(
    ‘Players’,
    ‘complexType’,
    ‘array’,
    ”,
    ‘SOAP-ENC:Array’,
    array(),
    array(
    array(‘ref’=>’SOAP-ENC:arrayType’,’wsdl:arrayType’=>’tns:Player[]’)
    ),
    ‘tns:Player’
    );
    // ==== WSDL METHODS REGISTRATION ===========================================

    $methodName = ‘search’;
    $input = array();
    $output = array(‘return’ => ‘tns:Players’);
    $soapAction = false;
    $style = ‘rpc’;
    $use = ‘literal’;
    $description = ‘A web service to get all customers’;
    $server->register($methodName, $input, $output, $NAMESPACE , $soapAction, $style, $use, $description);

  25. If you find it hard to manage your SOAP web service, do not hesitate and use REST. In REST you can customize the output (normally a XML string) and your application will know how to process everything. Of course you do not have automatically generated methods and classes, but it is not a pain.

  26. Thx boyan, what a fast response 😀

    Time to REST

  27. Hi there:
    I last i managed to ran it.

    you will need the latest nusoap.php (or a modded nusoap).
    http://sourceforge.net/projects/nusoap/ (0.7.3)

    extract nusoap.php and put inside the other php file.

    Uncomment the line 153 (or the line 152?):
    //var $soap_defencoding = ‘UTF-8’;
    –>
    var $soap_defencoding = ‘UTF-8’;

    and edit the line 5355
    $xml = ”;
    –>
    $xml = ‘soap_defencoding .'”?>’;
    And thats it!.
    soap_defencoding do nothing without those changes.

  28. in the line 5355 (or 5354,5352?)
    change :
    ISO-8859-1
    for UTF-8

    Also:
    In the root of the server (ex: http://localhost/)
    add the next file

    clientaccesspolicy.xml

    — cut here–

    — cut here–

  29. Great and very helpfull article. Have one question. What about security. How to set credentials to service and get this credentials on server side script?

  30. Hi,

    Is there anything that I should change in my ServiceReferences.ClientConfig?
    Coz I am having an error:

    ” There was an error reflecting ‘Exception’. ”
    From this code Reference.cs:

    public IntegrationClientChannel(System.ServiceModel.ClientBase client) :
    base(client) {
    }

    Any help is very much appreciated. Tnx in Advance!

  31. By the way, I have my own webservice. Sorry I didn’t use yours. I am using Silverlight 4 Visual Studio 2010

  32. @nitro_67 Normally you can use Apache authentication at server side. You pass the credentials to ClientCredentials property of the service client class.
    @lovenuqui Usually you do not need to change anything there. Check your WSDL file and see what’s generated for your web service.

  33. Hi, great tutorial, very useful. I have a question, how can I use a Datagrid instead of a ListBox?

  34. @Alessadro: The idea is the same as using ListBox. Just bind your DataGrid using its ItemsSource property to the collection.

  35. I have bound the ItemsSource to the collection, but when I open the page, it becomes blank.
    The definition of my Datagrid is:

    Are there any errors?

  36. I see in the past comment there isn’t the definition, you can see here:
    http://pastebin.com/raw.php?i=Ufvk1HV4

  37. What does you data look like? If you use the data as described in my post, you can try adding three columns to your datagrid: FisrtName, LastName and Salary. (or use AutoGenerateColumns). Make sure you receive your data correctly.

  38. Solved using AutoGenerateColumns.

  39. Rohit Raisinghani

    Hi Boyan, I followed the steps that you described to add webservice. Though i cannot find the operations that appear in wsdl in my reference.cs. Are there any restriction on using complex type? When I add the service in a console application or the web project of my silverlight solution everything works fine. All the operations are present in reference.cs. Plz help me out.

  40. Hey.

    i cant consume my webservice if i use SOAP-ENC:Array…

    but i have to get lists of complextypes. could someone help me?

  41. […] paar Interessante Links zu dem Thema: Verfügbar machen eines Diensts über Domänengrenzen hinweg Silverlight & PHP Programming with NuSOAP Tagged PHP, Silverlight Kommentare (RSS) […]