Creating a Web Service Using Visual Studio .NET

Creating a Web Service Using Visual Studio .NET

To demonstrate how a web service may be constructed and used by other web services and web forms, a simple date scheduling application is presented in this chapter. This date scheduling system is made up of the following three classes:

  • anEvent A class representing an event that takes place at a given time and day

  • Events A class representing a collective group of instances of class anEvent

  • EventClient A web form that consumes Events and anEvent instances

The Events class is a web service, anEvent is a class used by the Events web service, and the EventClient class is a web form that uses anEvent and Events. All the classes reside under the same namespace, called myPortal. The assembly created when compiled is myPortal.dll. An Events.asmx file will point to a class within the myPortal.dll. The myPortal.dll will also host the class for the web form EventClient and the class anEvent. The EventClient.aspx file will direct the .NET Framework to myPortal.dll for the compiled code containing the associated class.

Let’s create a new ASP.NET web service project:

  1. Open Visual Studio .NET, and a start page will be displayed (unless it has been configured not to display the start page). Like the previous versions of Visual Studio, a project template splash screen is provided by default, but this can be disabled.

  2. Choose File | New Project to open the New Project window and the New Project window will open displaying project types and the corresponding project templates.

  3. Select the Visual C# Projects node in the left list. The project templates that correspond to C# will be displayed in the right list.

  4. Select the ASP.NET Web Service project template.

  5. The default name assigned to a new web service in any project is Service1. In this example, the project will be named myPortal, as shown in Figure 15-2. The server name may also be specified using the Uniform Resource Locator (URL) or using a Universal Naming Convention (UNC) file path to the web root. The default server name, localhost, could be specified in the URL if you wanted to host the solution on your workstation during the initial code and unit test phase.

  6. Click OK.

    click to expand
    Figure 15-2: New project myPortal being created in the New Project dialog box

Visual Studio .NET will attempt to connect to the web server specified in the New Project dialog box. If Visual Studio .NET connects successfully, it will create a new virtual directory and it will copy the default web services files to the new virtual directory.

After Visual Studio .NET has completed generation of all of the project files for the web service being created, the design view of the newly generated web service, Service1, is presented and prepared for editing. Visual Studio .NET assigns a default name to the web service files created in the project so they will be renamed.

  1. Open the Solution Explorer from the menu View | Solution Explorer.

  2. Right click on the file Service1.asmx and select Rename.

  3. Delete the name Service1 and enter the name Events.

  4. Press the ENTER key and the filename for the ASMX file, the Codebehind file, and the resolution file should change to Events.asmx, Events.asmx.cs, and Events.asmx.res, respectively.

The class supporting the web service will still be named Service1, however. The web service will function properly with the different names but let’s change the class to be the same as the web service name.

  1. Select the Events.asmx file in the Solution explorer and click the View Designer button at the top of the Solution Explorer. The Events.asmx.cs file will be displayed in the Visual Studio .NET Component Designer.

  2. Right-click on the Events.asmx.cs file as it is displayed in the Visual Studio .NET Component Designer and select Properties.

  3. After the Properties window opens, the value Service1 should be in the Name property. Delete the value.

  4. Enter the value Events in the name property. The Component Designer will change each occurrence of the class name in the Codebehind file automatically.

The purpose of the Events web service is to add, open, or delete instances of class anEvent to and from the portal. The data for a given instance of anEvent will be stored in a database. Because the Events class will interact with a database, components from the toolbox that will aid in the acquisitions and submission will be used in the course of building the web service, as shown in Figure 15-3. The components will be pasted on the design view of the Events web service.

click to expand
Figure 15-3: Designer components pasted on design view for Events web service

Using the Component Designer

The toolbox provides many types of components that you can add to a web service. Some of the components are available in both web forms and web services, but the components that serve to produce a graphical user interface (GUI) for the end user are not available in the web service project. Pasting web service components on the design view for the Events web service has no effect on the Events.asmx file. The ASMX is just like the web form ASPX file in that it associates the language, class, Codebehind, and resource files to the web service. The ASMX differs from the ASPX file in that it does not contain any other information pertaining to display.

The content of Events.asmx is shown in Listing 15-1. If Listing 15-1 were for a web form, it would contain more XML (eXtensible Markup Language) and HTML (Hypertext Markup Language) code designating display configurations; however, because this code is for a web service, it consists of only a single line of text.

Listing 15-1: Source Code of Web Service Events - File Events.asmx

start example
<%@ WebService Language="c#" Codebehind="Events.asmx.cs"   %>
end example

When the connection component or any component is pasted on the design view of the web service, the properties for the component may be set in the Properties window. For each value set in the Properties window, the Visual Studio .NET Component Designer produces initialization code in the Codebehind file for the web service. A preprocessor region command is defined, called Component Designer–generated code. Preprocessor commands in C# are similar to the preprocessor commands in C++ and C. The preprocessors commands in C# differ from those of C++ and C in the following ways:

  • C# preprocessor commands are not interpreted by a preprocessor that is separate from the compiler. The compiler and the preprocessor are the same.

  • C# preprocessor commands cannot specify macros.

The # region command specifies an area that can be expanded or collapsed within the Visual Studio .NET editor. The # region command has no functional effect on the solution.

Within the Component Designer–generated code region, Visual Studio .NET declares three items:

  • A reference to IContainer named components

  • A subroutine named InitializeComponent

  • A function named Dispose

All components pasted on the design view of the web service are initialized in the subroutine InitializeComponent. A call to the InitializeComponent subroutine is automatically placed in the constructor for the web service. Any properties that are set in the Properties window, as shown in Figure 15-3, will be assigned to the respective component to which they belong. The comments the Visual Studio .NET Component Designer places within this region warn you not to edit code manually. The Component Designer–generated code region appears as a section devoted to supporting Component Designer design view interaction for the web service.

The IContainer components instance is used by the Dispose function. The components instance contains references to all of the instances of components within the web service. The Dispose method of the components instance will release any resources claimed by the web services container.

Configuring a Database Connection Component

Because the intended data source for the Events web service is a SQL Server 2000 database, a SQLConnection component from the toolbox will be pasted into the design view. If support for another type of database were required, the OleDBConnection component could be used instead. SQLConnection offers some advanced management capabilities and efficiencies over the OleDBConnection component, however, so the OleDBConnection should be used only when necessary. An open database connectivity (ODBC) provider is also available if no OLE-DB provider is available for the data source, but the former ships in a separate assembly that must be downloaded from Microsoft.

The ConnectionString property from the Properties window will offer the developer the option of selecting previous connections that have been configured on the workstation or the opportunity to create a new connection. For this example, a new connection will be created, as shown in Figure 15-4.

click to expand
Figure 15-4: Selecting a new connection for the ConnectionString property of the SQLConnection component

The Data Link Properties window will open after you select <New Connection…> from the ConnectionString property setting. Almost all of the possible settings that could be represented in an ADO.NET connection string may be established using the Data Link Properties window. The Data Link Properties window is a common window used by Visual Studio anytime you configure an ADO connection string. For the Events web service, the database server hosted on the server named AMD1700 and the database named ASPNETServices will be utilized, as shown in Figure 15-5.

click to expand
Figure 15-5: Setting a new data link for the Events web service

The name of the SQLConnection component will be changed to ServicesDBConn from the default SQLConnection1 so that is has a user-friendly name. After the SQLConnection is configured and created, it may be used anywhere within the web service, and it will not have to be created again. The Events class inherits from System.Web.Services.WebService, which provides the class many of the web-oriented classes and functions required to interact with HTTP communication. Listing 15-2 shows the source code generated by Visual Studio .NET for the class Events.

Listing 15-2: Source Code of Class Events after SQLConnection Component Added and Configured

start example
 /// <summary> /// Summary description for Events. /// </summary> public class Events : System.Web.Services.WebService {      public Events()      {           //CODEGEN: This call is required by the            //ASP.NET Web Services Designer           InitializeComponent();      }      private System.Data.SqlClient.SqlConnection ServicesDBConn;      #region Component Designer generated code            //Required by the Web Services Designer      private IContainer components = null;                      /// <summary>      /// Required method for Designer support - do not modify      /// the contents of this method with the code editor.      /// </summary>      private void InitializeComponent()      {           this.ServicesDBConn = new                               System.Data.SqlClient.SqlConnection();           //           // ServicesDBConn           //           this.ServicesDBConn.ConnectionString =            "data source=amd1700;initial catalog=ASPNETServices;" +           "integrated security=SSPI;persist security info=False;" +           "workstation id=AMD1700;packet size=4096";      }      /// <summary>      /// Clean up any resources being used.      /// </summary>      protected override void Dispose( bool disposing )      {           if(disposing && components != null)           {                components.Dispose();           }           base.Dispose(disposing);      }            #endregion }
end example

The use of the Visual Studio .NET Component Designer on web services components is not obligatory in terms of using the web service controls. The controls can also be added to a given web service by declaring and constructing them in the Codebehind file, as with any other variable or class. For example, a SQLConnection object instance could also have been created and initialized in the constructor for the Events class. The code in Listing 15-3 demonstrates the creation and use of a local instance of the SQLConnection object without using the Visual Studio .NET Component Designer and the SQLConnection component from the toolbox.

Listing 15-3 Using SQLConnection Object without the Designer and Obtaining Connection String from the web.config File

start example
 public class Events : System.Web.Services.WebService {      //locals to class      private System.Data.SqlClient.SqlConnection myConn;      public Events()      {           //CODEGEN: This call is required by the            //ASP.NET Web Services Designer           InitializeComponent();           System.Configuration.AppSettingsReader                myAppSettings =                new System.Configuration.AppSettingsReader();           //get the connection string from web.config           string sConnect =                ((string)                (myAppSettings.GetValue                ("ProductionDB.ConnectionString",                typeof(string))));           //make the DB connection         myConn = new System.Data.SqlClient.SqlConnection(sConnect);      }      #region Component Designer generated code            //Required by the Web Services Designer      private IContainer components = null;                      /// <summary>      /// Required method for Designer support - do not modify      /// the contents of this method with the code editor.      /// </summary>      private void InitializeComponent()      {      }      /// <summary>      /// Clean up any resources being used.      /// </summary>      protected override void Dispose( bool disposing )      {           if(disposing && components != null)           {                components.Dispose();           }           base.Dispose(disposing);       }            #endregion }
end example

In Listing 15-3, the myConn instance is declared local to the Events class. The connection string is obtained from the web.config file and used as a constructor for the myConn instance. After the myConn instance is created in the Events constructor, myConn may be used elsewhere throughout the class as needed.

Reading Application Settings from web.config

The web.config file is a great place to obtain initialization data specific to a web application deployment. This enables a developer to produce a solution that obtains arguments that pertain to the specific deployment without making a code change for other deployments. Using the AppSettingsReader class, data may be read from the <appSettings> section of the web.config file. The web.config file that contains the database connection string that Listing 15-3 obtained in the Events constructor is shown in Listing 15-4.

Listing 15-4: web.config File With <appSettings> Element That Contains Database Connection String

start example
  <?xml version="1.0" encoding="utf-8" ?> <configuration>      <system.web>     <compilation defaultLanguage="c#" debug="true"/>     <customErrors mode="RemoteOnly" /> </system.web>  <appSettings>     <add key="ProductionDB.ConnectionString"           value="data source=amd1700;                  initial catalog=ASPNETServices;                  integrated security=SSPI;                  persist security info=False;                  workstation id=AMD1700;                  packet size=4096"       />   </appSettings> </configuration>
end example

The Visual Studio .NET Component Designer also has a mechanism that uses the appSetings element of the web.config file. If the Properties window for an existing connection component that is hosted on the design view of a given web service were accessed, the ConnectionString setting could be configured as a property set using DynamicProperties, as shown in Figure 15-6.

click to expand
Figure 15-6: Connection component properties using DynamicProperties to obtain ConnectionString

By default, the ConnectionString property is not enabled to use DynamicProperties. The specific property must be mapped to a key in the web.config file. The key is an attribute named key located in an add element subordinate to the appSettings element, as seen in Listing 15-4. Clicking the … button in the ConnectionString property under the DynamicProperties will open a dialog box where the developer can choose a key, as shown in Figure 15-7.

click to expand
Figure 15-7: Mapping the ConnectionString property to a key in the configuration file

The Data Adaptor Component

After the data connection has been established, the web service knows what data source it will communicate with and what credentials need to be supplied to the data source. Next, the web service must send a request to the data source to get the data. ADO.NET offers another component for this purpose, called a data adaptor. A version of the data adaptor for SQL Server 2000 uses the SQL Server .NET provider called SQLDataAdaptor. OledbDataAdaptor, the version for OLE-DB, is available for legacy versions of SQL Server or other databases that do not have a specific provider. The data adaptor may be created, set, and used as any other class in ADO.NET. ASP.NET provides a component in the toolbox that may be used instead, if the developer wishes. In the Visual Studio .NET Component Designer, the data adaptor component may be pasted on the design view of the web service and configured via the Properties window.

When the data adaptor component is pasted on the design view of a web service, the Data Adaptor Configuration Wizard opens, inviting the programmer to configure the component instance. The Data Adaptor Configuration Wizard may be dismissed and the properties may be set manually if desired.

Here’s how to use the Data Adaptor Configuration Wizard:

  1. In the opening screen, click Next to start the effort of gaining information about setting up the instance of the data adaptor component pasted on the web service.

  2. In the Choose Your Data Connection screen as shown in Figure 15-8, you can select from the drop-down combo box a data connection that has already been configured for the project. If you click the New Connection button to configure a new connection, the same Data Link Properties window shown in Figure 15-5 will open and you can configure a new connection. In this example, a previously configured connection will be chosen.

    click to expand
    Figure 15-8: Data Adaptor Configuration Wizard—Choose Your Data Connection

  3. After you select the data connection, click the Next button and the wizard will prompt you for the means whereby data will be requested from the data source, as shown in Figure 15-9, in the Choose A Query Type screen.

    click to expand
    Figure 15-9: Data Adaptor Configuration Wizard—Choose a Query Type

    Choose Use SQL Statements and the wizard will generate a set of command objects (using either SQLCommand or OledbCommand classes, depending on the respective connection class being utilized) in the InitializeComponent function of the web service class. The command objects will be set with SQL commands that use aliases for each field name. Referring the alias name in the command object instance, values may be set in the command object to represent the value for a given field.

    Choose either Create New Stored Procedures or Use Existing Stored Procedures and the wizard will ask for more information about the data tables so that the stored procedures may be built or mapped, respectively.

  4. For this example, choose Use SQL Statements.

  5. Click the Next button to continue, and the wizard will open a Generate The SQL Statements screen. Here you’ll type in a Select SQL command for the dataset that the adaptor should use as a model dataset to construct the SQL statements, as shown in Figure 15-10. The SQLDataAdaptor and the OledbDataAdaptor both support an interface for executing Select, Insert, Delete, and Update SQL statements. The wizard generates the SQL commands for the data manipulation commands that are to be set in the data adaptor. The wizard prompts for this Select SQL statement to produce the command text that will be used in the respective Select, Insert, Delete, and Update SQL commands that will be set in the respective SQL commands for the data adaptor.

    click to expand
    Figure 15-10: Data Adaptor Configuration Wizard—Generate The SQL Statements

  6. After typing the Select SQL statement select * from tblEvents in the box, click the Next button to see the View Wizard Results confirmation screen, as shown in Figure 15-11. This screen describes what will be performed on the web service code. If the wizard had difficulty parsing the SQL statement that was entered in the previous step, this confirmation would not show all of the possible SQL comments shown in Figure 15-11. The developer can click the Back button and revise the SQL command that was entered or even choose to have stored procedures created in the database server.

    click to expand
    Figure 15-11: Data Adaptor Configuration Wizard—View Wizard Results

In this example, the data adaptor was named SQLDataAdaptor1, since the Visual Studio .NET Component Designer provides this name as a default name for any SQLDataAdaptor component being pasted in the design view. This name can be changed at any time, however, and the associated wizard-generated code in the InitializeComponent subroutine of the web service will automatically be updated by theVisual Studio .NET Component Designer if the Name property in the Properties window is edited. In this example, the SQLDataAdaptor name was changed to EventsAdaptor using the name property of the Properties window.

The SQLCommand objects generated by the Data Adaptor Configuration Wizard were named SQLSelectCommand1, SQLDeleteCommand1, SQLInsertCommand1, and SQLUpdateCommand1. To make them more appropriate to their context, the names for the command objects were changed to SelectEvent, DeleteEvent, InsertEvent, and UpdateEvent, respectively. The Properties window for the SQLDataAdaptor was used for this purpose by editing the name property found subordinate to the Dynamic Properties of each specific command object. Listing 15-5 shows the code generated by the designer for the EventsAdaptor data adaptor and the ServicesDBConn data connection object.

Listing 15-5: Initialization Code Generated by the VS Designer for a Data Adaptor and a Data Connection

start example
 private void InitializeComponent() {      System.Configuration.AppSettingsReader       configurationAppSettings = new       System.Configuration.AppSettingsReader();          this.ServicesDBConn = new System.Data.SqlClient.SqlConnection();    this.EventsAdaptor = new System.Data.SqlClient.SqlDataAdapter();    this.SelectEvent = new System.Data.SqlClient.SqlCommand();    this.InsertEvent = new System.Data.SqlClient.SqlCommand();    this.UpdateEvent = new System.Data.SqlClient.SqlCommand();    this.DeleteEvent = new System.Data.SqlClient.SqlCommand();      //      // ServicesDBConn      //       this.ServicesDBConn.ConnectionString =                          ((string)(configurationAppSettings.GetValue              ("ServicesDBConn.ConnectionString", typeof(string))));      //      // EventsAdaptor      //      this.EventsAdaptor.DeleteCommand = this.DeleteEvent;      this.EventsAdaptor.InsertCommand = this.InsertEvent;      this.EventsAdaptor.SelectCommand = this.SelectEvent;
end example

Listing 15-5 features part of the subroutine InitializeComponent, demonstrating the SQLCommand components that were created by the Visual Studio .NET Component Designer after they were renamed. After the AppSettingsReader class was created to get the application settings form the web.config file, the connection, data adaptor, and command classes are created. After the connection class is initialized with the connection string obtained from the web.config file, the data adaptor class has each of the SQLCommand object instances assigned to their respective command property. For example, the DeleteEvent command instance is assigned to the DeleteCommand property of the SQLDataAdaptor instance named EventsAdaptor.

The Visual Studio .NET Component Designer generated a considerably large amount of code for setting the SQL command text and parameters to each of their respective command object instances, which is not shown in Listing 15-5. The designer also identified each field in the dataset with an alias in the SQL command. The aliases were set as parameters in the command object. Listing 15-6 shows the source code setting the SQL command text and the parameters for the InsertEvent command object.

Listing 15-6: Initialization Code Generated by the VS Designer for a InsertEvent SQLCommand Object in Subroutine InitializeComponent();

start example
 // // InsertEvent // this.InsertEvent.CommandText = "INSERT INTO tblEvent" +             "(Name, StartDate, Description) " +            "VALUES (@Name, @StartDate, @Description); "+            "SELECT Name, StartDate, Description, ID " +            "FROM tblEvent WHERE (ID = @@IDENTITY)"; this.InsertEvent.Connection = this.ServicesDBConn; this.InsertEvent.Parameters.Add(                             new System.Data.SqlClient.SqlParameter              ("@Name", System.Data.SqlDbType.VarChar, 50, "Name")); this.InsertEvent.Parameters.Add(                             new System.Data.SqlClient.SqlParameter                     ("@StartDate", System.Data.SqlDbType.DateTime,                         8, "StartDate")); this.InsertEvent.Parameters.Add(                              new System.Data.SqlClient.SqlParameter                     ("@Description", System.Data.SqlDbType.VarChar,                                                200, "Description"));
end example

Data Reader Class

By observing the aliases that were generated by the Visual Studio .NET Component Designer, code may be written to set the parameters and fill a DataReader object. For example, the Add function of the Events web service uses the InsertEvent command class instance to add a new event. The aliases of the database table field names established in the InsertEvent class initialization are used by the Parameters method to assign a value to the field that the alias represents in the Insert SQL command that the InsertEvent class uses to update the database table. Listing 15-7 shows the Add function.

Listing 15-7: Add Function in Events Web Service

start example
 /// <summary> /// Adds a new event to system /// </summary> [WebMethod] public bool Add() {      System.Data.SqlClient.SqlDataReader myEvent;  try  {   //set state for the command object instance   InsertEvent.Parameters["@Name"].Value =mEvent.Name;   InsertEvent.Parameters["@StartDate"].Value =mEvent.DateTime;   InsertEvent.Parameters["@Description"].Value =mEvent.Description;    //open the connection object   ServicesDBConn.Open();   //run query   myEvent = this.InsertEvent.ExecuteReader();       //must advance to first record   myEvent.Read();      //fill local properties   mEvent.ID =  myEvent.GetInt32(3);   //shut down record   myEvent.Close();  }  catch(System.Exception Err )  {   //log error   this.LogMessage(Err.ToString() , true);      //rethrow for client consumption   throw Err;  }   //success if we get this far   return true; }
end example

A class instance of the SQLDataReader was created to access the data returned from the SQLCommand class instance InsertEvent. Because InsertEvent was set as a property of the SQLDataAdaptor EventsAdaptor, and has an instance of the connection object servicesDBConn, InsertEvent can return data to the SQLDataReader object instance myEvent. A local instance of anEvent named mEvent is used to hold the current state of the event for the Events web service. Listing 15-8 shows the source for class anEvent.

Listing 15-8: Source Code for Class anEvent

start example
 /// <summary> /// a single event /// </summary> public class anEvent {      private long CurrentID;      private string CurrentName;      private string CurrentDescription;      private DateTime CurrentDateTime;      public anEvent()      {      }      /// <summary>      /// ID for opened event      /// </summary>      public long ID      {           get           {                return CurrentID;           }           set           {                CurrentID = value;           }      }      /// <summary>      /// Date and time of actual event      /// </summary>      public DateTime DateTime      {           get           {                return CurrentDateTime;           }           set           {                CurrentDateTime = value;           }      }      /// <summary>      /// description of event      /// </summary>      public string Description      {           get           {                return CurrentDescription;           }           set           {                CurrentDescription = value;           }      }      /// <summary>      /// Name for opened event      /// </summary>      public string Name      {           get           {                return CurrentName;           }           set           {                CurrentName = value;           }      } }
end example

As shown in Listing 15-8, class anEvent simply holds the data that makes an Event. The web service Events reads and writes the values of an event to and from the database data source so a local instance of anEvent was declared for the class Events and created in the Events constructor.

When the Add function in Listing 15-7 sets the parameters for the Name, Date, and Description, it uses the respective property values for the anEvents instance mEvent. The properties for mEvent are set in the Events web service either from a consumer’s input or from the database values for the Event that might be loaded in the web service at any given moment. Once the parameters for the InsertEvent command are set, the connection is opened, and the command is executed and the results are read into the myEvent instance using the ExecuteReader command of the InsertEvent SQLCommand object. The Read command of the SQLDataReader object advances the dataset to the next row, which happens to be the first row on a freshly opened dataset. If myEvent is read without advancing to the first row, an error would be raised by ADO.NET. The local instance of anEvent is updated with the new ID since the database generates the ID for any given anEvent in the system.

Many programmers familiar with ADO versions previous to ADO.NET may be horrified by the use of the ordinal position of the ID field being referenced to obtain the value of the ID for the mEvent instance. The ordinal value of any field should not be used to refer to a value in a recordset. The SQLDataReader is very much like an ADO recordset. If the database table were updated with the addition of a new column, the ADO recordset might start pulling the wrong field value depending on where in the table definition the new column was added. In ADO.NET, however, this is not a problem, since the ordinal position is defined in terms of the data adaptor instance. The data adaptor provides the layer of abstraction from the data layer so that the programmer may refer to the ordinal position if he or she chooses to do so without fear that database table changes will break the software, as he or she would if the code were abstracted properly using named fields in legacy ADO.

Event Log Component

All the database interaction code in Listing 15-7 is inside the Try section of a Try .. Catch block. If an exception scenario occurs, the Catch block is executed. The System.Exception class instance is passed as an argument to the Catch function, and it should have information about the error that occurred in the Try block. In Listing 15-7, the System.Exception class instance is serialized into a string using the ToString function. The ToString function is a common function that is found among many classes, since the function is inherited from the object class. The string representation of the error message is passed to the LogMessage function, which writes the error to the Application Log in the Event Viewer, and then the error is rethrown so that the consuming application can catch the error.

The LogMessage function is designed so that any information may be written to the Application log of the host server. The Application log also supports a means for identifying the type of message that is written to the log. The LogMessage function writes messages that are type error or type information depending on the value of the Error parameter that is passed. If the Error parameter is true, LogMessage identifies the message in the Application log as an error; otherwise, the message is information. Listing 15-9 shows the code for the LogMessage function.

Listing 15-9: LogMessage Function of the Events Class

start example
 /// <summary> /// logs messages to event log /// in: string that contains message of error ///          or information that ought to be logged ///           ///     out: returns true if successful write, ///          rethrows the error if failure occurs /// </summary> /// [WebMethod] public bool LogMessage(string Message, bool Error) {      System.Diagnostics.EventLogEntryType MessageType;      try      {           //determine the type of message           if (Error )           {                MessageType =                     System.Diagnostics.EventLogEntryType.Error;           }           else           {                MessageType =                System.Diagnostics.EventLogEntryType.Information;           }                                          //make the write           this.Log.WriteEntry(Message, MessageType);      }      catch (System.Exception eLogWrite)      {           //nothing else left to do except throw the raw error           throw eLogWrite;      }                     //we have success if we get to this line      return true; }
end example

The object instance named Log represents the application log for the host server. The Visual Studio .NET Component Designer toolbox provides a component that represents any log in the host server Event Viewer. Simply paste the control onto the design view of the web service and the properties for the log may be set to establish the log on the host that messages should be written to using the instance of the component. Of all the possible logs that could be utilized, the Application log is probably the best choice for writing messages to, since it was designed for application information logging.

start sidebar
Logging Status and Errors

In all web services, status and errors should always be logged on the local host server. Quite often, web projects seem to be produced without adequate error handling code or diagnostic information about what the code is doing. When the application begins to fail in production, and the error condition cannot be duplicated in a development environment, the inclination often seems to be to allow a developer access to the production environment to diagnose and debug the code in production. However, the application should never be diagnosed in a production environment, and because developers can examine messages written to the Application log and easy ways of writing the information to the Application log exist, there is no reason for a developer to take such measures at diagnosing the failure. Allowing a developer access to a production environment should be considered a huge failure of the application and is easily preventable with good error handling and diagnostic logging.

end sidebar




IIS 6(c) The Complete Reference
IIS 6: The Complete Reference
ISBN: 0072224959
EAN: 2147483647
Year: 2005
Pages: 193

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net