Gunnar Peipman's ASP.NET blog

ASP.NET, C#, SharePoint, SQL Server and general software development topics.

Sponsors

News

 
 
 
 
 
DZone MVB

Links

Social

September 2007 - Posts

Using WCF Services with PHP

I recently wrote two postings on the subject of WCF services: WCF Services – Let's Get Started and WCF and Unit Tests. One could see that creating and testing services was not complicated at all. Let's go on and take some steps nearer to the real world – our service is used by SOAP clients running on different platforms.

I conducted my first experiment with PHP. PHP is widely used in the world of the Web and in all likelihood there will dawn a day when DT is asked just for such an integration. As PHP4 development and support is soon going to be discontinued, I didn't bother with an example using PHP4 SOAP tools. PHP5 is on the market and it comes with a quick and stable SOAP library. The performance is many times better than in case of similar widgets written for PHP4.

I have Apache and PHP5 running on Windows and for SOAP support I have to use an extension named php_soap.dll. Thus, I have to remove the comment mark in front of the appropriate php.ini line and restart Apache.

As an example I will present a PHP code calling the service's Add() method and writing the result on the screen. An example of WCF code can be found in our blog, in the posting WCF Services – Let's Get Started.


<?php
header('Content-Type: text/plain'); echo "WCF Test\r\n\r\n"; $client = new SoapClient('http://gamma/wcftest/MathService.svc?wsdl');
$obj->x = 2.5;
$obj->y = 3.5;
$retval = $client->Add($obj); echo "2.5 + 3.5 = " . $retval->AddResult;
?>

If nothing went wrong, the result should be something like this:

    WCF Test
    2.5 + 3.5 = 6

As you can see, using WCF services in PHP is very simple. The SOAP library provided along with PHP5 does a great deal of the work "behind the curtains", leaving us with an easily readable brief code.


kick it on DotNetKicks.com vote it on WebDevVote.com pimp it Progg it Shout it
Exporting GridView Data to Excel

My current project required a way for exporting data to Excel. I could of course write a separate export method for every data set but in my opinion it would be a pointless waste of time. I would also like to utilise the existing functionality as much as possible – as it is, the lists going to Excel are displayed to the user in the browser.

Solution

The solution – the simplest and least painful at that – is to render GridView into HTML, and to present the resulting HTML to Excel that can also read the HTML format.


/// <summary>
/// Export button was pushed.
/// </summary>
protected void btnExpExcel_Click(object sender,
ImageClickEventArgs e)
{
    // Let's hide all unwanted stuffing
    this.gdvList.AllowPaging = false;
    this.gdvList.AllowSorting = false;
    this.gdvList.EditIndex = -1;     // Let's bind data to GridView
    this.BindList();     // Let's output HTML of GridView
    Response.Clear();
    Response.ContentType = "application/vnd.xls";
    Response.AddHeader("content-disposition",
            "attachment;filename=contacts.xls");     StringWriter swriter = new StringWriter();
    HtmlTextWriter hwriter = new HtmlTextWriter(swriter);     HtmlForm frm = new HtmlForm();
    this.gdvList.Parent.Controls.Add(frm);
    frm.Attributes["runat"] = "server";
    frm.Controls.Add(this.gdvList);
    frm.RenderControl(hwriter);     Response.Write(swriter.ToString());
    Response.End();
}

There is one more thing to be done before we can start the export. The page (not the user control) hosting GridView must not handle event validation. To ensure that, let's add the following definition to the header, into the Page section of the declaration: EnableEventValidation="false"

Extension Possibilities

This functionality can also be extended to other controllers, e.g. DataList, Repeater and other controllers that can be associated with data. One could create a separate class for exporting, and even extend it to other formats besides Excel.

kick it on DotNetKicks.com vote it on WebDevVote.com pimp it Progg it Shout it
WCF and Unit Tests

Good practices demand tests for every new thing you have been able to get running. Otherwise our TDD chief is glum and moody during smoke breaks. So, to maintain the ever cheerful and busy climate in our office, this posting is going to discuss testing.

After installing WCF and getting it to work I also installed everything required for unit tests. It means I installed NUnit and TestDriven.Net and added a tests project to the project mentioned in the previous posting discussing WCF. I created an ordinary DLL library project for the tests, so it could be used with versions of Visual Studio that do not have built-in tests.

To use NUnit with a testing project you have to add a reference to nunit.framework.dll located under Program Files in the NUnit bin directory. This completes all preparations and we can continue with the tests.

New Methods for the Service

To have more things to test I added a couple of new methods to the service. Nothing complicated, just subtraction, multiplication and division, to cover all the four basic operations. Thus, we have to change the service contract and service class. The changes are as follows.


[ServiceContract()]
public interface IMathService
{
    [OperationContract]
    double Add(double x, double y);
    [OperationContract]
    double Subtract(double x, double y);
    [OperationContract]
    double Divide(double x, double y);
    [OperationContract]
    double Multiply(double x, double y);
} public class MathService : IMathService
{
    public double Add(double x, double y)
    {
        return x + y;
    }
    public double Subtract(double x, double y)
    {
        return x - y;
    }
    public double Multiply(double x, double y)
    {
        return x * y;
    }
    public double Divide(double x, double y)
    {
        return x / y;
    }
}

Unit Tests

For testing I created a class named MathServiceTest. We also have to add a Service Reference to the project and provide it with the URL to the MathService service. When the service is in place we can continue with the tests class.

To prevent creating and closing the service connection at every step we will connect to the service at the beginning of testing and disconnect after completing the tests.


using System;
using System.Collections.Generic;
using System.ServiceModel;
using System.Text;
using NUnit.Framework;
using WCFTestTests.gamma; namespace WCFTestTests
{
    [TestFixture]
    public class MathServiceTest
    {
        private MathServiceClient client;
       
        [TestFixtureSetUp]
        public void Initialize()
        {
            this.client = new MathServiceClient();
            this.client.Open();
        }         [TestFixtureTearDown]
        public void TearDown()
        {
            if (this.client.State != CommunicationState.Closed)
                this.client.Close();
        }
    }
}

Next, we will add testing methods for all methods of the service.


using System;
using System.Collections.Generic;
using System.ServiceModel;
using System.Text;
using NUnit.Framework;
using WCFTestTests.gamma; namespace WCFTestTests
{
    [TestFixture]
    public class MathServiceTest
    {
        private MathServiceClient client;
       
        [TestFixtureSetUp]
        public void Initialize()
        {
            this.client = new MathServiceClient();
            this.client.Open();
        }         [TestFixtureTearDown]
        public void TearDown()
        {
            if (this.client.State != CommunicationState.Closed)
                this.client.Close();
        }         [Test]
        public void AddTest()
        {
            Assert.AreEqual(5, client.Add(2, 3));
        }         [Test]
        public void SubtractTest()
        {
            Assert.AreEqual(3, client.Subtract(8, 5));
        }         [Test]
        public void MultiplyTest()
        {
            Assert.AreEqual(12, client.Multiply(2, 6));
        }         [Test]
        public void DivideTest()
        {
            Assert.AreEqual(4, client.Divide(12, 3));
        }
    }
}

Let's start the NUnit GUI and run the test.


Press the right mouse button on the tests project, select Test With from the menu
and then NUnit from the submenu. The NUnit GUI opens.


NUnit GUI displays all classes containing tests, and tests included in the classes.
Tests can be run within a specific class, if required.


It seems I got lucky – all tests have succeeded!

If nothing went wrong all tests are displayed in green. It means we can safely say the service code works correctly. It went well with me this time, I hope you are as lucky or even luckier than I.

Coverage Test

At first, I didn't want to touch the Coverage Test at this time. When I started it, however, I noticed something that should be mentioned here, to widen the reader's horizons.

Let's start the coverage test. It's located in the same menu as the NUnit GUI. TestDriven.Net comes with NCover that enables us to run coverage tests. TestDriven.Net completes the coverage test automatically. You only have to select the appropriate item from the menu, and the results are displayed in a window.


Coverage test failed – code exists that is never run for our project,
unless we change the code.

As we can see the coverage test fails. Methods exist that are never used. These methods have been generated by the service's proxy generator and they are the four overloads of the proxy constructor.

If required, we can remove these constructors from the service's proxy, but refreshing the service causes these constructors to be automatically regenerated. If anybody knows how to prevent it, a comment would be welcome.

Summary

To sum it up, I can say that testing WCF services is not complicated as long as the services are simple. The development environment with all necessary tools can be created quickly and one can begin working almost at once. In addition to Unit Tests testDriven.Net also provides our development environment with Coverage Tests.

As I am dealing with a more complicated SOAP project at the moment, I am quietly contemplating the most effective way of testing the SOAP layer architecture after getting it in place. Anyway, it will certainly give me material for a couple of longer postings.


kick it on DotNetKicks.com vote it on WebDevVote.com pimp it Progg it Shout it
Hello, World!

This is my welcome message to the world from my very own ASP.NET blog. I wrote mainly to my company's blog that is in estonian language. I will publish here best articles I have written about ASP.NET and related technologies. As I'm new to Community Builder it takes a little time to study it, so I try to publish here one post per week. I hope I'm able for more in near future. So, thank you for visiting this blog and have a nice stay!

Sincerely yours,
Gunnar Peipman

Posted: Sep 12 2007, 10:09 PM by DigiMortal | with 1 comment(s)
Filed under:
WCF Services – Let's Get Started

In connection with testing WCF services I had to get the services to work under IIS on my development computer. The default WCF services library created by Visual Studio does not automatically include IIS support. There were other small glitches that I was able to overcome nicely, in spite of everything.

Server

For starters I created a simple service that adds two figures together. What a classic, isn't it? When creating the service, I selected WCF Service Library as the project type. The service file named MathService.cs appears as follows.


using System;
using System.Collections.Generic;
using System.Text;
using System.ServiceModel;
using System.Runtime.Serialization;

namespace WCFTest
{
    [ServiceContract()]
    public interface IMathService
    {
        [OperationContract]
        double Add(double x, double y);
    }

    public class MathService : IMathService
    {
        public double Add(double x, double y)
        {
            return x + y;
        }
    }
}


IIS was the next issue. Mapping the project directory under IIS turned out to be pretty pointless as under IIS all application binaries are searched from the /bin directory but on compilation the files are created in the /bin/Debug directory instead. As workaround I wrote some post-build commands for the WCF service project, copying all necessary files to IIS directories as required. Of course, the IIS directory has to be defined as an IIS application.

Next I dealt with the service configuration.


<?xml version="1.0"?>
<configuration> 

  <system.web>
     <compilation debug="false"/>
     <authentication mode="Windows"/>
   </system.web> <system.serviceModel>
     <services>
       <service name="WCFTest.MathService"
           behaviorConfiguration="MathServiceBehavior">
         <endpoint address=""                   binding="basicHttpBinding"
                  contract="WCFTest.IMathService" />
         <endpoint contract="IMetadataExchange"
                  binding="mexHttpBinding"
                  address="mex" />
       </service>
     </services>     <behaviors>
       <servicebehaviors>
         <behavior name="MathServiceBehavior">           <servicedebug includeExceptionDetailInFaults="False" />           <servicemetadata httpGetEnabled="true" />         </behavior>       </servicebehaviors>     </behaviors>
  </system.serviceModel>
</configuration>

And now the most exciting part – how to make the service visible under IIS. Creating a file with the service's name and svc extension is sufficient. In my case MathService.svc. The content of the file is simple – it is used to set the name of the service class.   

    <%@ServiceHost language=c# Debug="true" Service="WCFTest.MathService" %>

Now the service part should be up. It is quite easy to check – you only need to compile the service and enter its URL in the browser. If anything is wrong, we'll get an error message. If everything is OK, we will see a page introducing the service, with the URL of the service's WSDL in the upper part.

Client

To test the service I created a simple client program that adds two figures together and displays the result.


using System; 

using System.Collections.Generic; using System.Text; using WCFTestConsole.MathService; namespace WCFTestConsole
{
     class Program
     {
         static void Main(string[] args)
         {
             MathServiceClient client = new MathServiceClient();
             Console.WriteLine("2 + 3 = " + client.Add(2, 3));
             Console.WriteLine("Press any key to exit");
             Console.ReadLine();
        }
    }
}

Here I discovered something new and interesting – hooking up the service as a web service behaves differently from adding it as a WCF service. In case of SOAP the wrapper methods created are completely different. They have twice as many arguments as the service method plus two additional arguments for the returned result. Every argument and returned result has an additional Boolean-type parameter indicating whether this parameter has been set or not.

When hooking up the service by adding the service reference to the project, these parameters are not generated because the WCF client is able to solve the situation by itself.

You can read more on this topic from Eugene Osovetsky's blog posting Solving the "disappearing data" issue when using Add Web Reference or Wsdl.exe with WCF services.

Now you have everything you need to get started with WCF and test the results, so I can only wish you success with WCF.


kick it on DotNetKicks.com vote it on WebDevVote.com pimp it Progg it Shout it
More Posts