[英]How do you query Tableaus GraphQL using C#
(Question also asked here .) (问题也在这里问。)
I am attempting to connect to and query Tableau via GraphQL using C#.我正在尝试使用 C# 通过 GraphQL 连接和查询 Tableau。 I have been trying for a while now, and keep hitting a wall when sending the query.我已经尝试了一段时间,并且在发送查询时不断撞墙。
I am creating a httpWebRequest to send the query using the following method.我正在创建一个 httpWebRequest 以使用以下方法发送查询。
The variables passed in are:传入的变量是:
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 } } } } }"""
The AuthToken is obtained by querying the REST API. AuthToken 是通过查询 REST API 获得的。 The authenticated user has permissions to be able to perform any and all of the required actions.经过身份验证的用户有权执行任何和所有必需的操作。
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;
}
}
The most recent error i am getting is "The underlying connection was closed: The connection was closed unexpectedly."我最近收到的错误是“基础连接已关闭:连接意外关闭。” being returned at the following line:在以下行返回:
HttpWebResponse wr = wc.GetResponse() as HttpWebResponse;
Any ideas or assistance would be greatly appreciated任何想法或帮助将不胜感激
------------------------------------------------------------ -------------------------------------------------- ----------
Update:更新:
using Fiddler i get the following response.使用 Fiddler 我得到以下响应。
{
"timestamp": 1600939439846,
"status": 401,
"error": "Unauthorized",
"message": "User is not authenticated",
"path": "/relationship-service-war/graphql"
}
I am authenticated, Authentication token is valid and is passed in the headers.我已通过身份验证,身份验证令牌有效并在标头中传递。
------------------------------------------------------ -------------------------------------------------- ----
Update:更新:
Adding the code for authentication.添加验证码。 logged in user is a server admin so no issues with access rights.登录用户是服务器管理员,因此访问权限没有问题。
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;
}
}
Double check if you're requesting a token from the correct Tableau Site (if you have multiple sites).仔细检查您是否从正确的 Tableau 站点(如果您有多个站点)请求令牌。 Also what permissions does user have and can you share the code where you request the token?此外,用户拥有哪些权限,您可以在请求令牌的地方共享代码吗?
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.