Posted by Federico

May 31, 2012

12:13 pm

Leave Reply

Visualizing ExactTarget data with C# and WPF

Summary

In this exercise, we’ll visit the very basic steps to pull some data from an ExactTarget account and generate a pie chart to analyze the results. We’ll use C# to write the application, WCF (Windows Communication Foundation) to connect to the ExactTarget API and WPF (Windows Presentation Foundation) to display the pie chart. More specifically, we’ll study the volume of e-mails created over the past 12 months.

Requirements

  • Basic knowledge of C#, WCF, WPF
  • Visual Studio 2008 or 2010
  • WPF Toolkit

Project

The first step is to configure your Visual Studio project to connect to the ExactTarget API. For this exercise, we’ll use WCF, but for older .NET versions, you can also use WSE (Web Services Enhancements).

ExactTarget provides three instances and you need to use the one your account uses. In order to determine what instance your account uses, log in to ExactTarget using your credentials as you normally do and view the URL in your browser window. The URL should look like:

  • S1 instance:
    http://members.exacttarget.com
  • S4 instance:
    http://members.s4.exacttarget.com
  • S6 instance:
    http://members.s6.exacttarget.com

Once you have determined what the instance you need is, go to: VS > Solution Explorer > right-click your WPF project > Add Service Reference…

  • S1 Instance:
    https://webservice.exacttarget.com/etframework.wsdl
  • S4 Instance:
    https://webservice.s4.exacttarget.com/etframework.wsdl
  • S6 Instance:
    https://webservice.s6.exacttarget.com/etframework.wsdl

Enter the instance web address, click Go and wait a few seconds until VS pulls the service definition. Then enter ExactTarget on the namespace field. This is the namespace that VS will use to generate all ExactTarget classes. You can use any name you want, but for simplicity we’ll just use ExactTarget. Finally, click Ok.

You’re now able to use the ExactTarget API in your code.

Next, you need to add a reference to the DataVisualization namespace in order to use the charting classes provided by the WPF toolkit. Go to: VS > Solution Explorer > right-click your WPF project > Add Reference… > Assemblies > Extensions

and add a reference to System.Windows.Controls.DataVisualization.Toolkit.

You’re now ready to use WPF charts in your application.

ExactTarget

With the ExactTarget API you can do a lot of things, like create e-mails or subscribers; and even though, in terms of code, they don’t differ much from each other, we’ll focus here on polling the service for some data to feed our charts. This involves three steps:

  • Creating and configuring an ExactTarget SOAP client instance.
  • Building the request to get the data you need
  • Retrieving the results from the service
  • private List<Email> GetEmails()
  • {
  •   List<Email> emails = null;
  •   // Create and configure the SOAP client ——
  •   // Create the SOAP Client. There are 4 more
  •   // constructors that allow you to customize the
  •   // client in different ways.
  •   var client = new SoapClient();
  •   try
  •   {
  •     // Using the default constructor, the securi-
  •     // ty mode is set to Transport. We need to
  •     // change it in order to manually specify
  •     // account credentials. All other default va-
  •     // lues are Ok. By allowing each user to use
  •     // their own credentials you can control
  •     // their access to data based on their permi-
  •     // ssions.
  •     var binding = client.Endpoint.Binding
  •            as BasicHttpBinding;
  •     binding.Security.Mode = BasicHttpSecurityMode
  •           .TransportWithMessageCredential;
  •     // Set the user credentials
  •     client.ClientCredentials.UserName.UserName =
  •                  “[your username]”;
  •     client.ClientCredentials.UserName.Password =
  •                  “[your password]”;
  •     // Create and configure the request ——–
  •     // Create a new request
  •     var request = new RetrieveRequest();
  •     // Set object type. For a complete list of
  •     // objects, please refer to
  •     // http://docs.code.exacttarget.com/020_Web_Service_Guide/Objects
  •     // Each object documentation also lists all
  •     // members.
  •     request.ObjectType = “Email”;
  •     // From the object type selected, select only
  •     // those properties you want to include in
  •     // your query. All other properties not spe-
  •     // cified will not be populated and contain
  •     // the corresponding default value to each
  •     // type. Depending on your needs, you might
  •     // not need to bring all properties.
  •     request.Properties = new string[] { “Name”,
  •      “CreatedDate”,“ModifiedDate”, “Subject” };
  •     // Optionally, you can specify a filter to
  •     // narrow down your results. In this case we
  •     // need only those e-mails that were created
  •     // over the last year starting today. In
  •     // other words, we need all e-mails where the
  •     // “CreatedDate” is greater than or equal to
  •     // 1 year ago from today.
  •     var filter = new SimpleFilterPart();
  •     filter.Property = “CreatedDate”;
  •     filter.SimpleOperator =
  •         SimpleOperators.greaterThanOrEqual;
  •     filter.DateValue = new DateTime[]
  •         { DateTime.Now.AddYears(-1) };
  •     request.Filter = filter;
  •     // Execute the request and get the results –
  •     // Define the variables the call will use to
  •     // store the results
  •     APIObject[] results;
  •     string requestId;
  •     // Execute the request
  •     var response = client.Retrieve(request,
  •             out requestId, out results);
  •     if (response == “OK”)
  •     {
  •       // if the response is OK, create a new
  •       // list of the results using the appro-
  •       // priate type. The results collection
  •       // contains objects of the type specified
  •       // in the request
  •       emails = results.Cast<Email>().ToList();
  •     }
  •     // close the client
  •     client.Close();
  •   }
  •   catch (Exception ex)
  •   {
  •     // Exceptions related to the SOAP client that
  •     // you get here are CommunicationException
  •     // and TimeoutException. Abort the operation
  •     // and rethrow the expection
  •     client.Abort();
  •     throw ex;
  •   }
  •   // return the results
  •   return emails;
  • }

Charts

As for the charting end of the flow, it involves the following steps:

  • Define and configure the chart
  • Using the raw data returned by the service, generate the actual results we need to place in the chart
  • Feed the chart with the processed data

In order to display a chart in our application, we need to define it in our XAML code of the application window. Make sure to add the corresponding namespace reference to the window attributes in order to insert the chart definition.

  • <Window x:Class=”ExactTargetWpf.MainWindow”
  •     xmlns=”http://schemas.microsoft.com/winfx/2006/xaml/presentation”
  •     xmlns:x=”http://schemas.microsoft.com/winfx/2006/xaml”
  •     xmlns:charting=”clr-namespace:System.Windows.Controls.DataVisualization.Charting;assembly=System.Windows.Controls.DataVisualization.Toolkit”
  •     Title=”MainWindow” Height=”380″ Width=”500″>
  •   <charting:Chart Name=”PieChart”>
  •     <charting:Chart.Series>
  •       <!–
  •       ItemsSource is bound to the data context
  •       in order to let WPF generate all items
  •       in the collection for you.
  •       DependentValueBinding refers to the nume-
  •       ric property of our objects that is re-
  •       presented in the chart. Since each of our
  •       objects is a KeyValuePair<string, int>,
  •       we tell the chart to get the numeric va-
  •       lue from the Value property of the
  •       KeyValuePair object.
  •       IndependentValueBinding refers to the
  •       property that is used as a label of each
  •       pie slice. So we should use Key. Unfortu-
  •       nately, the default style of the chart
  •       doesn’t have good usability, leaving us
  •       with just the color to tie a month to its
  •       value. By not specifying a property, WPF
  •       calls the ToString() method of the object
  •       which in the case of KeyValuePair, in-
  •       cludes the key and the value.
  •       –>
  •       <charting:PieSeries
  •       ItemsSource=”{Binding}”
  •       DependentValueBinding=”{Binding Value}”
  •       IndependentValueBinding=”{Binding}”>
  •       </charting:PieSeries>
  •     </charting:Chart.Series>
  •   </charting:Chart>
  • </Window>

The series type defines the chart type. The available series types are: AreaSeries, BarSeries, BubbleSeries, ColumnSeries, LineSeries, PieSeries and ScatteredSeries. The important elements are the binding attributes since they tell the chart which of the object properties to use to create the pie slices and to use as labels. This allows you to use the object of your choice when feeding data to the chart.

The collection we get from the service is just raw data that only includes a collection of e-mail objects. To make real use of this data, we need to process this collection in order to get something we can feed to the chart. In this exercise, we want to generate a chart with the volume of e-mails sent on each month of the past 12 months. In other words, we need to generate 12 objects, one for each month, where each object encapsulates the name of the month and the volume of e-mails for that particular month. We could create our own class for this, but for simplicity we’ll use KeyValuePair<string, int>.

  • private List<KeyValuePair<string, int>>
  •     GetMonthlyData(List<Email> emails)
  • {
  •   // create a new list of key-value pairs. Each
  •   // pair contains the name of a month and the
  •   // number of emails created on that month.
  •   var items = new List<KeyValuePair<string,
  •                    int>>();
  •   // get the number of the current month
  •   var thisMonth = DateTime.Now.Month;
  •   for (var i = 0; i < 12; i++)
  •   {
  •     // in order to get each month number, ending
  •     // with the current month, use the following
  •     // formula. This combines all emails from the
  •     // current month of this year and those from
  •     // last year after today’s date in one bu-
  •     // cket, but for this exercise that’s all
  •     // right.
  •     var month = 1 + (thisMonth + i) % 12;
  •     // for each month [1 to 12] create a new
  •     // pair. Then get the name of the month using
  •     // the current culture info and count the
  •     // number of emails that were created in that
  •     // month
  •     items.Add(new KeyValuePair<string, int>(
  •       CultureInfo.CurrentCulture
  •         .DateTimeFormat.GetMonthName(month),
  •       emails.Count(em =>
  •         em.CreatedDate.Month == month)));
  •   }
  •   return items;
  • }

The last step is to connect all 3 pieces together in one method. This is where we actually feed the pie chart.

  • private void Initialize()
  • {
  •   try
  •   {
  •     // Poll the server using the predefined query
  •     var emails = this.GetEmails();
  •     // Generate the chart data off of the email
  •     // collection returned from the ExactTarget
  •     // service and feed the chart object with it.
  •     this.PieChart.DataContext =
  •            this.GetMonthlyData(emails);
  •     // Based on the query we run, set the chart
  •     // labels accordingly
  •     this.PieChart.Title = “E-mails per month”;
  •     this.PieChart.LegendTitle = “Last 12 months”;
  •   }
  •   catch (Exception ex)
  •   {
  •     // Display an error message
  •     MessageBox.Show(ex.Message,
  •             ex.GetType().Name,
  •             MessageBoxButton.OK,
  •             MessageBoxImage.Error);
  •   }
  • }

What next?

There are several aspects that you may consider for making this code more robust and efficient. Some of these are:

  • Making asynchronous calls in order to keep the UI responsive while the service responds and the chart is generated.
  • Separation of steps into dynamic and more flexible methods when putting together a call to the service. This way you can generate queries dynamically based on user input.
  • As previously stated, the default usability of the chart control leaves a lot of room for improvement, but unfortunately, adding all of the desired usability enhancements requires redefining the template of the chart, legend and tooltip controls, as well as some other WPF tricks, quickly going beyond the scope of this exercise. Depending on your requirements, you might even consider developing your own pie chart control from scratch.

External links

Leave a Reply

Your email address will not be published. Required fields are marked *

Explore Posts By Category

Archives

Archives

Want to know more?

Contact us