IDeliveryProtocol Interface

Provides a framework for developing a custom delivery protocol, which can be used by one or more delivery channels. A delivery protocol is used to create a notification message and route it to an external delivery system for delivery.

Namespace: Microsoft.SqlServer.NotificationServices
Assembly: Microsoft.SqlServer.NotificationServices (in microsoft.sqlserver.notificationservices.dll)

Syntax

'Declaration
Public Interface IDeliveryProtocol
public interface IDeliveryProtocol
public interface class IDeliveryProtocol
public interface IDeliveryProtocol
public interface IDeliveryProtocol

Remarks

This interface provides a framework for developing a custom delivery protocol. To create a custom delivery protocol, you must create a class that implements this interface and then implement the interface's methods as appropriate for your application.

The IDeliveryProtocol interface provides the following methods:

  • Initialize allows the delivery protocol to be initialized by the distributor prior to running.

  • DeliverNotification allows the distributor to pass formatted notification data to the delivery protocol so that it can create the notification message and route it to the external delivery system. This method is called once for each notification message that must be created and delivered.

  • Flush allows the distributor to request that the delivery protocol complete any pending deliveries.

  • Close allows the distributor to make the delivery protocol release any resources it is using and prepare it for shutdown.

The sequence of calls begins with Initialize, followed by a series of DeliverNotification calls, one for each message to be sent. Flush can be called before or after any of the DeliverNotification calls (but never in parallel with a DeliverNotification call). Close is the last method in the sequence to be called. After Close has returned, DeliverNotification and Flush is not called again, unless the calling sequence is started over, with a new call to Initialize.

The methods on a single delivery protocol instance are called by a single thread, so accesses to instance data do not need to be thread-safe. Multiple protocol instances might possibly be called on multiple threads, so accesses to shared class-wide data must be thread safe.

Note

The distributor does not enforce any time-outs on the IDeliveryProtocol methods. The delivery protocol classes are considered to be trusted, tested code. If any of the methods stop responding, then the distributor thread that calls them stops responding. If this happens on enough threads, distributor operation might halt.

Note

The IHttpProtocolProvider interface is offered to speed development of HTTP-based delivery protocols, because these protocols are commonly candidates for custom development. The IDeliveryProtocol interface is to be used for custom delivery protocols that implement other protocols, or for HTTP-based delivery protocols that require more flexibility than IHttpProtocolProvider provides.

For more information, see Developing a Custom Delivery Protocol.

Example

The following examples show how an interface declaration to help you get started with new custom delivery protocols, a sample delivery protocol that uses a stored procedure to process notification data, and sample application definition file (ADF) and instance configuration file (ICF) code for declaring and using the custom delivery protocol.

Use the following interface declaration to start developing your custom delivery protocol.

public interface IDeliveryProtocol
{
    void Initialize(
            StringDictionary channelArgs,
            Boolean multicast,
            NotificationStatusCallback nsc);
    void DeliverNotification(
            NotificationHeaders[] headersList,
            String body);
    void Flush();
    void Close();
}

In the following code example, the delivery channel sends notifications to a stored procedure in a Microsoft SQL Server database:

using System;
using System.Collections;
using System.Collections.Specialized;
using System.Data;
using System.Data.SqlClient;
using System.Diagnostics;
using System.Text;
using Microsoft.SqlServer.NotificationServices;

namespace AdventureWorks.Notifications.MyDeliveryProtocol
{
    // Create a class for the delivery protocol
    public class StoredProcProtocol : IDeliveryProtocol
    {
        private bool multicast = false;
        private NotificationStatusCallback 
            notificationStatusCallback = null;
        private string server = null;
        private string database = null;
        private string storedProc = null;
        private string appName = null;
        private int commandTimeout = 0;
        private string connectionString = null;

        public StoredProcProtocol()
        {
            // Add constructor logic here if required.
        }

        // Implement the IDeliveryProtocol.Initialize method.
        public void Initialize(
            StringDictionary channelArgs,
            bool multicast,
            NotificationStatusCallback notificationStatusCallback )
        {
            this.multicast = multicast;
            this.notificationStatusCallback = 
                notificationStatusCallback;

            // This delivery protocol requires five arguments:
            // The Database Engine instance to connect to.
            // The database to use.
            // The stored procedure to receive notifications.
            // The name of the application making the connection.
            // The time-out period for the command.
            if (5 == channelArgs.Count)
            {
                this.server = channelArgs["Server"];
                this.database = channelArgs["Database"];
                this.storedProc = channelArgs["storedProc"];
                this.appName = channelArgs["AppName"];
                this.commandTimeout = int.Parse(
                    channelArgs["CommandTimeout"]);
            }
            else
            {
                throw new ArgumentException(
                    "Inadequate number of arguments supplied.");
            }

            // Validate the values of the arguments here if needed.

            // Build the connection string.
            StringBuilder connectBuilder = new StringBuilder();
            connectBuilder.AppendFormat("Data Source={0};", server);
            connectBuilder.AppendFormat(
                "Initial Catalog={0};", database);
            connectBuilder.AppendFormat("Integrated Security=true;");
            connectBuilder.AppendFormat("App={0}", appName);

            connectionString = connectBuilder.ToString();
        }

        // Implement the IDeliveryProtocol.DeliverNotification method.
        public void DeliverNotification(
            NotificationHeaders[] notificationHeaders,
            string body)
        {
            bool successfulDelivery = false;
            Exception failureException = null;

            try
            {
                // Get a connection to SQL Server.
                using (SqlConnection databaseConnection = 
                    new SqlConnection(connectionString))
                {
                    // Prepare the SqlCommand object.
                    SqlCommand databaseCommand = 
                        databaseConnection.CreateCommand();
                    databaseCommand.CommandTimeout = commandTimeout;
                    databaseCommand.CommandType = 
                        CommandType.StoredProcedure;
                    databaseCommand.CommandText = storedProc;

                    // Call the stored procedure for each recipient.
                    foreach(NotificationHeaders header 
                        in notificationHeaders)
                    {
                        // Reset the parameters.
                        databaseCommand.Parameters.Clear();

                        // Set the procedure parameters.
                        if (null != header.ProtocolFields)
                        {
                            foreach (string protocolField in 
                                header.ProtocolFields.Keys)
                            {
                              databaseCommand.Parameters.AddWithValue(
                                String.Format("@" + protocolField), 
                                header.ProtocolFields[protocolField]);
                            }
                        }
                        // Execute the command.
                        databaseConnection.Open();
                        databaseCommand.ExecuteNonQuery();
                        databaseCommand.Connection.Close();
                        successfulDelivery = true;
                    }
                }
            }
            catch (Exception ex)
            {
                failureException = ex;
                // Handle any exceptions here; for instance,
                // write exception information to the event log.
            }
            finally
            {
                SendStatus(notificationHeaders, successfulDelivery, 
                    body, failureException);
            }
        }

        // Build a statusInfo message, create a NotificationStatus 
        // object, and call the notificationStatusCallback delegate.
        private void SendStatus(
            NotificationHeaders[] notificationHeaders,
            bool successfulDelivery,
            string body,
            Exception failureException)
        {
            if (null != notificationStatusCallback)
            {
                ArrayList statusList = new ArrayList(
                    notificationHeaders.Length);
                string statusInfo;

                // Set some notification status parameters
                // based on delivery success or failure.
                string notificationText;
                if (null == failureException)
                {
                    statusInfo = "";
                    notificationText = "";
                }
                else
                {
                    statusInfo = failureException.Message;
                    notificationText = body;
                }

                object timeStamp = DateTime.UtcNow;

                // Create a NotificationStatus object for
                // each notification and add it to an array.
                for (int i = 0; i < notificationHeaders.Length; i++)
                {
                    NotificationHeaders notificationHeader = 
                        notificationHeaders[i];
                    statusList.Add(new NotificationStatus(
                        notificationHeader.NotificationState, 
                        successfulDelivery, statusInfo, 
                        notificationText, timeStamp));
                }

                // Pass the array of NotificationStatus objects
                // to the NotificationStatusCallback delegate.
                notificationStatusCallback(
                    (NotificationStatus[])statusList.ToArray(
                        typeof(NotificationStatus)));
            }
        }

        // Implement the IDeliveryProtocol.Flush method.
        public void Flush()
        {
            // Notification delivery by this protocol is synchronous 
            // and completes in the DeliverNotification call. There 
            // is nothing for Flush to do.
        }

        // Implement the IDeliveryProtocol.Close method.
        public void Close()
        {
            // No resources are held beyond the sychronous call 
            // to DeliverNotification. There are no resources for 
            // Close to release.
        }
    }
}

If you have any trouble using this custom delivery protocol, use the Windows event viewer to view delivery failure information, and use SQL Server Profiler to view the command text sent to SQL Server by the custom delivery protocol.

You also must define application and instance properties for the custom delivery protocol. Here's an example of how to define this custom delivery protocol in an instance configure file (ICF):

<Protocols>
        <Protocol>
            <ProtocolName>MyStoredProcProtocol</ProtocolName>
            <ClassName>AdventureWorks.Notifications.MyDeliveryProtocol.StoredProcProtocol</ClassName>
            <AssemblyName>%BaseDirectoryPath%\MyDeliveryProtocol.dll</AssemblyName>
        </Protocol>
</Protocols>

And here's how to define a delivery channel for this custom protocol in the ICF:

<DeliveryChannel>
    <DeliveryChannelName>StoredProcChannel</DeliveryChannelName>
    <ProtocolName>MyStoredProcProtocol</ProtocolName>
    <Arguments>                
        <Argument>
            <Name>Server</Name>
            <Value>%SqlServer%</Value>
        </Argument>
        <Argument>
            <Name>Database</Name>
            <Value>MyTestDB</Value>
        </Argument>
        <Argument>
            <Name>storedProc</Name>
            <Value>dbo.MyFlightSP</Value>
        </Argument>
        <Argument>
            <Name>AppName</Name>
            <Value>Flight</Value>
        </Argument>
        <Argument>
            <Name>CommandTimeout</Name>
            <Value>30</Value>
        </Argument>
    </Arguments>
</DeliveryChannel>

And here's how to define a the notification class protocol fields for this custom delivery protocol:

<Protocol>
    <ProtocolName>MyStoredProcProtocol</ProtocolName>
    <Fields>
        <Field>
            <FieldName>LeavingFrom</FieldName>
            <FieldReference>LeavingFrom</FieldReference>
        </Field>
        <Field>
            <FieldName>GoingTo</FieldName>
            <FieldReference>GoingTo</FieldReference>
        </Field>
        <Field>
            <FieldName>Carrier</FieldName>
            <FieldReference>Carrier</FieldReference>
        </Field>
        <Field>
            <FieldName>Price</FieldName>
            <FieldReference>Price</FieldReference>
        </Field>
        <Field>
            <FieldName>Conditions</FieldName>
            <FieldReference>Conditions</FieldReference>
        </Field>
    </Fields>
</Protocol>

Platforms

Development Platforms

For a list of the supported platforms, see Hardware and Software Requirements for Installing SQL Server 2005.

Target Platforms

For a list of the supported platforms, see Hardware and Software Requirements for Installing SQL Server 2005.

See Also

Reference

IDeliveryProtocol Members
Microsoft.SqlServer.NotificationServices Namespace