C# 如何使用C查询Tableaus GraphQL#
(还有人问。) 我正在尝试使用C#通过GraphQL连接并查询Tableau。我已经尝试了一段时间了,在发送查询时总是碰壁 我正在创建一个httpWebRequest,以使用以下方法发送查询 传入的变量是:C# 如何使用C查询Tableaus GraphQL#,c#,graphql,httpwebrequest,tableau-api,C#,Graphql,Httpwebrequest,Tableau Api,(还有人问。) 我正在尝试使用C#通过GraphQL连接并查询Tableau。我已经尝试了一段时间了,在发送查询时总是碰壁 我正在创建一个httpWebRequest,以使用以下方法发送查询 传入的变量是: string Url = MyTableauServer/api/metadata/graphql string Method = "POST" string payload = """query TestName1 { datab
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;
}
}
仔细检查您是否从正确的Tableau站点请求令牌(如果您有多个站点)。用户有哪些权限?您可以在请求令牌的位置共享代码吗?这是一个很好的观点。我必须针对站点进行身份验证,但是Tableau的GraphQL文档没有指定如何将查询限制为仅针对站点。在获取令牌时的身份验证部分,您可以在XML请求主体中定义站点。我知道这一部分,但是当我查询GraphQLAPI时,没有办法指定我要查询的站点,所以我很容易从RESTAPI获得身份验证密钥。我根据“Site1”进行身份验证,现在我有一个只针对Site1进行身份验证的密钥。使用此键访问GraphQLAPI,无法告诉API我正在查询Site1。我假设它可能试图对所有站点运行查询,但失败了,因为我只针对Site1进行了身份验证。我知道请求令牌是可行的,因为我有一个已经运行了几年的整个自动化系统,现在通过REST API查询所有站点,但我会在编辑中添加代码。