-8-

 

Web Services

 

The .Net framework recognizes and acknowledges files with an extension of asmx as a Web Service. Therefore, in order to cater to the prerequisites of .Net framework, we design a file called a.asmx, with a class named zzz.

 

a.asmx

public class zzz

{

public int abc(int i)

{

return i*2;

}

}

 

Output

Parser Error Message: The page must have a <%@ webservice class="MyNamespace.MyClass" ... %> directive

 

The class zzz has a function called abc, that accepts an int as a parameter and returns a value, after multiplying the parameter by 2. No class can be more uncomplicated and clear-cut than the one we have written. Yet, we get an error when the file is loaded as  http://localhost/a.asmx in the browser. This is because, a Web service is a special file, and the framework is required to handle this exceptional file, a little differently. So, we need to supplement this file by making some more additions, as shown below.

 

a.asmx

<%@ WebService Language="C#" Class="zzz" %>

public class zzz

{

public int abc(int i)

{

return i*2;

}

}

 

In the previous program, since the directive named WebService was missing, an error was reported. The directive WebService is followed by the name of the language which has been initialized to C#, because we will be writing the Web Service, using the C# programming language. An asmx file may contain a numerous classes, but only one of them represents the Web Service. Thus, the class property is made equal to zzz. We spot the following output in the browser:

 

Output

zzz WebService

 

zzz

The following operations are supported. For a formal definition, please review the Service Description.

 

----------------------------------------------------------------------------

This web service is using http://tempuri.org/ as its default namespace.

Recommendation: Change the default namespace before the web service is made public.

Each web service needs a unique namespace to identify it so that client applications can distinguish it from other ..............

......................

For more details on XML namespaces, see the W3C recommendation on Namespaces in XML.

For more details on WSDL, see the WSDL Specification.

For more details on URIs, see RFC 2396.

 

The class zzz is now acknowledged as a Web Service. For the moment, there are no web methods exposed by our class.  A Web Service permits others to execute code in our class. We want the function abc to be called with a number, so that it can majestically return the numbers twice over, than it had been served with.

 

No web methods are shown, since at this point in time, the function abc is inaccessible.

 

a.asmx

<%@ WebService Language="C#" Class="zzz" %>

using System.Web.Services;

public class zzz

{

[WebMethod]

public int abc(int i)

{

return i*2; } }

 

Output

zzz

 

The following operations are supported. For a formal definition, please review the Service Description.

 

abc

 

Click on abc and the screen changes to accept values in a text box

  

 Click here for a complete list of operations.

 

abc

 

Test

To test, click the 'Invoke' button.

 

Parameter Value

i:   

 

SOAP

 

The following is a sample SOAP request and response. The placeholders shown need to be replaced with actual values.

 

POST /a.asmx HTTP/1.1

Host: localhost

Content-Type: text/xml; charset=utf-8

Content-Length: length

SOAPAction: "http://tempuri.org/abc"

 

<?xml version="1.0" encoding="utf-8"?>

<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/">

  <soap:Body>

    <abc xmlns="http://tempuri.org/">

      <i>int</i>

    </abc>

  </soap:Body>

</soap:Envelope>

HTTP/1.1 200 OK

Content-Type: text/xml; charset=utf-8

Content-Length: length

 

<?xml version="1.0" encoding="utf-8"?>

<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/">

  <soap:Body>

    <abcResponse xmlns="http://tempuri.org/">

      <abcResult>int</abcResult>

    </abcResponse>

  </soap:Body>

</soap:Envelope>

 

HTTP GET

The following is a sample HTTP GET request and response. The placeholders shown need to be replaced with actual values.

 

GET /a.asmx/abc?i=string HTTP/1.1

Host: localhost

 

HTTP/1.1 200 OK

Content-Type: text/xml; charset=utf-8

Content-Length: length

 

<?xml version="1.0" encoding="utf-8"?>

<int xmlns="http://tempuri.org/">int</int>

 

HTTP POST

The following is a sample HTTP POST request and response. The placeholders shown need to be replaced with actual values.

 

POST /a.asmx/abc HTTP/1.1

Host: localhost

Content-Type: application/x-www-form-urlencoded

Content-Length: length

 

i=string

HTTP/1.1 200 OK

Content-Type: text/xml; charset=utf-8

Content-Length: length

 

<?xml version="1.0" encoding="utf-8"?>

<int xmlns="http://tempuri.org/">int</int>

 

To convert a function into a web method, we have to add an attribute  named WebMethod from the namespace System.Web.Services. When the asmx file is now loaded, the screen is flashed with the name of the function, its parameter names and their data types. In addition, we get an input box to enter a number. This number becomes the value of the parameter i. When we keyed in the number 12 and clicked on the Invoke button, to our utter amazement, we saw the number 24 displayed, as shown below.

 

Output

<?xml version="1.0" encoding="utf-8" ?>

  <int xmlns="http://tempuri.org/">24</int>

 

 

This happens to be an xml file. Since the return value of our function is an int, the number 24 is enclosed within the int tag. The html file that we had taken notice of, and had attended to, was honestly, all smokes and mirrors.

 

Whenever the framework stumbles upon a file with an asmx extension, it treats it very differently from an aspx file. It finds out all the functions in the Web Service class that are tagged with an attribute of WebMethod. It then creates an HTML file. Clicking on the invoke button results in the execution of a URL by passing it parameters.

 

Next, we are interested in calling the function abc, with a parameter i, which has a value of 23. However, when we actually call the function abc, which has to be summoned from the Web Service zzz in the file a.asmx, the following URL has to be entered in the IE address bar: http://localhost/a.asmx/abc?i=23

 

The output window displays the following:

 

Output

<?xml version="1.0" ?>

<int xmlns="http://tempuri.org/">46</int>

 

Thus, if we are aware about the existence of a Web Service and are responsive towards its nuts and bolts, we can easily call the code from it, using a URL. The parameters to the functions are passed as HTML parameters. Assuming that we had two parameters named i and j in the function abc, we would enter the URL as follows:  http://localhost/a.asmx/abc?i=12&j=10.

 

On placing an error in the above C# program, we noticed that our Web Service is actually a dll. No extra code is added to the Web Service file, unlike in a control. Also, a Web Service does not derive from any other class. A Web Service internally uses SOAP, or the Simple Object Access Protocol, to bring this magic into being!

 

One more thing that you should be well conversant with, is the Service Description (WSDL file). If you click on the Service Description link, you will see an XML file that has obviously not been written by us. Let us now try to appreciate, what goes into this file.

 

WSDL file

 <?xml version="1.0" encoding="utf-8" ?>

- <definitions xmlns:s="http://www.w3.org/2001/XMLSchema" xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" xmlns:tm="http://microsoft.com/wsdl/mime/textMatching/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:s0="http://tempuri.org/" targetNamespace="http://tempuri.org/" xmlns="http://schemas.xmlsoap.org/wsdl/">

- <types>

- <s:schema attributeFormDefault="qualified" elementFormDefault="qualified" targetNamespace="http://tempuri.org/">

- <s:element name="abc">

- <s:complexType>

- <s:sequence>

  <s:element minOccurs="1" maxOccurs="1" name="i" type="s:int" />

  </s:sequence>

  </s:complexType>

  </s:element>

- <s:element name="abcResponse">

- <s:complexType>

- <s:sequence>

  <s:element minOccurs="1" maxOccurs="1" name="abcResult" type="s:int" />

  </s:sequence>

  </s:complexType>

  </s:element>

  <s:element name="int" type="s:int" />

  </s:schema>

  </types>

- <message name="abcSoapIn">

  <part name="parameters" element="s0:abc" />

  </message>

- <message name="abcSoapOut">

  <part name="parameters" element="s0:abcResponse" />

  </message>

- <message name="abcHttpGetIn">

  <part name="i" type="s:string" />

  </message>

- <message name="abcHttpGetOut">

  <part name="Body" element="s0:int" />

  </message>

- <message name="abcHttpPostIn">

  <part name="i" type="s:string" />

  </message>

- <message name="abcHttpPostOut">

  <part name="Body" element="s0:int" />

  </message>

- <portType name="zzzSoap">

- <operation name="abc">

  <input message="s0:abcSoapIn" />

  <output message="s0:abcSoapOut" />

  </operation>

  </portType>

- <portType name="zzzHttpGet">

- <operation name="abc">

  <input message="s0:abcHttpGetIn" />

  <output message="s0:abcHttpGetOut" />

  </operation>

  </portType>

- <portType name="zzzHttpPost">

- <operation name="abc">

  <input message="s0:abcHttpPostIn" />

  <output message="s0:abcHttpPostOut" />

  </operation>

  </portType>

- <binding name="zzzSoap" type="s0:zzzSoap">

  <soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document" />

- <operation name="abc">

  <soap:operation soapAction="http://tempuri.org/abc" style="document" />

- <input>

  <soap:body use="literal" />

  </input>

- <output>

  <soap:body use="literal" />

  </output>

  </operation>

  </binding>

- <binding name="zzzHttpGet" type="s0:zzzHttpGet">

  <http:binding verb="GET" />

- <operation name="abc">

  <http:operation location="/abc" />

- <input>

  <http:urlEncoded />

  </input>

- <output>

  <mime:mimeXml part="Body" />

  </output>

  </operation>

  </binding>

- <binding name="zzzHttpPost" type="s0:zzzHttpPost">

  <http:binding verb="POST" />

- <operation name="abc">

  <http:operation location="/abc" />

- <input>

  <mime:content type="application/x-www-form-urlencoded" />

  </input>

- <output>

  <mime:mimeXml part="Body" />

  </output>

  </operation>

  </binding>

- <service name="zzz">

- <port name="zzzSoap" binding="s0:zzzSoap">

  <soap:address location="http://localhost/a.asmx" />

  </port>

- <port name="zzzHttpGet" binding="s0:zzzHttpGet">

  <http:address location="http://localhost/a.asmx" />

  </port>

- <port name="zzzHttpPost" binding="s0:zzzHttpPost">

  <http:address location="http://localhost/a.asmx" />

  </port>

  </service>

  </definitions>

 

This XML file gives us all the details about the Web Service. It represents the Web Service, but without the code.

 

Let us explain the how's and why's of it.

A WSDL document defines services as collections of network endpoints, or ports. The tag called definition describes the Web Service, but in a non-programming manner. All Web Services are based on SOAP.

 

A Service Definition Language is made up of six major elements:

 

•   types, which provides data type definitions used to describe the messages exchanged.

•   message, which represents an abstract definition of the data being transmitted. A message consists of logical parts, each of which is associated with a definition within some type system.

•   portType, which is a set of abstract operations. Each operation refers to an input message and output messages.

•   binding, which specifies concrete protocol and data format specifications for the operations and messages defined by a particular portType.

•   port, which specifies an address for a binding, thus defining a single communication endpoint.

•   service, which is used to aggregate a set of related ports.

 

The WSDL file that has been generated, helps us to figure out the number of functions in the Web Service. The parameters, their data types and the return value are also specified along with the function names. This description is sufficient to execute a function. Observe that there is no sign of any code in the asmx file. Thus, the WSDL file is not concerned about whether the code is in Java or C# or in any other language. Since the file is machine generated, we will not spend more time deciphering it.

 

Let us now summon the Web Service from our program, which is written in C#.

 

a.asmx

<%@ WebService Language="C#" Class="zzz" %>

using System.Web.Services;

public class zzz

{

[WebMethod]

public int abc(int i)

{

return i*2;

}

}

 

Firstly, we write the following URL and click on the Service Description link, and then copy whatever file is displayed in the file named, a.wsdl in the c:\inetpub\wwwroot\bin sub-directory.

 

We now want some program to generate a C# program, which can act like our Web Service. The program that we shall be running, using the command laid down below, is called WebServiceUtil. Very soon, we shall be explaining as to what the various options in this command signify.

 

>wsdl.exe /l:CS /n:nnn a.wsdl

 

This will create a file called zzz.cs, since our Web Service class was called zzz. /n:nnn adds namespace nnn to the class. In case you receive any errors, you should ensure that the first line, <?xml version="1.0" ?>, begins at the first column, and the file thereafter starts with a tag on every line. Also if you have selected and copied the file from your browser, you will have to remove the ‘-’ sign preceeding every line.

 

The contents of zzz.cs are as follows:

 

zzz.cs

//--------------------------------------------------------------------------

// <autogenerated>

//     This code was generated by a tool.

//     Runtime Version: 1.0.2914.16

//

//     Changes to this file may cause incorrect behavior and will

//     be lost if the code is regenerated.

// </autogenerated>

//--------------------------------------------------------------------------

//

// This source code was auto-generated by wsdl, Version=1.0.2914.16.

namespace nnn {

    using System.Diagnostics;

    using System.Xml.Serialization;

    using System;

    using System.Web.Services.Protocols;

    using System.Web.Services;

       

    [System.Web.Services.WebServiceBindingAttribute(Name="zzzSoap", Namespace="http://tempuri.org/")]

    public class zzz : System.Web.Services.Protocols.SoapHttpClientProtocol {

       

        [System.Diagnostics.DebuggerStepThroughAttribute()]

        public zzz() {

            this.Url = "http://localhost/a.asmx";

        }

       

        [System.Diagnostics.DebuggerStepThroughAttribute()]

        [System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://tempuri.org/abc", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)]

        public int abc(int i) {

            object[] results = this.Invoke("abc", new object[] {

                        i});

            return ((int)(results[0]));

        }

       

        [System.Diagnostics.DebuggerStepThroughAttribute()]

        public System.IAsyncResult Beginabc(int i, System.AsyncCallback callback, object asyncState) {

            return this.BeginInvoke("abc", new object[] {

                        i}, callback, asyncState);

        }

       

        [System.Diagnostics.DebuggerStepThroughAttribute()]

        public int Endabc(System.IAsyncResult asyncResult) {

            object[] results = this.EndInvoke(asyncResult);

            return ((int)(results[0]));

        }

    }

}

This program has been generated by the wsdl program. The name of the class is given as zzz, which is derived from  System.Web.Services.Protocols.SoapHttpClientProtocol. The function abc accepts one parameter i.e. int i. Before we go on to explain how this code gets generated, let us first convert this machine generated code into a library zzz.dll, with the help of the following csc command:

 

>csc /t:library /r:system.web.services.dll  zzz.cs

 

Next, we have to call code from our Web Service. For this, we create a file a.aspx in the inetpub/wwwroot sub-directory.

 

a.aspx

<%@ Import Namespace="nnn" %>

<%@ language=C# %>

<form action="a.aspx" method="post" runat="server">

<script language="C#" runat=server>

void abc(Object a1, EventArgs e)

{

zzz a = new zzz();

int i = a.abc(Int32.Parse(aaa.Text));

Response.Write(i.ToString());

}

</script>

<asp:textbox id="aaa" runat="server"/>

<asp:button type=submit text="Click" OnClick="abc" runat="server"/>

</form>

 

The framework looks into the bin sub-directory for the code of the objects. On sighting it, the code gets executed.

 

The above program will generate a compilation error, if zzz.dll is not present in the bin sub-directory or if there are more dlls in the directory. This is because, the code for the class zzz resides in the zzz.dll, moreover, the compiler is not informed about the location and the name of the dll name. This can be done using the /R: option.

 

 

To solve the mystery of locating the dll, we take the assistance of the web.config file.

 

web.config

<configuration>

<system.web>

<compilation debug="false">

<assemblies>

<add assembly="zzz"/>

</assemblies>

</compilation>

</system.web>

</configuration>

 

To change the default behavior of anything in the ASP.Net world, we have to turn to the configuration file. The 'add assembly' option adds the dll that has been assigned to it, to the csc compiler. To be precise, it appends the dll with the /r: option to the compiler, while compiling any cs file. This assembly can be present anywhere on our hard disk. The /bin sub-directory is a special directory, which is checked only for our business objects. This is how the framework can be customized to work with our files.

 

Now, if you load the aspx file using http://localhost/a.aspx, you will notice a button and a textbox. If you type in the number 12 and click on the button, the abc function in the aspx file will be called. In the function abc, a new zzz object called a, is created, and the function abc is called off it. This function is supplied with a parameter, which is the text entered in the TextBox, after converting it into an int. The return value of this function is displayed through the Write function. Any number that we enter is multiplied by 2, and then the value is returned.

 

Note that the code for the multiplication is not present in the zzz class. To further prove this point, we merely open the asmx file and multiply by 3, instead of 2. Now, if we click on the button, we will observe the numbers being multiplied by 3. Are you feeling perplexed already? If so, it would be sensible for you to revise the above text, before proceeding any further.

 

 

We are doing the following to prove to you that, you can easily change the way ASP+ looks at the world.

 

The VB sample in the documentation derives from the WebService class, while, the C# sample does not.

 

a.asmx

<%@ WebService Language="C#" Class="zzz" %>

using System;

using System.Web.Services;

public enum yyy

{

b1 = 10,

b2 = 20

}

public class xxx

{

public int i1;

public double d1;

}

public class zzz

{

[WebMethod]

public String a1()

{

return "vijay";

}

[WebMethod]

public int[] a2()

{

int[] a = new int[2];

a[0] = 10;

a[1] = 20;

return a;

}

[WebMethod]

public yyy a3()

{

return yyy.b1;

}

[WebMethod]

public xxx a4()

{

xxx x = new xxx();

x.i1=10;

x.d1 = 10.1;

return x;

}

[WebMethod]

public xxx[] a5()

{

xxx [] x = new xxx[2];

x[0] = new xxx();

x[0].i1=3;

x[0].d1=3.1;

x[1] = new xxx();

x[1].i1=9;

x[1].d1 = 9.1;

return x;

}

}

 

We have created 5 functions named a1 to a5 in our Web Service. The display order may not be in the order of creation. The point we are making here is that, we are allowed to return any data types that we like. Let us start by clicking on each function and understanding the output. The first function, a1, simply returns a string.

 

Output

<?xml version="1.0" encoding="utf-8" ?>

  <string xmlns="http://tempuri.org/">vijay</string>

 

The value 'vijay' is placed within a tag called string, since our function returns a string. The next function, a2, returns an array of ints.

 

Output

<?xml version="1.0" encoding="utf-8" ?>

<ArrayOfInt xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://tempuri.org/">

  <int>10</int>

  <int>20</int>

  </ArrayOfInt>

 

The individual ints are tagged with the int tag, and the entire array is enclosed in an ArrayOfInt tag. Thus, we can also return an array of any data type.

 

The next click will call function a3, which returns the value of an enum. An enum is a class that contains names that represent values.

 

Output

 <?xml version="1.0" encoding="utf-8" ?>

  <yyy xmlns="http://tempuri.org/">b1</yyy>

 

The enum member that is returned, is placed in a tag, that is the name of the enum class yyy.

 

Function a4 returns an object of a class xxx. This class has two members, i1 and d1. Hence, the output is displayed as follows:

 

Output

<?xml version="1.0" encoding="utf-8" ?>

<xxx xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://tempuri.org/">

  <i1>10</i1>

  <d1>10.1</d1>

  </xxx>

 

The last function, a5 is like the one above, but it returns an array of xxx objects.

 

Output

<?xml version="1.0" encoding="utf-8" ?>

<ArrayOfXxx xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://tempuri.org/">

<xxx>

  <i1>3</i1>

  <d1>3.1</d1>

  </xxx>

<xxx>

  <i1>9</i1>

  <d1>9.1</d1>

</xxx>

</ArrayOfXxx>

 

The tag, ArrayOfXxx encloses the entire output. Each member of the array is placed within the tag xxx, and the individual members are placed within their own tags. By making use of  a Web Service, we are at a liberty to pass any data types, as return values or as parameters. Thus, there are no restrictions. We will leave it as an exercise for you to run the same Web Service from an aspx file.

 

a.asmx

<%@ WebService Language="C#" Class="zzz" %>

using System;

using System.Data;

using System.Data.SqlClient;

using System.Web.Services;

public class zzz

{

[WebMethod]

public DataSet abc()

{

SqlConnection c = new SqlConnection("server=localhost;uid=sa;pwd=;database=NorthWind");

SqlDataAdapter co = new SqlDataAdapter("select productid,productname from Products where productid='1'",c);

SqlDataAdapter co1 = new SqlDataAdapter("select customerid,companyname from Customers where customerid='BOLID'", c);

DataSet ds = new DataSet();

co.Fill(ds, "zzz");

co1.Fill(ds, "yyy");

return ds;

}

}

 

Output

  <?xml version="1.0" encoding="utf-8" ?>

 <DataSet xmlns="http://tempuri.org/">

<xsd:schema id="NewDataSet" targetNamespace="" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">

<xsd:element name="NewDataSet" msdata:IsDataSet="true">

<xsd:complexType>

<xsd:choice maxOccurs="unbounded">

<xsd:element name="zzz">

<xsd:complexType>

<xsd:sequence>

<xsd:element name="productid" type="xsd:int" minOccurs="0" />

  <xsd:element name="productname" type="xsd:string" minOccurs="0" />

  </xsd:sequence>

  </xsd:complexType>

  </xsd:element>

<xsd:element name="yyy">

<xsd:complexType>

<xsd:sequence>

<xsd:element name="customerid" type="xsd:string" minOccurs="0" />

  <xsd:element name="companyname" type="xsd:string" minOccurs="0" />

  </xsd:sequence>

  </xsd:complexType>

  </xsd:element>

  </xsd:choice>

  </xsd:complexType>

  </xsd:element>

  </xsd:schema>

<diffgr:diffgram xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" xmlns:diffgr="urn:schemas-microsoft-com:xml-diffgram-v1">

<NewDataSet xmlns="">

<zzz diffgr:id="zzz1" msdata:rowOrder="0">

  <productid>1</productid>

  <productname>Chai</productname>

  </zzz>

<yyy diffgr:id="yyy1" msdata:rowOrder="0">

  <customerid>BOLID</customerid>

  <companyname>Bσlido Comidas preparadas</companyname>

  </yyy>

  </NewDataSet>

  </diffgr:diffgram>

  </DataSet>

 

One thing that is very evident is that, Microsoft is in love with XML and finds it irresistable. Hence, we see XML popping out of everywhere.

 

In the above Web Service, we are connecting to the database NorthWind and creating two SQL statements that will return one record each, from two separate tables. These select statements are added to our dataset object and the object is then returned. The output is in the form of an appealingly formatted XML file.

 

Let us try to understand this file now.

As usual, the XML file starts with the xml version number. It is then followed by a tag called DataSet. DataSet informs us that the data given within it is from a database. The first dataset with the name zzz, becomes the name of our element. This is succeeded by the field names or the schema.

 

The same procedure is repeated for the second table in the data set. Then, we have a tag called NewDataSet, followed by the name of the first dataset zzz, in a tag form. Then, we have the values from the database enclosed by the field names, once again in tags. The same process is reiterated for the other table too.

 

a.asmx

<%@ WebService Language="C#" Class="zzz" %>

using System;

using System.Web.Services;

public class zzz : WebService

{

[WebMethod(EnableSession=true)]

public String abc()

{

if (Session["aa"] == null)

{

Session["aa"] = 1;

}

else

{

Session["aa"] = ((int) Session["aa"]) + 1;

}

return "Session " + Session["aa"].ToString() + " times.";

}

[WebMethod(EnableSession=false)]

public String pqr()

{

if (Application["aa"] == null)

{

Application["aa"] = 1;

}

else

{

Application["aa"] = ((int) Application["aa"]) + 1;

}

return "Application " + Application["aa"].ToString() + " times.";

}

}

 

In the above Web Service, we use two functions, named abc and pqr. The function abc has a parameter called EnableSession=true, added to the WebMethod. This parameter switches on the session tracking. The function pqr is similar to this, with an exception of the session tracking being disabled. Thereafter, a Session Variable aa, is created in the function abc and an Application Variable by the same name aa is created in pqr to store a value. This value is incremented by 1, each time, and is finally returned as a string.

 

The Application and Session objects are framework intrinsic. To understand the above example, select the 'prompt' radio button for the cookie. Now, each time we click on abc, a cookie is received by the browser. However, such is not the case with the Application.

 

Now, close all instances of the browser and open only one browser copy. Rewrite the same URL in the address bar and click on abc. The session count begins from 1. If you click on pqr, you will notice that the application remembers its last count, which, it now increments by 1. By disabling the session support for a particular web function, the web server now has less work to do. Thus, the web method will be served up faster.

 

We first start with the WSDL file named a.wsdl in the c:\inetpub\wwwroot\bin sub-directory.

 

a.wsdl

<?xml version="1.0"?>

<definitions xmlns:s="http://www.w3.org/1999/XMLSchema" xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:s0="http://tempuri.org/" targetNamespace="http://tempuri.org/" xmlns="http://schemas.xmlsoap.org/wsdl/">

<types>

<s:schema targetNamespace="http://tempuri.org/"

attributeFormDefault="qualified" elementFormDefault="qualified">

<s:element name="abc">

<s:complexType derivedBy="restriction"/>

</s:element>

<s:element name="abcResult">

<s:complexType derivedBy="restriction">

<s:all>

<s:element name="result" type="s:string" nullable="true"/>

</s:all>

</s:complexType>

</s:element>

<s:element name="string" type="s:string" nullable="true"/>

</s:schema>

</types>

<message name="abcHttpGetIn"/>

<message name="abcHttpGetOut">

<part name="Body" element="s0:string"/>

</message>

<portType name="zzzHttpGet">

<operation name="abc">

<input message="s0:abcHttpGetIn"/>

<output message="s0:abcHttpGetOut"/>

</operation>

</portType>

<binding name="zzzHttpGet" type="s0:zzzHttpGet">

<http:binding verb="GET"/>

<operation name="abc">

<http:operation location="/a.html"/>

<input>

<http:urlEncoded/>

</input>

<output>

<text xmlns="http://microsoft.com/wsdl/mime/textMatching/">

<match name='Title' pattern='TITLE&gt;(.*?)&lt;'/>

<match name='Vijay' pattern='&gt;(.*?)&lt;'/>

</text>

</output>

</operation>

</binding>

<service name="zzz">

<port name="zzzHttpGet" binding="s0:zzzHttpGet">

<http:address location="http://localhost" />

</port>

</service>

</definitions>

 

a.html

<HTML>

<HEAD>

<TITLE>Hello!</TITLE>

</HEAD>

<BODY>

<Vijay>Mukhi</Vijay>

</BODY>

</HTML>

 

We then run the following two commands:

 

>wsdl /l:CSharp /n:nnn a.wsdl

 

The above command creates a file called zzz.cs for us.

 

>csc /t:library zzz.cs

 

This creates a file by the name of zzz.dll in the bin sub directory.

 

zzz.cs

//----------------------------------------------------------------------

// <autogenerated>

//     This code was generated by a tool.

//     Runtime Version: 1.0.2914.16

//

//     Changes to this file may cause incorrect behavior and will be lost if

//     the code is regenerated.

// </autogenerated>

//----------------------------------------------------------------------

//

// This source code was auto-generated by wsdl, Version=1.0.2914.16.

//

namespace nnn {

    using System.Diagnostics;

    using System.Xml.Serialization;

    using System;

    using System.Web.Services.Protocols;

    using System.Web.Services;

    public class zzz : System.Web.Services.Protocols.HttpGetClientProtocol {

       

        [System.Diagnostics.DebuggerStepThroughAttribute()]

        public zzz() {

            this.Url = "http://localhost/a.html";

        }

      [System.Diagnostics.DebuggerStepThroughAttribute()]

        [System.Web.Services.Protocols.HttpMethodA

ttribute(typeof(System.Web.Services.Protocols.TextReturnReader), typeof(System.Web.Services.Protocols.UrlParameterWriter))]

      public abcMatches abc() {

       return ((abcMatches)(this.Invoke("abc", (this.Url + "/QuickStart/aspplus/samples/services/TextMatching/CS/MatchServer.html"), new object[0])));

        }

      [System.Diagnostics.DebuggerStepThroughAttribute()]

        public System.IAsyncResult Beginabc(System.AsyncCallback callback, object asyncState) {

      return this.BeginInvoke("abc", (this.Url + "/QuickStart/aspplus/samples/services/TextMatching/CS/MatchServer.html"), new object[0], callback, asyncState);

        }

     [System.Diagnostics.DebuggerStepThroughAttribute()]

     public abcMatches Endabc(System.IAsyncResult asyncResult)

     {

            return ((abcMatches)(this.EndInvoke(asyncResult)));

     }

    }

    public class abcMatches {

             [System.Web.Services.Protocols.MatchAttribute("TITLE>(.*?)<")]

        public string Title;

           [System.Web.Services.Protocols.MatchAttribute(">(.*?)<")]

        public string Vijay;

   }

}

 

a.aspx

<%@ Import Namespace="nnn" %>

<html>

<script language="C#" runat="server">

public void Abc(Object Src, EventArgs E)

{

zzz m= new zzz();

abcMatches ma = m.abc();

ma.Vijay = "mukhi";

Response.Write(ma.Title + "." + ma.Vijay);

}

</script>

<body>

<form runat="server">

<input type="submit" OnServerClick="Abc" runat="server"/>

</form>

</body>

</html>

 

Output

 

After clicking on the button:

Hello!.mukhi

 

For the first time, we are creating a WSDL file manually.

 

<operation name="abc">

<http:operation location="/a.html"/>

 

We have a tag called operation that sets the name property to the function abc and the http operation location is set to a file named a.html. 

 

The text tag encloses two occurrence of another tag called 'match'. The name 'property' is set to 'Title' and 'Vijay', respectively. Moreover, a pattern or wild card is specified for each of them. It specifies a certain pattern or a rule.

 

Now, the question that vexes our wits, is : From where will the value of 'Title' be obtained?

 

The value lies in the html file. The value of 'Hello', which is enclosed in the Title tag in the HTML file, is picked up and assigned to the 'Title' variable in a.aspx. The same procedure is followed for 'Vijay'. The tag name match is a special tag. It is available as a class called abcMatches, in the aspx file.

 

In the .cs file that is generated, the constructor saves the URL in a variable called Url, for future reference. The function abc returns an instance of the abcMatches class. The class abcMatches created in zzz.cs, contains two instance variables, 'Title' and 'Vijay', with or without the pattern.

 

In the aspx file, when a button is clicked, the function Abc is called. In this function, we create a new zzz instance, and then call the function abc from it. The output is an abcMatches object which we store in an object named ma. Thereafter, the value in 'Vijay' is initialized to 'mukhi'. Finally, both the variables are displayed, using the Write function. Thus, without creating any asmx file, using our code, we have been able to read data within tags in an HTML file. We are thus, doing things in a way that is a drastic departure from what we have been doing so far.

 

As we reiterated many times in the past, you are allowed to configure  everything in case of ASP+. The main web.config file informs the framework about the aspx file that handles a Web Service, or a file with an asmx extension.