Sunday, October 28, 2012

WCF Endpoints and Bindings Explained

My last post was about netTcpBinding in WCF and I thought it's better if I write a more detailed post about endpoints and bindings in WCF.

Windows Communication Foundation gives us the ability to transmit messages using different transport protocols such as HTTP, TCP, and MSMQ (Microsoft Message Queuing) etc. As you already know all communication with a WCF service occurs through the endpoints of the service.

There can be more than one endpoint for a service (Multiple Endpoints) and these endpoints provide client's the access to functionality offered by a WCF service. These endpoints has many properties and there are three main attributes which are commonly known as ABC’s or Where, How and What of a service. The ABCs make up an endpoint in WCF and these endpoints need to be set for both the service and the client.
  1. Address : The address uniquely identifies the endpoint and tells where the service is located.
  2. Binding : The binding specifies how to communicate with the endpoint. This includes the transport protocol, encoding to use for the messages and the necessary security requirements.
  3. Contract : The contract outlines what functionality the endpoint exposes to the client.
Today I will be focusing on the Address and the Binding attributes, because these two are very important.

For demonstration purposes I have created a WCF Service Application which is “WCFBindingApp” and I am using the IIS and not the Visual Studio Development server to host my service. Because we can’t use TCP bindings for services which are hosted in Visual Studio Development Server.

IService1

using System.ServiceModel;

namespace WcfBindingApp
{
    [ServiceContract]
    public interface IService1
    {
        [OperationContract]
        string MyMethod(string s);
    }
}

Service1.svc.cs

namespace WcfBindingApp
{
    public class Service1 : IService1
    {
        public string MyMethod(string s)
        {
            return string.Format("Message From Client: {0}", s);
        }
    }
}

Address of a Endpoint

When we define endpoints for a service, there are numerous options for specifying the address. You can either use the IP address or the host name along with the port number. If no port number is mentioned the default port for the protocol is used. There are two techniques we can use to specify the address.

   1.   Specify the absolute address for each endpoint

<services>        
    <service name="WcfBindingApp.Service1">        
        <endpoint address="http://localhost/WcfBindingApp/Service.svc" binding="basicHttpBinding" contract="WcfBindingApp.IService1" ></endpoint>
    </service>
</services>

    2.   Specify a base address and then specify relative address for each endpoint

<services>
    <service name="WcfBindingApp.Service1">
        <endpoint address="" binding="basicHttpBinding" contract="WcfBindingApp.IService1" ></endpoint>
        <endpoint address="secure" binding="wsHttpBinding" contract="WcfBindingApp.IService1" ></endpoint>
        <endpoint address="tcp" binding="netTcpBinding" contract="WcfBindingApp.IService1" ></endpoint>

        <host>
            <baseAddresses>
                <add baseAddress="http://localhost/WcfBindingApp/Service.svc" />
            </baseAddresses>
        </host>
    </service>
</services>

since I am using the IIS here, I can write it even in this way without mentioning the base address (the base address will be determined by the IIS virtual directory). This will also work.

<services> 
    <!-- base address determined by IIS virtual directory -->        
    <service name="WcfBindingApp.Service1">
        <endpoint address="" binding="basicHttpBinding" contract="WcfBindingApp.IService1" ></endpoint>
        <endpoint address="secure" binding="wsHttpBinding" contract="WcfBindingApp.IService1" ></endpoint>
        <endpoint address="tcp" binding="netTcpBinding" contract="WcfBindingApp.IService1" ></endpoint>
    </service>
</services>

There are couple of things you should know when you define the address.

 1. If the address is empty, you can omit the address attribute. This means the endpoint will be exposed via the base address.

<endpoint address="" binding="basicHttpBinding" contract="WcfBindingApp.IService1" ></endpoint>

is same as,

<endpoint binding="basicHttpBinding" contract="WcfBindingApp.IService1" ></endpoint>

2. As I said before, when hosting in IIS, you don’t have to mention the base address. The base HTTP address is determined by the IIS virtual directory and WCF  ignores any base addresses we may specify.

3. When hosting in IIS, if you do specify an absolute address for a particular endpoint, it must start with the base address corresponding to the virtual directory.

4. When exposing multiple endpoints with same contract and with different bindings, each endpoint address must be unique.

5. If multiple endpoints share the same binding with different contracts, you can use the same address across those endpoints.

6. You can have multiple base addresses for each service, but only one for each protocol.

Bindings of a Endpoint

The bindings is the key element of the WCF architecture. There are variety types of bindings available to use when defining endpoints.

Built-In Bindings

Within the Windows Communication Foundation programming model, bindings are represented by the “System.ServiceModel.Channels.Binding” class. All binding classes must derive from this base class. Following image shows all the binding classes which are available with WCF.

image
Binding class which are available out of the box
In here I will only list the features of most used ones.
  • basicHttpBinding
    • Designed for scenarios where interoperability is of utmost importance.
    • HTTP for the transport and text for the message encoding.
    • Message version is SOAP 1.1.
    • Capable of using transport or message security, but both are disabled by default.
  • wsHttpBinding
    • Designed for interoperability while incorporating with richer Web services protocols for security, reliable messaging, and transaction.
    • Message version is SOAP 1.2.
    • This is default binding in WCF.
  • wsDualHttpBinding
    • Supports all the feature of wsHttpBinding.
    • Used for Duplex service contracts.
    • Supports bidirectional communication.
  • netTCPBinding
    • Unlike the ws* specific bindings, the various "Net" bindings were not designed for interoperability. This explains why the binding names are prefixed with "Net"
    • Assumes you have the Microsoft .NET Framework 3.0 installed on both sides.
    • NetTcpBinding uses TCP for the transport, binary for the message encoding, and SOAP 1.2 for the message version.
    • Enables transport security by default and can support transactions if enabled.
  • netPeerTCPBinding
    • Provides a secure binding for peer-to-peer network applications.
  • netNamedPipeBinding
    • Provides a secure and reliable binding that is optimized for on-machine communication.
    • Can be only used over a single WCF computer.
  • netMSMQBinding
    • Represents a queued binding that is suitable for cross-machine communication.
  • CustomBinding
Transport Protocols

Not like XML web services, WCF supports any protocol to communicate with the clients.
  • Http : This is the chosen protocol for communicating over the web and gives the ability to integrate the service with open standards exposing services to clients on many plaforms.
  • TCP : Fast binary format protocol. A great performance in WCF-WCF communication.
  • Named pipes : Fast communication between the client and the server which runs on the same machine. Works only in WCF-WCF.
  • MSMQ : Microsoft Message Queue allows queuing of messages and very useful in disconnected communications between the client the server. Used when client wants to enqueue a message that a service can consume later.
  • Custom Protocols : Can define own protocols.
Now let’s move in to see how binding is specified in the configuration file. The basic way is as follows.

<services>
    <service name="WcfBindingApp.Service1">
        <endpoint address="" binding="basicHttpBinding" contract="WcfBindingApp.IService1" ></endpoint>
        <endpoint address="secure" binding="wsHttpBinding" contract="WcfBindingApp.IService1"></endpoint>
        <endpoint address="tcp" binding="netTcpBinding" contract="WcfBindingApp.IService1" ></endpoint>

        <host>
            <baseAddresses>
                <add baseAddress="http://localhost/WcfBindingApp/Service.svc" />
            </baseAddresses>
        </host>
    </service>
</services>

Here I have specified three bindings. And default settings are applied to each bindings. Now let’s say you want to change the wsHttpBinding defaults and apply new settings. You can easily do it this way.

<services>
    <service name="WcfBindingApp.Service1">
        <endpoint address="" binding="basicHttpBinding" contract="WcfBindingApp.IService1" ></endpoint>
        <endpoint address="secure" binding="wsHttpBinding" bindingConfiguration="mybinding" contract="WcfBindingApp.IService1"></endpoint>
        <endpoint address="tcp" binding="netTcpBinding" contract="WcfBindingApp.IService1" ></endpoint>

        <host>
            <baseAddresses>
                <add baseAddress="http://localhost/WcfBindingApp/Service.svc" />
            </baseAddresses>
        </host>
    </service>
</services>

<bindings>
    <wsHttpBinding>
        <binding name="mybinding"></binding> <!--you can change the default settings here-->
    </wsHttpBinding>
</bindings>

I am changing the wsHttpBinding settings and giving it a name. And in my endpoint I am giving it as endpoints binding congfiguration.

Now I have a client console application which will communicate with service using different bindings.

using System;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                using (svcTest.Service1Client client = new svcTest.Service1Client("BasicHttpBinding_IService1"))
                {
                    Console.WriteLine(client.MyMethod("basicHttpBinding"));
                }
                using (svcTest.Service1Client client = new svcTest.Service1Client("WSHttpBinding_IService1"))
                {
                    Console.WriteLine(client.MyMethod("wsHttpBinding"));
                }
                using (svcTest.Service1Client client = new svcTest.Service1Client("nettcpbinding_iservice1"))
                {
                    Console.WriteLine(client.MyMethod("netTcpBinding"));
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("Error:{0}", ex);
            }
            Console.ReadLine();
        }
    }
}

And when I run this I will get the output as follows.
Output
Hope you all got a good understanding about endpoints and different bindings I have explained. Appreciating your feedback.

Happy Coding.

Regards,
Jaliya

Thursday, October 25, 2012

netTcpBinding in WCF Services

I have wrote some posts about WCF and today I am going to write about configuring netTcpBinding in WCF as it needs some little extra work. WCF or Windows Communication Foundation is one my favorite areas in the .NET Framework and bindings is one of the things which I like the most in WCF.

Before starting off, there is a small check list to be checked. First is, you can’t configure netTcpBinding, if your service is running in the Visual Studio Development Server. The reason for this is Visual Studio Development Server only supports HTTP. And to configure netTcpBinding, we need IIS 7. This will not work on previous versions of IIS. 

Next you have to make sure “Windows Communication Foundation Non-HTTP Activation” is available. Since I am using Windows Server 2008R2 operating system, it’s on the .NET Framework 3.5.1 Features under Features in Server Manager.
image
WCF Activation
Final item in the check list is, you have to make sure following service is started.
image
Net.Tcp Listener Adapter
Now I have created a WCF Service Application and I have changed the project properties as follows.
image
Use Local IIS Web Server
Then you can click on "Create Virtual Directory" button or if you run the project for the first time without clicking it, you will be asked before Visual Studio creating a directory for you. After creating the virtual directory you can see it under “Default Web Site” in the IIS.
image
Default Web Site in IIS
Now you have to do two configurations in IIS. Right click on “Default Web Site” and click on "Edit Bindings". Check whether net.tcp type is there and if not add it.
image
Default Web Site : Site Bindings
Now right click on created Virtual Directory and select "Advanced Settings" under Manage Applications. In Enabled Protocols add net.tcp.
Untitled
Advanced Settings of created virtual directory
Now you are done with the IIS configurations. Now modify the web.config as follows.
<system.serviceModel>
    <behaviors>      
        <serviceBehaviors>
            <behavior> 
                <!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
                <serviceMetadata httpGetEnabled="false"/>
                <!-- To receive exception details in faults for debugging purposes, set the value below to true.  Set to false before deployment to avoid disclosing exception information -->
                <serviceDebug includeExceptionDetailInFaults="false"/>
            </behavior>
        </serviceBehaviors>
    </behaviors>

    <services>
        <service name="WcfApplication.Service1">
            <endpoint address="" contract="WcfApplication.IService1" binding="netTcpBinding"></endpoint>
            <endpoint address="mex" contract="IMetadataExchange" binding="mexTcpBinding"></endpoint>

            <host>
                <baseAddresses>
                    <add baseAddress="http://localhost/WcfApplication/Service.svc" />
                </baseAddresses>
            </host>
        </service>
    </services>

    <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>


And that's it. In here please note that I have put httpGetEnabled to "false". Now right click on the Service and view it in your browser. You will get something like this.
Untitled
Created Service
Now you can test this service by adding a service reference from another project or by using WCF Test Client which is located at,
"C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\WcfTestClient.exe".
In here I am using the WCF Test Client.
image
WCF Test Client
image
WCF Test Client : Testing the service
That’s all. Hope this helps.

Happy Coding.

Regards,
Jaliya

Friday, October 19, 2012

Installing Windows Phone SDK 7.1 on Windows Server 2008R2

When you try to install Windows Phone SDK 7.1 on a Windows Server 2008/2008R2 operating system, you will be smashed with this error which says “Windows 7 or Windows Vista is required”.
Untitled
"Windows 7 or Windows Vista is required"
If you are thinking about trying this installation again in Windows 7 or Windows Vista machine, you don’t have to. There is a simple workaround for this.
  1. Download the web installer. I am saving the installer in a folder named “Windows Mobile” in my D: drive.
  2. Extract the installer by running this command vm_web2.exe /x
    Untitled2
    extracting the installer
  3. You will be asked to select a extract folder. Give a extraction folder and extract.
  4. Open the extracted folder and open the “baseline.dat” file in a text editor.
  5. Find the section named “[gencomp7788]”.
  6. Change following values.
    • InstallOnLHS value from “1” to “0”
    • InstallOnWin7Server value from “1” to “0”
  7. Save and close “baseline.dat”.
  8. Run setup.exe /web from the extracted folder. By specifying "web" parameter we are forcing setup to download the packages it needs to install.
    Untitled3
    running the setup
That’s all. Now you are done.
Untitled1
Starting the installation
Hope this helps.

Happy Coding.

Regards,
Jaliya

Thursday, October 18, 2012

ASP.NET GridView Inside an Update Panel

Sometimes there can be situations where you need to update a gridview inside a ASP.NET page without refreshing the page. This is how you can do it with Update Panel in AJAX Extensions. In here I have two gridviews and one is inside the Update Panel and the other one is out of the Update Panel. I am using the timer control to update the gridview in a timely manner.

I am pasting the source code below.

_Default.aspx

<%@ Page Title="Home Page" Language="C#" MasterPageFile="~/Site.master" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="GridViewUpdate._Default" %>
<asp:Content ID="HeaderContent" runat="server" ContentPlaceHolderID="HeadContent">
</asp:Content>
<asp:Content ID="BodyContent" runat="server" ContentPlaceHolderID="MainContent">
<asp:ScriptManager ID="ScriptManager1" runat="server"/>

    <asp:Timer runat="server" ID="tmrTimer" Interval="30000" OnTick="tmrTimer_Tick" />

    <asp:UpdatePanel runat="server" id="pnlUpdate">
        <Triggers>
            <asp:AsyncPostBackTrigger ControlID="tmrTimer" eventname="Tick"/>
        </Triggers>
        <ContentTemplate>
            <h2>Inside Update Panel</h2>
            <asp:GridView ID="gvCustomer" runat="server" 
                AutoGenerateColumns="False" GridLines="Both" AllowPaging="True">
                <Columns>
                    <asp:TemplateField HeaderText="Customer ID">
                        <ItemTemplate>
                            <asp:Label runat="server" ID="lblCustomerID" Text='<%# Eval("CUSTOMER_ID") %>' />
                        </ItemTemplate>                   
                    </asp:TemplateField>
                    
                    <asp:TemplateField HeaderText="First Name">
                        <ItemTemplate>                            
                            <asp:Label runat="server" ID="lblFirstName" Text='<%# Eval("CUSTOMER_FIRST_NAME") %>' />
                       </ItemTemplate>                    
                    </asp:TemplateField>

                    <asp:TemplateField HeaderText="Last Name">
                        <ItemTemplate>
                            <asp:Label runat="server" ID="lblLastName" Text='<%# Eval("CUSTOMER_LAST_NAME") %>' />
                        </ItemTemplate>
                    </asp:TemplateField>
                </Columns>
            </asp:GridView>
        </ContentTemplate>
    </asp:UpdatePanel>        

    <h2>Not Inside Update Panel</h2>
    <asp:GridView ID="gvCustomer1" runat="server" 
         AutoGenerateColumns="False" GridLines="Both" AllowPaging="True">
        <Columns>
            <asp:TemplateField HeaderText="Customer ID">
                <ItemTemplate>
                    <asp:Label runat="server" ID="lblCustomerID" Text='<%# Eval("CUSTOMER_ID") %>' />
                </ItemTemplate>
            </asp:TemplateField>

            <asp:TemplateField HeaderText="First Name">
                <ItemTemplate>  
                  <asp:Label runat="server" ID="lblFirstName" Text='<%# Eval("CUSTOMER_FIRST_NAME") %>' />
                </ItemTemplate>
            </asp:TemplateField>

            <asp:TemplateField HeaderText="Last Name">
                <ItemTemplate>
                    <asp:Label runat="server" ID="lblLastName" Text='<%# Eval("CUSTOMER_LAST_NAME") %>' />
                </ItemTemplate>
            </asp:TemplateField>
        </Columns>    
    </asp:GridView>
</asp:Content>

In here Timer Interval is "30000" and that is in miliseconds. So the interval between every "Tick" event is 30 seconds.

_Default.aspx.cs
using System;

namespace GridViewUpdate
{
    public partial class _Default : System.Web.UI.Page
    {
        //my custom dbconnection class
        private readonly DbConnection _dbConnection = new DbConnection();

        protected void Page_Load(object sender, EventArgs e)
        {
            if (!IsPostBack)
            {
                Bind();
            }
        }

        private void Bind()
        {
            const string query = "SELECT CUSTOMER_ID,CUSTOMER_FIRST_NAME,CUSTOMER_LAST_NAME FROM CUSTOMER";

            //my custom method that is in the dbconnection class that 
            //accepts a string query and returns a dataset
            gvCustomer.DataSource = _dbConnection.SelectDataSet(query);
            gvCustomer.DataBind();

            //my custom method that is in the dbconnection class that 
            //accepts a string query and returns a dataset
            gvCustomer1.DataSource = _dbConnection.SelectDataSet(query);
            gvCustomer1.DataBind();
        }

        protected void tmrTimer_Tick(object sender, EventArgs e)
        {
            Bind();
        }
    }
}
That’s it. Now I am running it and I can see something like this.
Before
Before
And then I am adding a new record to my customer table, but I am not refreshing my page. Then I can see something like this in few seconds.
After
After
You can see that, only the gridview which is inside the Update Panel is updated. Other is not. So hope this helps.

Happy Coding.

Regards,
Jaliya

Wednesday, October 17, 2012

Retrieve default and available values of Report Parameters using C# : ReportingService2010

I have been playing around with Reporting Services Web service ReportingService2010 for some time and I got really surprised from the things that we can do using this web service. Today I am going to write about retrieving the default and available values of a report parameter using C#. Sometimes back I wrote a post about Accessing Report Server using Report Server Web Service - Microsoft SQL Server 2008R2. So I am not going to write a more detailed post here.

Without much information, I will just paste the code down. Value retrieving part is in bold.
        /// <summary>
        /// pName is the parameter I want to get the default and available values for
        /// </summary>
        /// <param name="pName"></param>
        private void GetDefaultAndAvailableValues(string pName)
        {
            //credentials to connec to the web service
            var userName = "username";
            var password = "password";

            //connecting to web service
            var clientCredentials = new NetworkCredential(userName, password);
            var rs = new ReportingService2010SoapClient();
            if (rs.ClientCredentials != null)
            {
                rs.ClientCredentials.Windows.AllowedImpersonationLevel = TokenImpersonationLevel.Impersonation;
                rs.ClientCredentials.Windows.ClientCredential = clientCredentials;
            }

            //open the connection
            rs.Open();

            var oTrustedUserHeader = new TrustedUserHeader();
            string historyId = null;
            ParameterValue[] values = null;
            DataSourceCredentials[] credentials = null;
            ItemParameter[] itemParameter = null;

            //all the parameters of the report will be filled to out parameter 'itemParameter'
            rs.GetItemParameters(oTrustedUserHeader, "/MyReports/Dev/MyReport", historyId, true, values, credentials, out itemParameter);

            //iterate through parameters
            foreach (ItemParameter ip in itemParameter)
            {
                //check for the parameter I want to get default and available values for
                if (pName == ip.Name)
                {
                    //get default values
                    string[] defValues = ip.DefaultValues;

                    //get valid/available values
                    ValidValue[] validValues = ip.ValidValues;
                    foreach (ValidValue vValue in validValues)
                    {
                        //ValidValue has Label property and Value property
                        //if you check the parameters in report designer, every parameter has Label field and Value field
                        ddlParamValues.Items.Add(new ListItem(vValue.Label,vValue.Value));
                    }
                }
            }
            //close the connection
            rs.Close();
        }

And this is the output I am getting.
Untitled
Output
Hope this helps.

Happy Coding.

Regards,
Jaliya

Wednesday, October 3, 2012

Creating Data-driven Subscription Programmatically using C# – Delivery Extension : Email

In my last post I have mentioned I will write a post about creating Data-driven subscription programmatically and this is it. I am creating this subscription on Microsoft SQL Server 2008R2 using the method   CreateDataDrivenSubscription in ReportService2010 web service. In one of my last posts I wrote about Accessing Report Server using Report Server Web Service.

Reporting Services includes an e-mail delivery extension and a file share delivery extension. In here I will be using Email  Delivery Extension.

Before creating the Data-driven subscription make sure SQL Server Agent service is up and running. That’s because what really happens when you create Data-driven subscription is, there will be job created in SQL Server.
Untitled
SQL Server Agent
Without much information, I am pasting the code down here with all the comments. I have added a service reference to ReportService2010 web service.
using System;
using System.Globalization;
using System.Net;
using System.Security.Principal;
using System.Web.Services.Protocols;
using System.Windows.Forms;
using DataDrivenSubscriptionWebApp.wsReportService;

namespace DataDrivenSubscriptionWebApp
{
    public partial class _Default : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {

        }

        protected void Button1_Click(object sender, EventArgs e)
        {
            CreateDataDrivenSubscription();
        }

        private static void CreateDataDrivenSubscription()
        {
            // connecting to report server web service
            var clientCredentials = new NetworkCredential("administrator", "123@com");
            var rs = new ReportingService2010SoapClient();
            if (rs.ClientCredentials != null)
            {
                rs.ClientCredentials.Windows.AllowedImpersonationLevel = TokenImpersonationLevel.Impersonation;
                rs.ClientCredentials.Windows.ClientCredential = clientCredentials;
            }
            rs.Open();

            var oTrustedUserHeader = new TrustedUserHeader();

            // report which i am creating data-driven subscription for
            const string report = "/My Reports/Reports/Report1";
            const string description = "Programmatic Data Driven Subscription for Email";

            // Set the extension setting as report server email.
            var settings = new ExtensionSettings {Extension = "Report Server Email"};

            // Set the extension parameter values.
            var extensionParams = new ParameterValueOrFieldReference[8];

            var to = new ParameterFieldReference {ParameterName = "TO", FieldAlias = "EMAIL"}; // Data-driven.
            extensionParams[0] = to;

            var replyTo = new ParameterValue {Name = "ReplyTo", Value = "jaliya.udagedara@gmail.com"};
            extensionParams[1] = replyTo;

            var includeReport = new ParameterValue {Name = "IncludeReport", Value = "False"};
            extensionParams[2] = includeReport;

            var renderFormat = new ParameterValue {Name = "RenderFormat", Value = "HTML4.0"};
            extensionParams[3] = renderFormat;

            var priority = new ParameterValue {Name = "Priority", Value = "NORMAL"};
            extensionParams[4] = priority;

            var subject = new ParameterValue {Name = "Subject", Value = "Subsribed Report"};
            extensionParams[5] = subject;

            var comment = new ParameterValue {Name = "Comment", Value = "Here is the link to your report."};
            extensionParams[6] = comment;

            var includeLink = new ParameterValue {Name = "IncludeLink", Value = "True"};
            extensionParams[7] = includeLink;

            settings.ParameterValues = extensionParams;

            // Create the data source for the delivery query.
            var delivery = new DataSource {Name = ""};
            var dataSourceDefinition = new DataSourceDefinition
                                           {
                                               ConnectString = "Data Source=(local);Initial Catalog=SAMPLE_DB",
                                               CredentialRetrieval = CredentialRetrievalEnum.Store,
                                               Enabled = true,
                                               EnabledSpecified = true,
                                               Extension = "SQL",
                                               ImpersonateUserSpecified = false,
                                               UserName = "sa",
                                               Password = "sa"
                                           };
            delivery.Item = dataSourceDefinition;

            // Create the data set for the delivery query.
            var dataSetDefinition = new DataSetDefinition
                                        {
                                            AccentSensitivitySpecified = false,
                                            CaseSensitivitySpecified = false,
                                            KanatypeSensitivitySpecified = false,
                                            WidthSensitivitySpecified = false
                                        };

            var queryDefinition = new QueryDefinition
                                      {
                                          CommandText = "SELECT EMAIL from RECIPIENT",
                                          CommandType = "Text",
                                          Timeout = 45,
                                          TimeoutSpecified = true
                                      };
            dataSetDefinition.Query = queryDefinition;
            var results = new DataSetDefinition();
            var oServerInfoHeader = new ServerInfoHeader();

            bool changed;
            string[] paramNames;
            oServerInfoHeader = rs.PrepareQuery(oTrustedUserHeader, delivery, dataSetDefinition, out results, out changed,
                                                out paramNames);

            var dataRetrieval = new DataRetrievalPlan {DataSet = results, Item = dataSourceDefinition};

            // Set the event type and match data for the delivery.
            const string eventType = "TimedSubscription";
            const string matchData = "<ScheduleDefinition><StartDateTime>2012-10-01T14:00:00-07:00</StartDateTime><WeeklyRecurrence><WeeksInterval>1</WeeksInterval><DaysOfWeek><Monday>True</Monday><Tuesday>True</Tuesday><Wednesday>True</Wednesday><Thursday>True</Thursday><Friday>True</Friday></DaysOfWeek></WeeklyRecurrence></ScheduleDefinition>";

            //const string eventType = "SnapshotUpdated";
            //const string matchData = null;

            // Set the report parameter values.
            var parameters = new ParameterValueOrFieldReference[1];

            // i am retrieving value EMAIL from database and I am passing that value as my report parameter value
            var reportparam = new ParameterFieldReference {ParameterName = "ReportParameter1", FieldAlias = "EMAIL"}; // Data-driven.
            
            parameters[0] = reportparam;

            try
            {
                string subscriptionId = "";
                oServerInfoHeader = rs.CreateDataDrivenSubscription(oTrustedUserHeader, report, settings, dataRetrieval,
                                                                    description, eventType, matchData, parameters,
                                                                    out subscriptionId);
            }
            catch (SoapException ex)
            {
                MessageBox.Show(ex.Detail.InnerText.ToString(CultureInfo.InvariantCulture));
            }
            rs.Close();
        }
    }
}
Once you run this, you can see that there is Data-driven subscription created under your report.
Untitled1
Manage Report
Untitled2
Subscription
And you can also see a job created under SQL Server Agent in SQL Server Management Studio.
Untitled4
SQL Server Agent
You can manually start a job in SQL Server Agent by running following command in Management Studio query window.
USE msdb 
EXEC sp_start_job @job_name = '025B869B-BA52-4337-BC8B-DC65383EAC7C' --your job id
Hope this helps.

Happy Coding.

Regards,
Jaliya