Web Services and the .NET Framework
Building a Web Service component using C# and .NET

Gopalan Suresh Raj

Note
To work with any of these samples, you will need the following:
.........................................Microsoft .NET SDK
.........................................Microsoft Visual Studio.NET Beta 2 or higher

 

To ease development, I recommend using the Visual Studio.NET IDE. However, you are free to develop your application in the favorite editor of your choice, using the command-line to execute the various commands to build and deploy it.

Building Web Service components using the .NET Framework

Web Services run on top of HTTP. Therefore, they are developed and deployed on a Web Server and their URL is advertised so that "Internet" clients can discover and make use of their services. Even though that Web Server can be Microsoft IIS, or Apache, or any other such server, at this point in time, the .NET framework only supports deployment on Microsoft IIS.

In this article, we will build a web service called OIDServer that clients can use to generate a unique Object Identity (OID) string. The generated OID string is unique, and can be used by the client wherever unique keys are needed - either for COM GUIDs, or to act as a unique primary key for a database table, etc. Since the Web Service class is deployed on a Web Server, any "Internet" client can access it and make use of its services - as opposed to COM components which can only be accessed by COM clients.

The various steps that are involved in creating a Web Service Component using C# and the .NET Framework are as follows (I'm going to assume you're using the VS.NET IDE):

  1. Create a Visual C# - ASP.NET Web Service project

  2. Develop the OIDServer.asmx file and the OIDServer.asmx.cs class file

  3. Modify the generated AssemblyInfo.cs to add the right assembly information

  4. Build the Project Files

1. Create a Visual C# - ASP.NET Web Service project

Create a new Visual C# ASP.NET Web Service project.

 

2. Develop the OIDServer.asmx file and the OIDServer.asmx.cs class file

Visual Studio.NET creates a bunch of files for you to use while developing your web service. Of particular interest for our discussion now are, the OIDServer.asmx file and the OIDServer.asmx.cs class file.

The OIDServer.asmx file

OIDServer.asmx contains the <%@ WebService... %> directive, as well as the class that provides the implementation in the Class="OIDServer.OIDServer"  directive. To any web service client, the .asmx file serves as the main entry point to the Web Service. This file needs to be hosted on a virtual directory on IIS that has the executescripts permission turned on.

OIDServer.asmx
1:
<%@ WebService Language="c#" Codebehind="OIDServer.asmx.cs" Class="OIDServer.OIDServer" %>

People familiar with ASP will immediately recognize the @ symbol in front of the WebService keyword. The WebService directive specifies the language used to develop the web service so that ASP.NET can compile this service with the right compiler. The Class="OIDServer.OIDServer" directive specifies the class that implements the web service, so that the right class can be loaded and its Web Services Description (WSDL) generated using reflection. 

The OIDServer.asmx.cs Class file

As shown on Line 34, Web Services derive from the System.Web.Services.WebService class which allows the web service object to access all normal ASP objects exposed in the WebService base class. This means, the OIDServer class can use ASP objects as though it were a regular ASP based application. As the default namespace http://tempuri.org/ will not uniquely identify our web service from other web services on the internet, we specify our own namespace http://icommware.com before publishing our web service publicly as shown on Line 32. The  Namespace = "http://icommware.com" attribute facilitates us to specify our own namespace. Unless you don't want to publish a method, you need to tag all public methods with the WebMethod attribute to make web methods public methods of a distributed component that are accessible though the world-wide web. This is shown on line 64.

OIDServer.asmx.cs
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
//////////////////////////////////////////////////////
/// The following example illustrates a Web Service
/// developed using C# and the .NET Framework.
///
/// author: Gopalan Suresh Raj
/// Copyright (c), 2002. All Rights Reserved.
/// URL: https://gsraj.tripod.com/
/// email: gopalan@gmx.net
///
/// <generate>
/// wsdl /l:CS /protocol:SOAP http://localhost/OIDServer/OIDServer.asmx?WSDL
/// wsdl /l:CS /protocol:HttpGet http://localhost/OIDServer/OIDServer.asmx?WSDL
/// wsdl /l:CS /protocol:HttpPost http://localhost/OIDServer/OIDServer.asmx?WSDL
/// </generate>
/// <compile>
/// csc /t:library /r:System.Web.Services.dll /r:System.Xml.dll OIDServer.dll
/// </compile>
//////////////////////////////////////////////////////
using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Web;
using System.Web.Services;
using System.EnterpriseServices;

namespace OIDServer {
  /// <summary>
  /// Summary description for OIDServer.
  /// </summary>
  [WebService ( Namespace = "http://icommware.com", Name = "OIDServer",
                        Description =
"Generates unique Object Identity (OID)" )]
  public class OIDServer : System.Web.Services.WebService {

    /// <summary>
    /// Default No argument constructor
    /// </summary>
    public OIDServer() {
      //CODEGEN: This call is required by the ASP.NET Web Services Designer
      InitializeComponent();
    }

    #region Component Designer generated code
    /// <summary>
    /// Required method for Designer support - do not modify
    /// the contents of this method with the code editor.
    /// </summary>
    private void InitializeComponent() {
    }
    #endregion

    /// <summary>
    /// Clean up any resources being used.
    /// </summary>
    protected override void Dispose( bool disposing ) {
    }

    /// <summary>
    /// Generates unique Object Identity (OID). Returns a String representation
    /// of the value of a new GUID in the Windows Registry format.
    /// </summary>
    /// <returns></returns>
    [WebMethod( EnableSession = true, TransactionOption = TransactionOption.Disabled,
                         BufferResponse =
false, CacheDuration = 0, MessageName = "generateOID",
                         Description =
"Generates unique Object Identity (OID)" )]
    public string generateOID () {
      return Guid.NewGuid ().ToString();
    }
  }
}

Notice that the generateOID() method on Line 64 is tagged with the WebMethod tag using the [] syntax. By specifying the [WebMethod] tag in front of this public method, we make this public method callable from any Internet client. Behind the scenes, the generateOID() method is associated with an attribute which is implemented as a WebMethodAttribute class. This class has six properties which are also specified from Lines 64 through 66. 

The EnableSession property enables or disables session state. If you don't intend to use session state for this web method, you should disable this flag so that the web server does not generate and manage session IDs for every user accessing this web method. This might improve performance. This flag is true by default.

The TransactionOption property can be one of five values: Disabled, NotSupported, Supported, Required, and RequiresNew. As Web Methods can participate only as the root object in a Transaction, both Required and RequiresNew options result in a new transaction being created for the Web Method. The Disabled, NotSupported, and Supported  options result in no transactions being used for the web methods. The TransactionOption  property is set to Disabled by default.

The BufferResponse property controls whether or not to buffer the method's response.

The CacheDuration property specifies the length of time, in seconds, to keep the method response in the cache. The default does not hold the response in the cache (0 seconds).

The MessageName property is used to distinguish web methods with the same names. For example, if you have two methods with the same name, and you want to publish both these methods as web methods, the system will have a problem identifying one from the other as their names are duplicated. This property ensures that all service signatures in the WSDL are unique.

The Description property provides additional descriptive information about a particular method.

3. Modify the generated AssemblyInfo.cs to add the right assembly information

You provide the compiler with your assembly information in an assembly file called AssemblyInfo.cs. The assembly information file is compiled with the  rest of the project's source files. The information is in the form of assembly attributes - directives to the compiler on the information to embed in the assembly.

AssemblyInfo.cs
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
using System.Reflection;
using System.Runtime.CompilerServices;

//
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
//
[assembly: AssemblyTitle("OID Server")]
[assembly: AssemblyDescription("Creates unique Object Identity (OID)")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("eCommWare Corporation")]
[assembly: AssemblyProduct("OID Server")]
[assembly: AssemblyCopyright("(c) 2001, Gopalan Suresh Raj. All Rights Reserved.")]
[assembly: AssemblyTrademark("Web Cornucopia")]
[assembly: AssemblyCulture("en-US")]

//
// Version information for an assembly consists of the following four values:
//
//      Major Version
//      Minor Version
//      Build Number
//      Revision
//
// You can specify all the values or you can default the Revision and Build Numbers
// by using the '*' as shown below:

[assembly: AssemblyVersion("1.0.*")]

//
// In order to sign your assembly you must specify a key to use. Refer to the
// Microsoft .NET Framework documentation for more information on assembly signing.
//
// Use the attributes below to control which key is used for signing.
//
// Notes:
//   (*) If no key is specified, the assembly is not signed.
//   (*) KeyName refers to a key that has been installed in the Crypto Service
//       Provider (CSP) on your machine. KeyFile refers to a file which contains
//       a key.
//   (*) If the KeyFile and the KeyName values are both specified, the
//       following processing occurs:
//       (1) If the KeyName can be found in the CSP, that key is used.
//       (2) If the KeyName does not exist and the KeyFile does exist, the key
//           in the KeyFile is installed into the CSP and used.
//   (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility.
//        When specifying the KeyFile, the location of the KeyFile should be
//        relative to the "project output directory". The location of the project output
//        directory is dependent on whether you are working with a local or web project.
//        For local projects, the project output directory is defined as
//       <Project Directory>\obj\<Configuration>. For example, if your KeyFile is
//       located in the project directory, you would specify the AssemblyKeyFile
//       attribute as [assembly: AssemblyKeyFile("..\\..\\mykey.snk")]
//        For web projects, the project output directory is defined as
//       %HOMEPATH%\VSWebCache\<Machine Name>\<Project Directory>\obj\<Configuration>.
//   (*) Delay Signing is an advanced option - see the Microsoft .NET Framework
//       documentation for more information on this.
//
[assembly: AssemblyDelaySign(false)]
[assembly: AssemblyKeyFile("")]
[assembly: AssemblyKeyName("")]

The OIDServer.vsdisco file

Whenever a remote (or local) client is interested in using a Web Service, the first step is to determine which web services exist on a given machine. Even though the .NET class library provides the API that allows you to examine registered Web Services programmatically, discovery services are also required by numerous case tools. The .vsdisco file is used to describe each Web Service in a given virtual directory and any related subfolders.

OIDServer.vsdisco
1:
2:
3:
4:
5:
6:
7:
8:
9:
<?xml version="1.0" ?>
<dynamicDiscovery xmlns="urn:schemas-dynamicdiscovery:disco.2000-03-17">
<exclude path="_vti_cnf" />
<exclude path="_vti_pvt" />
<exclude path="_vti_log" />
<exclude path="_vti_script" />
<exclude path="_vti_txt" />
<exclude path="Web References" />
</dynamicDiscovery>

The Web.config file

The generated Web.config file should normally be placed in the same directory as the .asmx file. This configuration file allows you to control various application settings of the virtual directory. To ease development and testing, it is recommended that you set the authentication mode to None as shown on Line 28. However, when releasing the web service to the public, you can change it to either Windows, or Forms, or Passport, as opposed to None.

The authentication mode set to Windows indicates that authentication is performed by IIS in one of three ways - basic, digest, or Integrated Windows Authentication.

The authentication mode set to Forms indicates that un-authenticated requests are redirected to a login page.

The authentication mode set to Passport indicates that un-authentication requests are directed to Microsoft's centralized authentication service. When authenticated, a token is passed back and used by subsequent requests.

Web.config
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.web>
    <!--  DYNAMIC DEBUG COMPILATION
          Set compilation debug="true" to enable ASPX debugging.  Otherwise, setting this value to
          false will improve runtime performance of this application.
          Set compilation debug="true" to insert debugging symbols (.pdb information)
          into the compiled page. Because this creates a larger file that executes
          more slowly, you should set this value to true only when debugging and to
          false at all other times. For more information, refer to the documentation about
          debugging ASP.NET files.
    -->
    <compilation
         defaultLanguage="c#"
         debug="true"
    />
    <!--  CUSTOM ERROR MESSAGES
          Set mode="on" or "remoteonly" to enable custom error messages, "off" to disable. Add
          <error> tags for each of the errors you want to handle.
    -->
    <customErrors
    mode="Off"
    />
    <!--  AUTHENTICATION
          This section sets the authentication policies of the application. Possible modes are "Windows", "Forms",
          "Passport" and "None"
    -->
    <authentication mode="None" />
    <!--  APPLICATION-LEVEL TRACE LOGGING
          Application-level tracing enables trace log output for every page within an application.
          Set trace enabled="true" to enable application trace logging.  If pageOutput="true", the
          trace information will be displayed at the bottom of each page.  Otherwise, you can view the
          application trace log by browsing the "trace.axd" page from your web application
          root.
    -->
    <trace
        enabled="false"
        requestLimit="10"
        pageOutput="false"
        traceMode="SortByTime"
        localOnly="true"
    />
    <!--  SESSION STATE SETTINGS
          By default ASP.NET uses cookies to identify which requests belong to a particular session.
          If cookies are not available, a session can be tracked by adding a session identifier to the URL.
          To disable cookies, set sessionState cookieless="true".
    -->
    <sessionState
            mode="InProc"
            stateConnectionString="tcpip=127.0.0.1:42424"
            sqlConnectionString="data source=127.0.0.1;user id=sa;password="
            cookieless="false"
            timeout="20"
    />
    <!--  PREVENT SOURCE CODE DOWNLOAD
          This section sets the types of files that will not be downloaded. As well as entering
          a httphandler for a file type, you must also associate that file type with the aspnet_isapi.dll
          in the App Mappings property of the web site, or the file can be downloaded.
          It is recommended that you use this section to prevent your sources being downloaded.
    -->
    <httpHandlers>
            <add verb="*" path="*.vb" type="System.Web.HttpNotFoundHandler,System.Web" />
            <add verb="*" path="*.cs" type="System.Web.HttpNotFoundHandler,System.Web" />
            <add verb="*" path="*.vbproj" type="System.Web.HttpNotFoundHandler,System.Web" />
            <add verb="*" path="*.csproj" type="System.Web.HttpNotFoundHandler,System.Web" />
            <add verb="*" path="*.webinfo" type="System.Web.HttpNotFoundHandler,System.Web" />
    </httpHandlers>
    <!--  GLOBALIZATION
          This section sets the globalization settings of the application.
    -->
    <globalization
            requestEncoding="utf-8"
            responseEncoding="utf-8"
   />
</system.web>
</configuration>

4. Build the Project Files

Build the files that make up the project.

------ Rebuild All started: Project: OIDServer, Configuration: Debug .NET ------

Preparing resources...
Updating references...
Performing main compilation...

Build complete -- 0 errors, 0 warnings
Building satellite assemblies...



---------------------- Done ----------------------

Rebuild All: 1 succeeded, 0 failed, 0 skipped

5. Deploy the Web Service files on IIS, and test your Web Service

As soon as you compile your Web Service, you can use it by executing it from the Visual Studio.NET IDE - Run or Debug the Application. By default, the machine's active browser functions as a makeshift client, that shows a HTML view of all the methods marked with the [WebMethod] attribute as shown in the figure below.

You can invoke the generateOID() method by clicking the generateOID link and you'll get the following page shown.

When you click on the Invoke button, the web service is invoked and the result is displayed on the next page.

 

 

Now you need to build a client application that can access this Web Service component over the web.

Building a complete Web Service component using C# and .NET
Building a Web Service Client using C# and .NET
Accessing a .NET Web Service using Apache/SOAP and Java

 

Download the entire source code as a zip file.

 

click here to go to
My Advanced C#/.NET Tutorial Page...

About the Author...
Gopalan Suresh Raj is a Software Architect, Developer and an active Author. He has co-authored a number of books including "Professional JMS", "Enterprise Java Computing-Applications and Architecture" and "The Awesome Power of JavaBeans". His expertise spans enterprise component architectures and distributed object computing. Visit him at his Web Cornucopia© site (https://gsraj.tripod.com/) or mail him at gopalan@gmx.net.

 


Go to the Component Engineering Cornucopia page

This site was developed and is maintained by Gopalan Suresh Raj

This page has been visited times since January 6, 2002.

Last Updated : Jan 06, '02

If you have any questions, comments, or problems regarding this site, please write to me I would love to hear from you.


Copyright (c) 1997-2002, Gopalan Suresh Raj - All rights reserved. Terms of use.

All products and companies mentioned at this site are trademarks of their respective owners.