C# Utility to remotely trigger an extract refresh using undocumented REST API - Tableau Version 10

Version 1

    I've spent a number of days trying to trigger an extract refresh via the REST API for Tableau Online (10.1.0). I've read a lot, I've coded a lot, I've sworn a lot.


    How it needs to hang together

    The basic premise is we need to do two things via the undocumented REST api;

    1. Login and get a token
    2. Make the refresh call utilizing the token fetched in Step 1.


    Where I started

    Nick Priestley

    Nick Priestly put together this post nearly 12 months ago - C# Utility to remotely trigger an extract refresh using undocumented REST API which utilizes the runExtractRefreshesOnDatasources endpoint but this comprehensive code example did not work for me.

    According to this KB article, the XML endpoints referenced in this code are no longer supported. This meant I needed to find a new way to Login and get a token.


    Where to next

    I stumbled across this article in Python Tableau’s “Undocumented” API Made Easy with Python | vizibly diffrnt by Mark Jacobson. While I'm not familiar with Python it was easy enough to figure out what was Mark was doing; 1) Encrypting the Password, 2) Logging into the Server. If you'd like to learn more about what's going on under the covers here, jump in and read his blogpost as it explains it in much more detail.

    After I translated the encryption and login code to C#, I was able to replace the existing 'Login' code in the C# example by Nick and it all worked!


    Making it better?

    As part of my reading I came across this postData Source Management through REST API where I learned of a different way to trigger an extract refresh. The 'runExtractRefreshesOnDatasources' endpoint needs a data source ID in order to make the request. That means manually looking up the ID through your browser or other API calls to translate friendly names into backend ID's (this is explained more in the post referenced in this paragraph if you care to learn more).

    The alternative method suggested in this post calls a different endpoint which allows you to pass through a Data Source Name and a Project Name like follows - /clientxml/refresh_extracts/datasources?format=xml&name=MyDataSourceName&project=MyProject. This suited my needs much better, so I went ahead and wired this up.


    Bringing It All Together

    I've stolen re-utilized a lot from Nick's C# Utility example as this should make it easier for people who've used that code to 'upgrade'.

    Please note that I use two libraries / Nuget packages to make my REST requests (RestSharp) and deserialize some JSON (JSON.NET). There's also a couple of references you'll need to add in Visual Studio like System.Numerics, System.Security, System.Web.Extensions off the top of my head.


    Thanks to everyone who contributed to existing examples which helped me get to this point!