1
votes

I am new to API coding and working on a module which signs in to Tableau Server and gets the list of workbooks stored in a site. The code is to be written in C# using the Tableau Rest API.

I was able to sign in to Tableau server successfully using the Rest API. However, I was not able to query the workbooks. Below is my code.

class Program
    {
        static HttpClient client = new HttpClient();


        public static string site_id { get; set;}
        public static string token { get; set; }
        static void Main(string[] args)
        {
            CallWebAPIAsync().Wait();
        }

        static async Task CallWebAPIAsync()
        {
            using (var client = new HttpClient())
            {
                client.Timeout = TimeSpan.FromMilliseconds(Timeout.Infinite);
                client.BaseAddress = new Uri("https://my server url.com");
                client.DefaultRequestHeaders.Accept.Clear();
                client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/xml"));
                client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/octet-stream"));
                SignIn(client);
                Workbooks(client, site_id, token);
            }

            Console.Read();
        }

        public class CustomXmlMediaTypeFormatter : XmlMediaTypeFormatter
        {
            public CustomXmlMediaTypeFormatter()
            {
                UseXmlSerializer = true;
                WriterSettings.OmitXmlDeclaration = false;
            }
        }
        public static tableauCredentialsType SignIn(HttpClient client)
        {
            var name = "Administrator";
            var password = "password";
            var site = "";

            var tableauCredentialsType = new tsRequest()
            {
                Item = new tableauCredentialsType
                {
                    name = name,
                    password = password,
                    site = new siteType() { contentUrl = site }
                }
            };

            var httpContent = new ObjectContent<tsRequest>(tableauCredentialsType, new CustomXmlMediaTypeFormatter());

            var httpResponseMessage = client.PostAsync("/api/3.2/auth/signin", httpContent).Result;

            if (httpResponseMessage.StatusCode != System.Net.HttpStatusCode.OK)
                throw new Exception(string.Format("Unable to login to the server", site, name));

            var responseLogin = httpResponseMessage.Content.ReadAsAsync<tsResponse>(new List<MediaTypeFormatter>() { new CustomXmlMediaTypeFormatter() }).Result;

            var resultTableauCredentialsType = ((tableauCredentialsType)responseLogin.Items[0]);

            site_id = resultTableauCredentialsType.site.id;

            token = resultTableauCredentialsType.token;

            return resultTableauCredentialsType;

        }

        public static IList<workbookType> Workbooks(HttpClient client, string siteid, string auth_token, int pageSize = 100, int pageNumber =1)
        {
            IList<workbookType> results = new List<workbookType>();

            client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("x-tableau-auth", auth_token);
           var query = client.GetAsync(string.Format("/api/3.2/sites/{0}/workbooks", siteid, pageSize, pageNumber)).Result;

            if(query.StatusCode == System.Net.HttpStatusCode.OK)
            {
                var result = query.Content.ReadAsAsync<tsResponse>(new List<MediaTypeFormatter>() { new CustomXmlMediaTypeFormatter() }).Result;

                var pagination = (paginationType)result.Items[0];

                var workbooks = ((workbookListType)result.Items[1]).workbook.AsEnumerable();

                for (int i=2; i < pageNumber; i++)
                {
                    query = client.GetAsync(string.Format("/api/3.2/sites/{0}/workbooks", siteid, pageSize, i)).Result;

                    if(query.StatusCode == System.Net.HttpStatusCode.OK)
                    {
                        result = query.Content.ReadAsAsync<tsResponse>(new List<MediaTypeFormatter>() { new CustomXmlMediaTypeFormatter() }).Result;

                        workbooks = workbooks.Concat(((workbookListType)result.Items[1]).workbook.AsEnumerable());
                    }
                }

                results = workbooks.ToList();
            }

            return results;
        }
    }

When I try to run the Workbooks function in the above code I am getting 401-Unauthorized error. I came to know that I need to pass the X-tableau_auth so that I will have the authentication done while querying for the workbooks. However, I was not able to get that properly.

Can anyone help me with this?

2

2 Answers

0
votes

The header information can be passed using the DefaultRequestHeaders Add method.

You can try something like

client.DefaultRequestHeaders.Add("x-tableau-auth", "tokenvalue");

Also the api parameters is incorrect. You can refer to the API guide provided by Tableau

0
votes

Did you check the Url that you're using to fetch the list of workbooks? I checked with Tableau's API documentation, the Url format looks different, try updating your code

string.Format("/api/{0}/sites/site-id/workbooks", siteid, pageSize, i)

to

string.Format("/api/3.4/sites/{0}/workbooks", siteid)

Here I assumed you're using 3.4 version api.

I'd also recommend using some Rest Clients to test these Apis before you code.