WebService
AJAX
Børre Stenseth
Moduler>Webservices>Latin

Latinske ordtak

Hva
En enkel webservice

Vi lager en enkel WebService som skal returnere et tilfeldig latinsk ordtak på forespørsel. Dataene transporteres som en tekst streng. Datagrunnlaget er en fil som ser slik ut, de tre første linjene:

	Abusus non tollit usum ; Misbruk utelukker ikke bruk.
	Acta est fabula ; Historien er avsluttet
	Aegroto dum anima est, spes est ; Så lenge det er liv er det håp
	...

En tilfeldig linje skal returneres. ; skiller latinen fra forklaringen.

Vi bygger en ny Web Service i Visual Studio, og får automatisk:

  • Service.asmx
  • En katalog: App_Code med en fil: Service.cs
  • En tom katalog: App_Data. Vi legger våre data: ordtak.txt i denne katalogen.

Fila Service.asmx inneholder kun en linje som kopler oss til kodefila:

<%@ WebService Language="C#" 
               CodeBehind="~/App_Code/Service.cs" Class="Service" %>

Koden ser slik ut, etter at vi har redigert den:

using System;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.IO;
[WebService(Namespace = "http://www.donau.hiof.no/borres/dn/demosite1/s1/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class Service : System.Web.Services.WebService
{
    public Service () {
        //Uncomment the following line if using designed components 
        //InitializeComponent(); 
    }
    [WebMethod(Description="Returnerer en enkel text: Hallo alle sammen")]
    public string HelloWorld() {
        return "Hallo alle sammen";
    }
    [WebMethod(Description=
        "Returnerer et tilfeldig latinsk sitat og en kort forklaring, skilt med ;." +
        "Returnerer ERROR;forklaring dersom data ikke er tilgjengelige")]
    public string Dagens()
    {
        string physicalPath =HttpContext.Current.Server.MapPath(".").ToString();
        String filename = physicalPath + "\\App_Data\\ordtak.txt";
        String txt = LoadText(filename);
        String[] ord = txt.Split('\n');
        Random r = new Random(DateTime.Now.Millisecond);
        int select = r.Next(ord.Length - 1);
        String s = ord[select].Trim();
        return s;
    }

    static String LoadText(String filename)
    {
        String inTxt = "";
        FileStream s = null;
        StreamReader r = null;
        try
        {
            FileInfo source = new FileInfo(filename);
            s=source.OpenRead();
            r = new StreamReader(s);
            inTxt = r.ReadToEnd();
            r.Close();
            return inTxt;
        }
        catch (Exception e)
        {
            return "ERROR;"+e.Message+"\n";
        }
        finally
        {
            if (r != null)
                r.Close();
        }
    }
}
Vi kan nå se hvordan denne tjenesten presenterer seghttp://donau.hiof.no/borres/dn/service1/Service.asmx

Bruk fra et program

progscreen

Vi lager på vanlig måte en Windows Application i Visual Studio. I Solution Explorer, under References, legger vi til en WebReference og oppgir url'en til vår webservice: "http://donau.hiof.no/borres/dn/service1/Service.asmx". Vi kaller den "latin".

Vi kan da skrive følgende kode:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
namespace UseLatin
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            LoadQuote();
        }
        private void button1_Click(object sender, EventArgs e)
        {
            LoadQuote();
        }
        private void LoadQuote()
        {
            latin.Service proxy = new latin.Service();
            String S = proxy.Dagens();
            label1.Text = S.Substring(0, S.IndexOf(';'));
            label2.Text = S.Substring(S.IndexOf(';') + 1);
            if (label1.Text.CompareTo("ERROR") == 0)
                button1.Visible = false;
        }
    }
}

Bruk fra en vevside

webscreen

Framgangsmåten blir den samme som for et program, kople til og navngi webservice. Koden bak vevsiden blir slik:

using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
public partial class _Default : System.Web.UI.Page 
{
    protected void Page_Load(object sender, EventArgs e)
    {
        if (!this.IsPostBack)
            LoadQuote();
    }
    protected void Button1_Click(object sender, EventArgs e)
    {
        LoadQuote();
    }
    
    protected void LoadQuote()
    {
        latin.Service proxy = new latin.Service();
        String S = proxy.Dagens();
        Label1.Text = S.Substring(0, S.IndexOf(';'));
        Label2.Text = S.Substring(S.IndexOf(';') + 1);
        if (Label1.Text.CompareTo("ERROR") == 0)
            Button1.Visible = false;
    }
}
Du kan teste herhttp://donau.hiof.no/borres/dn/demosite2/

Du kan også åpne følgende adresse i nettleseren: http://donau.hiof.no/borres/dn/service1/Service.asmx, og du vil se hvordan tjenesten forklarer seg via en HTML-side. Av dokumentasjonen på denne siden ser du også hvordan vi kan "håndskrive" et program som ekstraherer de interessante dataene fra den XML-fila som returneres fra tjenesten. Dette blir en alternative strategi til å bruke den "proxy"-klassen som Visual Studio bygger.

Bruk via AJAX

Vi lager en konstruksjon der vi lar en aspx-fil hente, formatere og levere det latinske sitatet som et HTML-fragment. Selve siden består av en linje:

<%@ Page Language="C#" AutoEventWireup="true" 
         CodeFile="Default3.aspx.cs" Inherits="Default3" %>

Det er kodefile Default3.aspx.cs som gjør jobben og skriver tilbake bare det fragmentet vi er interessert i i Response-objektet:

webscreenajax
using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
public partial class Default3 : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        latin.Service proxy = new latin.Service();
        String S = proxy.Dagens();
        string q, ex;
        try
        {
            q = S.Split(';')[0];
            ex = S.Split(';')[1];
        }
        catch (Exception exp)
        {
            q = "??";
            ex = "??";
        }
        String T=String.Format(@"
            <p class=""latin"">{0}</p>
            <p class=""explain"">{1}</p>
        ", q,ex);
        Response.Write(T);
        Response.Flush();
    }
}

Når dette er på plass kan vi hente ordtaket fra en vevside via AJAX-mekanismer. I eksempelet du kan kjøre nedenfor er prototype [1] brukt som javascriptbibliotek.

Du kan teste herhttp://donau.hiof.no/borres/dn/demosite2/quotedemo.html

Google Webgadget

Dette er ikke noe hovedtema i dette materialet, men det er ganske nærliggende å se hvordan vi kan bruke denne webservicen i en Google webgadget [2] . Vi gjør dette så enkelt som mulig, og går ikke i detalj i forklaring av hvordan dette virker.

Selve gadgeten er beskrevet med en XML-fil. I sin aller enkleste form kan den se slik ut:

<?xml version="1.0" encoding="UTF-8" ?>
<Module>
  <ModulePrefs title="Latin" height="100" width="320" 
               description="Latinske sitater med norsk forklaring"
               author="B Stenseth" author_email="borre.stenseth@gmail.com"
               thumbnail="http://www.it.hiof.no/~borres/allround/selfimages/bs8.png">
    <Require feature="setprefs"/>
    <Require feature="dynamic-height"/>
    <Require feature="settitle"/>
  </ModulePrefs>
  <Content type="url" href="http://donau.hiof.no/borres/dn/demosite2/gadget.html" />
</Module>

Hvis vi har en Googlekonto, kan vi følge oppskriften på Developers Tools [3] , overlate til Google å lagre denne, vi kan publisere den og vi kan importere den til igoogle.

Url'en som er referet i XML-fila over, http://donau.hiof.no/borres/dn/demosite2/gadget.html, referer til den samme fila som er brukt i AJAX-eksempelet over.

Fler detaljer

Ovenfor har vi arbeidet etter minste motstands vei i Visual Studio. .Net fikser det meste for oss. Vi trenger ikke bekymre oss for verken SOAP eller WSDL. Hvis vi ser nærmere etter så lager Visual Studio følgende filer når vi kopler til en Web Service:

  • Service.wsdl
  • Service.discomap
  • Service.disco

Vi konsentrerer oss om den første av disse. Dette er en komlett beskrivelse av hvordan vi skal kommunisere med vevtjenesten. Den ser slik ut:

<?xml version="1.0" encoding="utf-8"?>
<wsdl:definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" 
                  xmlns:tm="http://microsoft.com/wsdl/mime/textMatching/" 
                  xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" 
                  xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" 
                  xmlns:tns="http://www.donau.hiof.no/borres/dn/demosite1/s1/" 
                  xmlns:s="http://www.w3.org/2001/XMLSchema" 
                  xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" 
                  xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" 
                  targetNamespace="http://www.donau.hiof.no/borres/dn/demosite1/s1/" 
                  xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
  <wsdl:types>
    <s:schema elementFormDefault="qualified" 
              targetNamespace="http://www.donau.hiof.no/borres/dn/demosite1/s1/">
      <s:element name="HelloWorld">
        <s:complexType />
      </s:element>
      <s:element name="HelloWorldResponse">
        <s:complexType>
          <s:sequence>
            <s:element minOccurs="0" maxOccurs="1" 
                       name="HelloWorldResult" type="s:string" />
          </s:sequence>
        </s:complexType>
      </s:element>
      <s:element name="Dagens">
        <s:complexType />
      </s:element>
      <s:element name="DagensResponse">
        <s:complexType>
          <s:sequence>
            <s:element minOccurs="0" maxOccurs="1" 
                       name="DagensResult" type="s:string" />
          </s:sequence>
        </s:complexType>
      </s:element>
    </s:schema>
  </wsdl:types>
  <wsdl:message name="HelloWorldSoapIn">
    <wsdl:part name="parameters" element="tns:HelloWorld" />
  </wsdl:message>
  <wsdl:message name="HelloWorldSoapOut">
    <wsdl:part name="parameters" element="tns:HelloWorldResponse" />
  </wsdl:message>
  <wsdl:message name="DagensSoapIn">
    <wsdl:part name="parameters" element="tns:Dagens" />
  </wsdl:message>
  <wsdl:message name="DagensSoapOut">
    <wsdl:part name="parameters" element="tns:DagensResponse" />
  </wsdl:message>
  <wsdl:portType name="ServiceSoap">
    <wsdl:operation name="HelloWorld">
      <wsdl:documentation xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
        Returnerer en enkel text: Hallo alle sammen
      </wsdl:documentation>
      <wsdl:input message="tns:HelloWorldSoapIn" />
      <wsdl:output message="tns:HelloWorldSoapOut" />
    </wsdl:operation>
    <wsdl:operation name="Dagens">
      <wsdl:documentation xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
        Returnerer et tilfeldig latinsk sitat og en kort forklaring, skilt med ;. 
        Returnerer ERROR;forklaring dersom data ikke er tilgjengelige
      </wsdl:documentation>
      <wsdl:input message="tns:DagensSoapIn" />
      <wsdl:output message="tns:DagensSoapOut" />
    </wsdl:operation>
  </wsdl:portType>
  <wsdl:binding name="ServiceSoap" type="tns:ServiceSoap">
    <soap:binding transport="http://schemas.xmlsoap.org/soap/http" />
    <wsdl:operation name="HelloWorld">
      <soap:operation soapAction=
                      "http://www.donau.hiof.no/borres/dn/demosite1/s1/HelloWorld" 
                      style="document" />
      <wsdl:input>
        <soap:body use="literal" />
      </wsdl:input>
      <wsdl:output>
        <soap:body use="literal" />
      </wsdl:output>
    </wsdl:operation>
    <wsdl:operation name="Dagens">
      <soap:operation soapAction=
                      "http://www.donau.hiof.no/borres/dn/demosite1/s1/Dagens" 
                      style="document" />
      <wsdl:input>
        <soap:body use="literal" />
      </wsdl:input>
      <wsdl:output>
        <soap:body use="literal" />
      </wsdl:output>
    </wsdl:operation>
  </wsdl:binding>
  <wsdl:binding name="ServiceSoap12" type="tns:ServiceSoap">
    <soap12:binding transport="http://schemas.xmlsoap.org/soap/http" />
    <wsdl:operation name="HelloWorld">
      <soap12:operation 
        soapAction="http://www.donau.hiof.no/borres/dn/demosite1/s1/HelloWorld" 
        style="document" />
      <wsdl:input>
        <soap12:body use="literal" />
      </wsdl:input>
      <wsdl:output>
        <soap12:body use="literal" />
      </wsdl:output>
    </wsdl:operation>
    <wsdl:operation name="Dagens">
      <soap12:operation 
        soapAction="http://www.donau.hiof.no/borres/dn/demosite1/s1/Dagens" 
        style="document" />
      <wsdl:input>
        <soap12:body use="literal" />
      </wsdl:input>
      <wsdl:output>
        <soap12:body use="literal" />
      </wsdl:output>
    </wsdl:operation>
  </wsdl:binding>
  <wsdl:service name="Service">
    <wsdl:port name="ServiceSoap" binding="tns:ServiceSoap">
      <soap:address location="http://donau.hiof.no/borres/dn/service1/Service.asmx" />
    </wsdl:port>
    <wsdl:port name="ServiceSoap12" binding="tns:ServiceSoap12">
      <soap12:address location="http://donau.hiof.no/borres/dn/service1/Service.asmx" />
    </wsdl:port>
  </wsdl:service>
</wsdl:definitions>
Referanser
  1. prototype Javascript bibliotekprototypejs.orgwww.prototypejs.org/14-03-2010
  1. Gadget APIGooglecode.google.com/intl/no/apis/gadgets/docs/overview.html22-03-2010
  1. Developers ToolsGooglecode.google.com/intl/no/apis/gadgets/docs/tools.html#GGE22-03-2010
  • Webservice latin (og webservice sonette):
    https://svn.hiof.no/svn/psource/Csharpsites/service1
  • Bruk fra program:
    https://svn.hiof.no/svn/psource/Csharpspikes/useLatin
  • Bruk fra vevside: (inklusive AJAX-løsningen og bruk av sonetter)
    https://svn.hiof.no/svn/psource/Csharpsites/demosite2
Vedlikehold

B.Stenseth, revidert mars 2007

(Velkommen) Moduler>Webservices>Latin (Sonetter)