tirsdag den 8. september 2009

C# Webservice og curl

For nyligt blev jeg bedt om at hjælpe på et projekt, hvor man havde brug for at udvide nogle webservices, som var skrevet i C#. Ja, det er ikke just min boldgade, men hvor svært kan det være? Og det er faktisk gået over al forventning.

At kalde det for webservices er måske lidt en tilsnigelse, for der er i vid udstrækning tale om et remote procedure call, også selvom det er pakket fint ind - der bruges godt nok plusord som "SOAP", "WSDL" og "Document Literal" (i en helt egenartig variation - bravo Microsoft!), men reelt skriver man en metode, og så bruger man værktøjer til at generere "det ind imellem".

Kigger man på den WSDL, som kommer ud af det, så bliver man ikke imponeret. At man har felter med en datatype, som kan være Null, betyder ikke at feltet skal være optionelt - jeg kiggede bl.a. på en webservice til at sende SMS'er, og der måtte man ifølge service definitionen selv om, om man ville angive telefonnummer og besked!

Kan man sluge den kamel (og det er noget af kamel at sluge for en person som jeg, der er til stærkt typede sprog), så må man sige, at det er ganske nemt. Og muligheden for at kalde den autogenerede metode via POST af en tilsvarende autogenereret formular, er tilnærmelsesvist genialt. Hvor er det dog nemt at få en hurtig test af det, som man lige har flikket sammen.

Men så var det, at jeg pludselig rendte ind i flg. besked på testsiden:
The test form is only available for methods with primitive types or arrays of primitive types as parameters.
...mand, og nu gik det ellers lige så godt med mine små "Hello, world!" eksperimenter.

Den sad jeg så lidt og grublede over. Det kunne da ikke være sandt, at man ikke kunne teste sådan en webservice på andre måder end ved at lave en hel ny klient til den?

Så var det, at jeg faldt over cURL. Hmm. Sammen med afvisningen på testsiden var der jo et eksempeldokument - mon ikke det kunne lade sig gøre, at kalde webservicen direkte via cURL?

Dokumentet kunne f.eks. være dette:
   1:<?xml version="1.0" encoding="utf-8"?>
2:<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
3: <soap:Body>
4: <TestData xmlns="http://test.example.org/ws">
5: <Id>Alfa</Id>
6: <list>
7: <item>
8: <field>NAME</field>
9: <oldValue>gammelt navn</oldValue>
10: <newValue>nyt navn</newValue>
11: </item>
12: <item>
13: <field>CITY</field>
14: <oldValue>Gammelby</oldValue>
15: <newValue>Nyborg</newValue>
16: </item>
17: </list>
18: </TestData>
19: </soap:Body>
20:</soap:Envelope>

Og cURL kan kaldes på flg. måde:
   1:#!/bin/bash
2:curl -H "SOAPAction: \"http://test.example.org/ws/TestData\"" \
3: -H "Content-Type: text/xml;charset=utf-8" \
4: -d @testdata.xml \
5: http://localhost/TestWebService/TestWebService.asmx?op=TestData

De to "-H" sætter headers på, og "-d" refererer til filen med ovenstående xml-dokument (som er body i beskeden). Sværere er det såmænd ikke.

Yeah!

2 kommentarer:

Mikis Seth Sorensen sagde ...

Hrrmmm, når du vælger at bruger curl til dine integrationstest antager jeg at det er fordi testene i vid udstrækning er manuelle. I tilfælde at at man skulle lave en rigtig automatisk test antager jeg at man ville vælge en anden teknologi at basere sin integrationstests på.

Unknown sagde ...

Fuldkommen korrekt. Man skal nemlig se det som et alternativ til den web-formular, som man ellers ville kunne bruge - og det er jo en "hul-igennem"-test man laver via den.

Man er mao. i første omgang ikke så vanvittigt interesseret i, om det er korrekt, men mere i at der ikke er nogle "stik" som ikke er sat rigtigt i.

Nu har du nok også læst min næste blog-post, og det som skete der var, at jeg blev ganske forbløffet over at få den slags fejl, for jeg mente jo nok at have fuld verifikation for alle komponenternes korrekthed - og alligevel sker der tilsyneladende pludselig underlige ting "undervejs", når man sætter det sammen. Det viste sig så heldigvis, at det var test-setuppet, som har fejlramt.

Når jeg åbent har indrømmet at min test var manuel, så ser jeg absolut intet til hindrer for, at teknikken kunne indgå i et automatiseret setup. Der er fuld kontrol over alt input, og det er en fornøjelse bare at kunne "trykke på knappen", når det skal køres igen. Budskabet er måske også i nogen grad, at man ikke nødvendigvis behøver at have fuldstændige klienter op og køre, for at teste servere (det giver bare en yderligere fejlkilde) - det er faktisk ret nemt at kalde webservices med "forkogte" requests - og ganske givet også nemt, at verificere resultatet på dokumentniveau.