首页 > 解决方案 > 如何使用 C# 查询 Tableaus GraphQL

问题描述

(问题也在这里问。)

我正在尝试使用 C# 通过 GraphQL 连接和查询 Tableau。我已经尝试了一段时间,并且在发送查询时一直碰壁。

我正在创建一个 httpWebRequest 以使用以下方法发送查询。

传入的变量有:

string Url = MyTableauServer/api/metadata/graphql

string Method = "POST"

string payload = """query TestName1   {  databaseServersConnection(first: 10)     {    totalCount,    pageInfo{endCursor,hasNextPage,}    nodes      {      connectionType,      __typename,      hostName,      name,      port,      isEmbedded,      tables        {        id,        schema,        name,        columns          {          id,          name          }        }      }    }  }"""

AuthToken 是通过查询 REST API 获得的。经过身份验证的用户有权执行任何和所有必需的操作。

    public static string SendJsonWebRequest(string Url, string Method, string payload, string AuthToken)

    {

      try

      {

        string response;

        //encode the json payload  

        byte[] buf = Encoding.UTF8.GetBytes(Uri.EscapeDataString(payload));

        //set the system to ignore certificate errors because Tableau server has an invalid cert.  

        System.Net.ServicePointManager.ServerCertificateValidationCallback = ((sender, certificate, chain, sslPolicyErrors) => true);

 

        //Create the web request and add the json payload  

        HttpWebRequest wc = WebRequest.CreateHttp(Url) as HttpWebRequest;

        wc.Method = Method;

        wc.PreAuthenticate = true;

        wc.Headers.Add($"X-Tableau-Auth: {AuthToken}, content-type: application/json, accept: application/json");

        wc.ContentLength = buf.Length;

        wc.GetRequestStream().Write(buf, 0, buf.Length);

 

        try

        {

          //Send the web request and parse the response into a string  

//this is as far as i get

          HttpWebResponse wr = wc.GetResponse() as HttpWebResponse;

          Stream receiveStream = wr.GetResponseStream();

          StreamReader readStream = new StreamReader(receiveStream, Encoding.UTF8);

          response = readStream.ReadToEnd();

          receiveStream.Close();

          readStream.Close();

          wr.Close();

        }

        catch (WebException we)

        {

          //Catch failed request and return the response code  

          if (we.Status == WebExceptionStatus.ProtocolError)

          {

            WebResponse resp = we.Response;

            using (StreamReader sr = new StreamReader(resp.GetResponseStream()))

            {

              response = sr.ReadToEnd();

            }

          }

          else

          {

            response = ((HttpWebResponse)we.Response).StatusCode.ToString();

          }

        }

        return response;

      }

      catch (Exception E)

      {

        logger.Trace($"- ERROR - Error in SendWebRequest. System says: {E.Message}");

        return E.Message;

      }

    }

我得到的最新错误是“底层连接已关闭:连接已意外关闭。” 在以下行返回:

HttpWebResponse wr = wc.GetResponse() as HttpWebResponse;

任何想法或帮助将不胜感激

-------------------------------------------------- ----------

更新:

使用 Fiddler 我得到以下响应。

{

  "timestamp": 1600939439846,

  "status": 401,

  "error": "Unauthorized",

  "message": "User is not authenticated",

  "path": "/relationship-service-war/graphql"

}

我已通过身份验证,身份验证令牌有效并在标头中传递。

-------------------------------------------------- ----

更新:

添加验证码。登录用户是服务器管理员,因此访问权限没有问题。

    public static string TabLogIn(string User, string Pass, string ContURL = "")
    {
        string response = "";
        try
        {
            using (XmlWriter loginxml = XmlWriter.Create("signin.xml"))
            {
                loginxml.WriteStartDocument();
                loginxml.WriteStartElement("tsRequest");
                loginxml.WriteStartElement("credentials");
                loginxml.WriteAttributeString("name", User);
                loginxml.WriteAttributeString("password", Pass);
                loginxml.WriteStartElement("site");
                loginxml.WriteAttributeString("contentUrl", ContURL);
                loginxml.WriteEndElement();
                loginxml.WriteEndElement();
                loginxml.WriteEndElement();
                loginxml.WriteEndDocument();
            }
            XElement myxml = XElement.Load("signin.xml");
            string myxmlstring = myxml.ToString();

            //send payload to routine to make the web request  
            string URL = $@"{Enums.Server}/api/{Enums.APIVersion34}/auth/signin";


            //Send the above url, the POST method, and the XML Payload string to create the web request  
            var infotl = SendWebRequest(URL, "POST", myxmlstring);

            response = infotl;
            File.Delete("signin.xml");

            return response;
        }
        catch(Exception E)
        {
            logger.Trace($"- ERROR - Error in TabLogIn. System says: {E.Message}");
            return response;
        }
        finally
        {
            if (File.Exists("signin.xml"))
            {
                File.Delete("signin.xml");
            }
        }
    }

    static string SendWebRequest(string Url, string Method, string payload)
    {
        try
        {
            string response;
            //encode the XML payload  
            byte[] buf = Encoding.UTF8.GetBytes(payload);
            //set the system to ignore certificate errors because Tableau server has an invalid cert.  
            System.Net.ServicePointManager.ServerCertificateValidationCallback = ((sender, certificate, chain, sslPolicyErrors) => true);

            //Create the web request and add the XML payload  
            HttpWebRequest wc = WebRequest.Create(Url) as HttpWebRequest;
            wc.Method = Method;
            wc.ContentType = "text/xml";
            wc.ContentLength = buf.Length;
            wc.GetRequestStream().Write(buf, 0, buf.Length);

            try
            {
                //Send the web request and parse the response into a string  
                HttpWebResponse wr = wc.GetResponse() as HttpWebResponse;
                Stream receiveStream = wr.GetResponseStream();
                StreamReader readStream = new StreamReader(receiveStream, Encoding.UTF8);
                response = readStream.ReadToEnd();
                receiveStream.Close();
                readStream.Close();
                wr.Close();
            }
            catch (WebException we)
            {
                //Catch failed request and return the response code  
                response = ((HttpWebResponse)we.Response).StatusCode.ToString();
            }
            return response;
        }
        catch(Exception E)
        {
            logger.Trace($"- ERROR - Error in SendWebRequest. System says: {E.Message}");
            return E.Message;
        }
    }

标签: c#graphqlhttpwebrequesttableau-api

解决方案


仔细检查您是否从正确的 Tableau 站点请求令牌(如果您有多个站点)。用户还有什么权限,您可以在请求令牌的地方共享代码吗?


推荐阅读