I'm communicating with my server with the following code,
private void Save_Click(object sender, RoutedEventArgs e)
{
var request = HttpWebRequest.Create(url) as HttpWebRequest;
request.Method = "POST";
request.BeginGetResponse(new AsyncCallback(GotResponse), request);
}
private void GotResponse(IAsyncResult asynchronousResult)
{
try
{
string data;
HttpWebRequest myrequest = (HttpWebRequest)asynchronousResult.AsyncState;
using (HttpWebResponse response = (HttpWebResponse)myrequest.EndGetResponse(asynchronousResult))
{
System.IO.Stream responseStream = response.GetResponseStream();
using (var reader = new System.IO.StreamReader(responseStream))
{
data = reader.ReadToEnd();
}
responseStream.Close();
}
this.Dispatcher.BeginInvoke(() =>
{
MessageBox.Show(data);
});
}
catch (Exception e)
{
var we = e.InnerException as WebException;
if (we != null)
{
var resp = we.Response as HttpWebResponse;
var code = resp.StatusCode;
this.Dispatcher.BeginInvoke(() =>
{
MessageBox.Show("Message :" + we.Message + " Status : " + we.Status);
});
}
else
throw;
}
}
I'm giving date and amount as my input value,it is url encoded. If all my data's are valid then everything works fine. And so my server will give the data as
{
"code":0,
"message":"Success",
"data":{
"date":xxxx,
"amount":123
}
}
But in case if give an invalid value,(For eg: abcd for 'amount'), then my server would reply as
{
"code":2,
"message":"Invalid value passed"
}
In this case, after Executing the line
using (HttpWebResponse response = (HttpWebResponse)myrequest.EndGetResponse(asynchronousResult))
It jumps to catch, and it display
Message:The remote server returned an error:NotFound. Status:UnKnown Error
Required Solution: It should fetch the result as it did in the previous case.
What sholud i do to fix it?
Well presumably the HTTP status code is 404. You're already accessing the response in your error code though - all you need to do is try to parse it as JSON, just as you are in the success case, instead of using we.Message to show an error message. You should probably be ready for the content to either be empty or not include valid JSON though, and only do this on specific status codes that you expect to still return JSON.
Related
(Question also asked here.)
I am attempting to connect to and query Tableau via GraphQL using C#. 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.
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. 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.
{
"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). Also what permissions does user have and can you share the code where you request the token?
I'm attempting to make an image scraper, now for some pages the image was not specified so i wanted to parse my output based on the status code i receive when accessing the page but when i attempt to pare my status code i get an exception instead of the status code if the page was not found, any idea why this happends?
if (gameinfo != null)
if (!string.IsNullOrEmpty(gameinfo.image_uri))
try
{
using (System.Net.WebClient client = new System.Net.WebClient())
{
// Build Uri and attempt to fetch a response.
UriBuilder uribuild = new UriBuilder(gameinfo.image_uri);
WebRequest request = WebRequest.Create(uribuild.Uri);
HttpWebResponse response = request.GetResponse() as HttpWebResponse;
switch (response.StatusCode)
{
// Page found and valid entry.
case HttpStatusCode.OK:
using (Stream stream = client.OpenRead(uribuild.Uri))
{
Console.WriteLine(String.Format("Downloading {0}", uribuild.Uri));
System.Drawing.Bitmap bitmap = new System.Drawing.Bitmap(stream);
bitmap.Save(System.IO.Path.Combine(rom_root, String.Format("{0}.jpg", file_name.Substring(2).Split('.').First())));
}
break;
// Unspecified status codes.
default:
Console.WriteLine("Unspecified status code found, aborting...");
break;
}
}
} catch(System.Net.WebException ex)
{
// Should be moved to switch with HttpStatusCode.NotFound ^
Console.WriteLine("Image page not found.");
}
That's just how the GetResponse() implementation is. If the response is anything other than a success, a WebException is thrown.
I agree, I find it a bit odd - it would be nice if it was optional behaviour at least.
Thankfully, you can read the status code from the WebException which is being thrown:
....
catch (WebException e)
{
using (WebResponse response = e.Response)
{
HttpWebResponse httpResponse = (HttpWebResponse) response;
var statusCode = httpResponse.StatusCode;
// Do stuff with the statusCode
}
}
This code works, but may be only as performant as a 112-year-old alcoholic:
try
{
const string uri = "http://localhost:28642/api/departments/Count";
var webRequest = (HttpWebRequest)WebRequest.Create(uri);
webRequest.Method = "GET";
var webResponse = (HttpWebResponse)webRequest.GetResponse();
if ((webResponse.StatusCode == HttpStatusCode.OK) && (webResponse.ContentLength > 0))
{
var reader = new StreamReader(webResponse.GetResponseStream());
string s = reader.ReadToEnd();
MessageBox.Show(string.Format("Content from HttpWebRequest is {0}", s));
}
else
{
MessageBox.Show(string.Format("Status code == {0}", webResponse.StatusCode));
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
The Web API REST method being called simply returns an int. Is this StreamReader jazz overkill for getting that one simple value? If so, what is the preferred method?
Jon Skeet is on the case - WebClient.DownloadString is easy as (eating) pie:
var client = new WebClient();
MessageBox.Show(client.DownloadString("http://localhost:28642/api/departments/Count"));
IOW, the code I originally showed is definitely overkill for retrieving a scalar value.
UPDATE
Better yet:
private void buttonGetDeptCount2_Click(object sender, EventArgs e)
{
MessageBox.Show(GetScalarVal("http://localhost:28642/api/departments/Count"));
}
private string GetScalarVal(string uri)
{
var client = new WebClient();
return client.DownloadString(uri);
}
I need to send some data from windows phone 7 to php page through POST method, I have the following code at wp7 side
public void SendPost()
{
var url = "http://localhost/HelpFello/profile.php";
// Create the web request object
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(url);
webRequest.Method = "POST";
webRequest.ContentType = "application/x-www-form-urlencoded";
// Start the request
webRequest.BeginGetRequestStream(new AsyncCallback(GetRequestStreamCallback), webRequest);
MessageBox.Show("data sent");
}
void GetRequestStreamCallback(IAsyncResult asynchronousResult)
{
HttpWebRequest webRequest = (HttpWebRequest)asynchronousResult.AsyncState;
// End the stream request operation
Stream postStream = webRequest.EndGetRequestStream(asynchronousResult);
// Create the post data
// Demo POST data
string postData = "user_id=3&name=danish&email_id=mdsiddiquiufo&password=12345&phone_Number=0213&about_me=IRuel2&rating=5";
byte[] byteArray = Encoding.UTF8.GetBytes(postData);
// Add the post data to the web request
postStream.Write(byteArray, 0, byteArray.Length);
postStream.Close();
// Start the web request
webRequest.BeginGetResponse(new AsyncCallback(GetResponseCallback), webRequest);
}
void GetResponseCallback(IAsyncResult asynchronousResult)
{
try
{
HttpWebRequest webRequest = (HttpWebRequest)asynchronousResult.AsyncState;
HttpWebResponse response;
// End the get response operation
response = (HttpWebResponse)webRequest.EndGetResponse(asynchronousResult);
Stream streamResponse = response.GetResponseStream();
StreamReader streamReader = new StreamReader(streamResponse);
var Response = streamReader.ReadToEnd();
streamResponse.Close();
streamReader.Close();
response.Close();
}
catch (WebException e)
{
MessageBox.Show(e.ToString());
}
}
and following on my localhost, to send the data to database
<?php
require_once("constants.php");
$user_id = $_POST['user_id'];
$name = $_POST['name'];
$email_id = $_POST['email_id'];
$password = $_POST['password'];
$phone_number = $_POST['phone_number'];
$about_me = $_POST['about_me'];
$rating = $_POST['rating'];
$query="INSERT INTO profile(User_ID,Name,Email_ID,password,Phone_Number,About_Me,Rating) VALUES ({$user_id},'{$name}','{$email_id}','{$password}',{$phone_number}, '{$about_me}' , {$rating})";
mysql_query($query,$connection);
mysql_close($connection);
?>
When I run the code I have no errors it means code is working fine, but no data is inserted in the database.
I think there is a better way than HttpWebRequest. That is WebClient. You can change the method there and append data like you do in get string. key=value&key2=value then when you invoke that request and get the response try debugging and getting the output from VS or if that is difficult simply assign he string to a textblock in the code. You will get to know if that page has been ever executed or not.
A sample code :
WebClient wc = new WebClient();
wc.UploadStringCompleted += new UploadStringCompletedEventHandler(wc_UploadStringCompleted);
wc.Headers["Content-Type"] = "application/x-www-form-urlencoded";
wc.Encoding = Encoding.UTF8;
Parameters prms = new Parameters();
prms.AddPair("email", email);
prms.AddPair("password", password);
wc.UploadStringAsync(new Uri(loginUrl), "POST", prms.FormPostData(), null);
private void wc_UploadStringCompleted(object sender, UploadStringCompletedEventArgs e)
{
// e.Result will contain the page's output
}
// This is my Parameters and Parameter Object classes
public class Parameters
{
public List<ParameterObject> prms;
public Parameters()
{
prms = new List<ParameterObject>();
}
public void AddPair(string id, string val)
{
prms.Add(new ParameterObject(id, val));
}
public String FormPostData()
{
StringBuilder buffer = new StringBuilder();
for (int i = 0; i < prms.Count; i++)
{
if (i == 0)
{
buffer.Append(System.Net.HttpUtility.UrlEncode(prms[i].id) + "=" + System.Net.HttpUtility.UrlEncode(prms[i].value));
}
else
{
buffer.Append("&" + System.Net.HttpUtility.UrlEncode(prms[i].id) + "=" + System.Net.HttpUtility.UrlEncode(prms[i].value));
}
}
return buffer.ToString();
}
}
public class ParameterObject
{
public string id;
public string value;
public ParameterObject(string id, string val)
{
this.id = id;
this.value = val;
}
}
First error: assuming that no error messages means success
Second error: gaping SQL injection holes
first fix: always assume queries will fail, and check for that condition:
$result = mysql_query($query) or die(mysql_error());
second fix: ditch the mysql_() functions and switch to PDO using prepared statements with placeholders. Boom. No more injection problems, and your code won't stop working on you when mysql_() is removed in a future PHP version.
ps..
3rd error: no quotes on your phone number value. So someone submits 867-5309, and you end up inserting -4442 because mysql saw it as two numbers being subtracted, not a string.
I am writing to Solr using JSON via HTTP/POST from a C#/Winforms/.NET4.0 app to speed up indexing and using the code below. I write a document to solr (based on these instructions) but keep getting a '400 bad request'. The JSON appears to be clean and no issues.
It seems to be a syntax issue but I have been wrestling with this for last many hours to no avail. Any ideas on what is awry? All help appreciated.
Here is the URI string being posted
"http://localhost:8080/solr/update/json -H 'Content-type:application/json' -d ' [ {\"UUID\":\"d2a174e4-81d6-487f-b68d-392be5d3d47a\",\"Extension\":\".AVI\",\"VideoFileName\":\"Clip 1.avi\"} ' ]"
string uri = http://localhost:8080/solr/update/json;
public bool WriteJSONToSolr(string uri, string json)
{
WebRequest request = WebRequest.Create(uri + " -H 'Content-type:application/json' -d ' [ " + json + " ' ]" );
request.ContentType = "application/x-www-form-urlencoded";
request.Method = "POST";
byte[] bytes = Encoding.ASCII.GetBytes(json);
Stream stream = null;
try
{ // send the Post
request.ContentLength = bytes.Length; //Count bytes to send
stream = request.GetRequestStream();
stream.Write(bytes, 0, bytes.Length); //Send it
}
catch
{
return false;
}
finally
{
if (stream != null)
{
stream.Close();
}
}
System.Net.WebResponse response = request.GetResponse();
if (response == null) return false;
return true;
}
If you are inserting then you will need to use add and doc in your json element. You'll also want to add a commit so that the index is updated. You can also remove the parameters from your uri as you can add them in the web request object. Lastly, you should have your collection name in the uri.
string json = "{\"add\":{\"doc\":{"
+ "\"UUID\":\"d2a174e4-81d6-487f-b68d-392be5d3d47a\","
+ "\"Extension\":\".AVI\","
+ "\"VideoFileName\":\"Clip 1.avi\"}},";
+ "\"commit\":{}}";
string uri = "http://localhost:8080/solr/collection/update";
WebRequest request = WebRequest.Create(uri);
request.ContentType = "application/json";
request.Method = "POST";
byte[] bytes = Encoding.ASCII.GetBytes(json);
Stream stream = null;
try {
request.ContentLength = bytes.Length;
stream = request.GetRequestStream();
stream.Write(bytes, 0, bytes.Length);
}
catch {
return;
}
finally {
if (stream != null) {
stream.Close();
}
}
System.Net.WebResponse response = request.GetResponse();
if (response == null) {
return;
}
If you are inserting multiple objects to solr you can add multiple add objects or doc objects to the json. For example...
json = "{add:{doc:{keys:values}}, add:{doc:{keys:values}}, commit:{}}"
or
json = "{add:{doc:{keys:values}, doc:{keys:values}}, commit:{}}"
While your debugging this watch the log for solr. It will alert you to any problems with that may be happening on the solr side.
First of all, I don't think you are passing a correct json data with -d option.. Look at the following formatting code in your code.
" -H 'Content-type:application/json' -d ' [ " + json + " ' ]"
Assume, your json data is {"name":"sam"} Then, the above formatting results to
-H 'Content-type:application/json' -d ' [{"name":"sam"} ' ]
You are passing a json data with missing ].
Apart from that, your approach for updating a document in solr index is wrong. Take a look at the following simple code.
[BTW: You may pass the 'commit' argument in the url].
public async Task PostAsync()
{
string json = "{\"add\": {\"doc\": {"
+ "\"id\":\"12345\","
+ "\"firstname\":\"Sam\","
+ "\"lastname\":\"Wills\","
+ "\"dob\":\"2016-12-14T00:00:00Z\""
+ "}}}";
using (var client = new HttpClient())
{
string uri = "http://localhost:8983/solr/people/update/json?wt=json&commit=true";
var jsonContent = new StringContent(json);
await client.PostAsync(new Uri(uri), jsonContent);
}
}
If you want to update a specific field instead of whole document [partial update], use the following code snippet.
public async Task PartialPostAsync()
{
string json = "{\"add\": {\"doc\": {"
+ "\"id\":\"12345\","
+ "\"lastname\":{\"set\":\"George\"}"
+ "}}}";
using (var client = new HttpClient())
{
string uri = "http://localhost:8983/solr/people/update/json?wt=json&commit=true";
var jsonContent = new StringContent(json);
await client.PostAsync(new Uri(uri), jsonContent);
}
}
'id' field is an unique field.
did you forget putting a space char before -H?
The reasong that your code isn't working, is because you are using cURL syntax in .Net.
cURL is an executable that sends and receives HTTP requests and .Net is a framework for programming applications.
They are not the same.
To make it work with .Net you first should post to the correct uri, and you need to set the correct ContentType property like such:
var uri = "http://localhost:8080/solr/update/json";
using (var r = WebRequest.Create(uri))
{
r.ContentType = "application/json";
r.Method = "POST";
using (var rs = r.GetRequestStream())
rs.Write // your data
// get response
// return response data
}
That said, why inflict pain upon yourself? Just use a SolR connector that already has a typed API for SolR operations!
https://code.google.com/p/solrnet/ for example!
But if you don't want to use that, then at least use a modern HTTP API like https://nuget.org/packages/RestSharp
I ran into this same problem today.
Try these two things
1) Keep in mind that you can NOT send a json string like
[{"A":"1","B":"0","C":"","D":"Washington"}]
instead you may have to massage the json to be more like
[{"A":"1","B":"0","D":"Washington"}]
Solr does not like empty values.
2) This second trick that helps (when sending data to solr via 'curl') : Try replacing all Double Quotes in your json string with two Double Quotes before you send the request to solr.
json = json.Replace(#"""", #"""""");
Please try below code after convert json to stream bytes
protected override void Append(LoggingEvent loggingEvent)
{
byte[] bodyBytes;
try
{
string body = BodyFormatter.CreateBody(loggingEvent, _parameters);
bodyBytes = Encoding.UTF8.GetBytes(body);
}
catch (Exception e)
{
ErrorHandler.Error("Failed to create body", e);
return;
}
HttpWebRequest request = BuildRequest();
request.BeginGetRequestStream(r =>
{
try
{
using (Stream stream = request.EndGetRequestStream(r))
{
stream.BeginWrite(bodyBytes, 0, bodyBytes.Length, c =>
{
try
{
stream.EndWrite(c);
request.BeginGetResponse(a =>
{
try
{
var response = request.EndGetResponse(a);
if (((HttpWebResponse)response).StatusCode != HttpStatusCode.OK)
ErrorHandler.Error("Got failed response: " + ((HttpWebResponse)response).StatusDescription);
response.Close();
}
catch (Exception e)
{
ErrorHandler.Error("Failed to get response", e);
}
}, null);
}
catch (Exception e)
{
ErrorHandler.Error("Failed to write", e);
}
}, null);
}
}
catch (Exception e)
{
ErrorHandler.Error("Failed to connect", e);
}
}, null);
}