Working cefsharp POST example - c#

Having a difficult time getting an HTTP POST request/response using cefsharp / ChromiumWebBrowser. I'm unable to find a working example on Stackoverflow, nor in the documentation. Looking to see if anyone has a full example? I'm stuck on if it can be done with a Navigate function (as show in one example), or needs to be a done with a handler / schema.
I'm trying a basic POST to a PHP script. If the data1/data2 match the input, it's return json status:success, otherwise failure. I see in the devtools that the html body comes back with json success, but this code returns or nothing at all. I've tried too different ways to get the response data. I want to grab the JSON response for the C# code to review. Surely there should be an easy way to accomplish this? I want to send an HTTP request and then get the body (json) to parse. If this needs the schema/handler, I cannot find a full example of using this.
namespace BrowserTest
{
public partial class MainForm : Form
{
ChromiumWebBrowser browser = null;
public Loader()
{
browser = new ChromiumWebBrowser("http://localhost/test/"); // Initialize to this page
pBrowserLogin.Controls.Add(browser);
}
private void btnTest_Click(object sender, EventArgs e)
{
byte[] request = Encoding.ASCII.GetBytes("data1=" + txtData1.Text + "&data2=" + txtData2.Text);
PostTest.Navigate(browser, "http://localhost/test/posttest.php", request, "application/x-www-form-urlencoded");
}
}
public static class PostTest
{
public static void Navigate(this IWebBrowser browser, string url, byte[] postDataBytes, string contentType)
{
IFrame frame = browser.GetMainFrame();
IRequest request = frame.CreateRequest();
request.Url = url;
request.Method = "POST";
request.InitializePostData();
var element = request.PostData.CreatePostDataElement();
element.Bytes = postDataBytes;
request.PostData.AddElement(element);
NameValueCollection headers = new NameValueCollection();
headers.Add("Content-Type", contentType);
request.Headers = headers;
frame.LoadRequest(request);
frame.GetTextAsync().ContinueWith(taskHtml =>
{
var html = taskHtml.Result;
System.Windows.Forms.MessageBox.Show(html);
});
string script = string.Format("document.documentElement.outerHTML;");
frame.EvaluateScriptAsync(script).ContinueWith(x =>
{
var response = x.Result;
if (response.Success && response.Result != null)
{
var fullhtml = response.Result;
System.Windows.Forms.MessageBox.Show(fullhtml.ToString());
}
});
}
}
}

Related

Getting 400 (Bad Request) with my firebase URL

I am coming to an issue where I am trying to do a PUT request to update and store data to my firebase database, but for some reason when I run my code and select on my object and click on next, I get error with my firebase web request url as a 400 (Bad Request) error. does anyone how to solve this issue. thanks for the help.
PS: HIDDEN_URL is just a text - I hide my project url for security purposes. Thanks!
-The hardcode values work: "{\"messages\":{\"message\":\"This is a test\"}}"; but not lastHighlightedObject.GetComponent<OBClick>().name;
Here is my code:
public void NextButton()
{
if (highlightSet == true)
{
var httpWebRequest =
(HttpWebRequest) WebRequest.Create("https://HIDDEN_URL.firebaseio.com/brokenComp.json");
httpWebRequest.ContentType = "application/json";
httpWebRequest.Method = "PUT";
using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
{
string missingObjectCount = lastHighlightedObject.GetComponent<OBClick>().name;
streamWriter.Write(missingObjectCount);
}
var httpResponse = (HttpWebResponse) httpWebRequest.GetResponse();
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
var result = streamReader.ReadToEnd();
Debug.Log(result);
}
// When everything is Okay, it will load the scene.
SceneManager.LoadScene("Quiz");
}
The service seems to require a certain JSON format. Since your hardcore version works
"{\"messages\":{\"message\":\"This is a test\"}}";
but not a single string I guess you have to use something like
string missingObjectCount = "{\"messages\":{\"message\":\"" + HighlightedObject.GetComponent<OBClick>().name + "\"}}"
As mentioned in your previous question:
Currently your code will freeze until the request is done.
I would rather use either UnityWebRequest.Put to not block the entire thread until the request is done.
This is just the example (with small edits) from the API but I guess it js pretty straight forward and you should be able to use it for your purpose
public class MyBehavior : MonoBehaviour
{
public void NextButton()
{
StartCoroutine(Upload());
}
IEnumerator Upload()
{
byte[] myData = System.Text.Encoding.UTF8.GetBytes("{\"messages\":{\"message\":\"" + HighlightedObject.GetComponent<OBClick>().name + "\"}}");
using (UnityWebRequest www = UnityWebRequest.Put(YOUR_URL, myData))
{
yield return www.Send();
if (www.isNetworkError || www.isHttpError)
{
Debug.Log(www.error);
}
else
{
Debug.Log("Upload complete!");
}
}
}
}
Btw is something hindering you from using the Firebase SDK?
There it would be something like
public class MyScript: MonoBehaviour
{
private void Start()
{
// Set up the Editor before calling into the realtime database.
FirebaseApp.DefaultInstance.SetEditorDatabaseUrl("https://YOUR-FIREBASE-APP.firebaseio.com/");
// Get the root reference location of the database.
reference = FirebaseDatabase.DefaultInstance.RootReference;
}
public void NextButton()
{
// ported the variable names from your latest question
mDatabaseRef.Child("messages").Child("message").SetValueAsync(HighlightedObject.GetComponent<OBClick>().name);
}
}

Xamarin.Android: How Can I Pass WebView Login Creds Into HttpWebRequest?

I am trying to pass login creds from a WebView into an HttpWebRequest but not having any luck getting an authenticated response. I am able to successfully make the request, but the response is acting like I haven't logged in. My app has 5 WebViews contained within Fragment s and I'm logged in on all of them. I've tried using the CookieSyncManager but it's deprecated and .Sync() didn't work. I've tried a lot of different ways of passing the cookies into the HttpRequest with no success and many hours spent.
One would think this is a simple request; user has logged in within the app; they should be authenticated for all requests. Here's the closest that I've gotten, but the response string is still not the same as through my authenticated WebView :
This attempt parses each Cookie into a string and adds it
public string _cookieString { get; set; }
private class ExtWebViewClient : WebViewClient
{
TheFragment5 _fm5 = new TheFragment5();
public override void OnPageFinished(WebView view, string url)
{
var cookieHeader = Android.Webkit.CookieManager.Instance.GetCookie(url);
var cookiePairs = cookieHeader.Split('&');
_fm5._cookieString = "";
foreach (var cookiePair in cookiePairs)
{
var cookiePieces = cookiePair.Split('=');
if (cookiePieces[0].Contains(":"))
cookiePieces[0] = cookiePieces[0].Substring(0, cookiePieces[0].IndexOf(":"));
cookies.Add(new Cookie
{
Name = cookiePieces[0],
Value = cookiePieces[1]
});
}
foreach (Cookie c in cookies)
{
if (_fm5._cookieString == "")
{
_fm5._cookieString = c.ToString();
}
else
{
_fm5._cookieString += c.ToString();
}
}
}
}
I've also tried just doing:
_fm5._cookieString = cookieHeader.ToString();
but neither of those attempts is working when I add the cookie string into my HttpRequest :
public async void GetNotificationText(string url)
{
//var _cmhc = _cookieMan.HasCookies;
await Task.Run(() =>
{
_notificationHttpRequestInProgress = true;
try
{
var _ctxxx = Android.App.Application.Context;
//URL _url2 = new URL("https://bitchute.com/notifications/");
//HttpURLConnection conn = (HttpURLConnection)_url2.OpenConnection();
//conn.ReadTimeout = 10000 /* milliseconds */;
//conn.ConnectTimeout = 15000 /* milliseconds */;
////conn.SetRequestProperty("Cookie", cookies);
//conn.Connect();
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
Uri uri = new Uri(url);
var _req = request;
var _uriii = uri;
var _cookiesss = _fm5._cookieString;
_cookieCon.SetCookies(uri, _cookiesss);
request.CookieContainer = _cookieCon;
//request.CookieContainer.SetCookies(uri, _cookiesss);
request.AutomaticDecompression = DecompressionMethods.GZip;
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
using (Stream stream = response.GetResponseStream())
using (StreamReader reader = new StreamReader(stream))
{
_notificationRawText = reader.ReadToEnd();
Console.WriteLine(_notificationRawText);
_rawNoteText = _notificationRawText;
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
_notificationHttpRequestInProgress = false;
});
}
This returns, but not the authenticated webtext request; I get the same response any user would get on a browser having never logged in. If I were to browse out to this same url on any WebView in my app, I'd get a completely different response.
You will also notice some commented out code that was another failed attempt at adding the cookies into a connection. I had also tried using HttpURLConnection.SetRequestProperty("Cookie", cookies);
where cookies was a CookieCollection and that didn't work either. The code is mostly commented out and layered because I've been trying this for days.
Does anyone know how I can pass WebView cookies into an HttpRequest using Xamarin.Android?
I am putting this code below in Fragment5 of my app; you can see and compile the full context here:
https://github.com/hexag0d/BitChute_Mobile_Android_BottomNav/blob/NotificationAdder/Fragments/TheFragment5.cs
I'm not sure exactly why the above example didn't work; maybe if you're better at .NET than I am, you could figure it out. However, I was able to successfully pass WebView creds into an HttpClient by following these steps, which are returning an authenticated response. This may not be the most elegant way of doing it, but you can always refine my answer, or post a better one.
What I had to do was set the HttpClient.DefaultRequestHeaders using the .Add() method like this: _client.DefaultRequestHeaders.Add("Cookie", TheFragment5._cookieHeader);
I got the CookieHeader (which is just a string btw) like this:
//instantiate a string that will house our cookie header
public static string _cookieHeader;
//you might want to make it private to prevent abuse
//but this example is just for demonstration
//the thing is we need a string to house our headers in scope of both the WebView and the HttpClient
//extend the WebViewClient
private class ExtWebViewClient : WebViewClient
{
public override void OnPageFinished(WebView view, string url)
{
//I get the cookies when the page finishes loading because
//then we know the cookie has our login cred header
//also, most of the previous examples got the cookies OnPageFinished
TheFragment5._cookieHeader = Android.Webkit.CookieManager.Instance.GetCookie(url);
}
}
Then we need another method for the HttpClient and HttpClientHandler ... mine scans a webpage for notification text.
public async void GetNotificationText(string url)
{
await Task.Run(() =>
{
/* this line is pretty important,
we need to instantiate an HttpClientHandler
then set it's UseCookies property to false
so that it doesn't override our cookies
*/
HttpClientHandler handler = new HttpClientHandler() { UseCookies = false };
try
{
Uri _notificationURI = new Uri("https://bitchute.com/notifications/");
//instantiate HttpClient using the handler
using (HttpClient _client = new HttpClient(handler))
{
//this line is where the magic happens;
//we set the DefaultRequestHeaders with the cookieheader we got from WebViewClient.OnPageFinished
_client.DefaultRequestHeaders.Add("Cookie", TheFragment5._cookieHeader);
//do a GetAsync request with our cookied up client
var getRequest = _client.GetAsync("https://bitchute.com/notifications/").Result;
//resultContent is the authenticated html string response from the server, ready to be parsed =]
var resultContent = getRequest.Content.ReadAsStringAsync().Result;
/*
I was writing to console to check the
response.. for me, I am now getting
the authenticated notification html
page
*/
Console.WriteLine(resultContent);
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
Hope this helps you, posting for future reference, especially for people using Xamarin.Android.

Is it possible to read results of the XmlSerializer being sent by HTTPClient?

I am using an extension method to post xml using the HTTPClient which works great.
My question: Is it possible to read, log, or display the results of the XmlSerializer data that is being sent/posted ?
public static class HttpExtensions {
public static Task<HttpResponseMessage> PostAsXmlWithSerializerAsync<T>(this HttpClient client, string requestUri, T value)
{
return client.PostAsync(requestUri
, value
, new XmlMediaTypeFormatter { UseXmlSerializer = true }
);
}
}
PostAsync hides the actually sent HttpRequestMessage from you, though you can retrieve it from the response, too so you can trace both the request and response contents:
var response = await client.PostAsync(uri, value, formatter);
Log(response);
If you really want to log the request only, create the request manually:
var request = new HttpRequestMessage(HttpMethod.Post, uri);
request.Content = new StreamContent(myXmlStream);
Log(request);
var response = await client.SendAsync(request);
Log(response);
And now you can create one or two Log overloads. I show it for the response, which includes both the request and response log. This is independent from the format, works for both XML and json content.
protected virtual void Log(HttpResponseMessage response)
{
// Use any log/trace engine here, this example uses Debug
Debug.WriteLine($"Response of the API Call [{response.RequestMessage.Method}] {response.RequestMessage.RequestUri}: {response.StatusCode} {FormatResponse(response)}");
}
private static string FormatResponse(HttpResponseMessage response)
{
var result = new StringBuilder();
result.AppendLine();
result.AppendLine("Original request:");
result.AppendLine(FormatHttpMessage(response.RequestMessage.Headers, response.RequestMessage.Content));
result.AppendLine();
result.AppendLine("Obtained response:");
result.AppendLine(FormatHttpMessage(response.Headers, response.Content));
}
private static string FormatHttpMessage(HttpHeaders headers, HttpContent content)
{
var result = new StringBuilder();
var headersString = headers.ToString();
if (!string.IsNullOrWhiteSpace(headersString))
{
result.AppendLine("Headers:");
result.AppendLine(headersString);
result.AppendLine();
}
if (content != null)
{
result.AppendLine("Content:");
result.AppendLine(content.ReadAsStringAsync().Result);
}
return result.ToString();
}
Yes, you can.
Download and install Fiddler , then filter your requestUri , you can monitor all transferring data such you serialized xml.

Downloading Large Google Drive files with WebClient in C#

I know there are tones of questions on this subject already. After reading all the threads, I decided to get a redirected URL in a confirmation HTML page and then use it as a direct link to download.
As you know, the original URL format of the direct download link is like this.
https://drive.google.com/uc?export=download&id=XXXXX..
But if the size of the target file is big, then it is like this.
https://drive.google.com/uc?export=download&confirm=RRRR&id=XXXXX..
I can get RRRR from the first downloaded data, so I need to try twice in order to download the real file. The concept is very simple enough but I can't get this to work.
class Test
{
class MyWebClient: WebClient
{
CookieContainer c = new CookieContainer();
protected override WebRequest GetWebRequest(Uri u)
{
var r = (HttpWebRequest) base.GetWebRequest(u);
r.CookieContainer = c;
return r;
}
}
static string GetRealURL(string filename)
{
// Some Jobs to Parse....
return directLink;
}
static void Main()
{
MyWebClient wc = new MyWebClient();
string targetLink = "https://drive.google.com/uc?export=download&id=XXXXXXX";
wc.DownloadFile(targetLink, "tempFile.tmp");
targetLink = GetRealURL("tempFile.tmp");
wc.DownloadFile(targetLink, "realFile.dat");
}
}
What did I wrong?
I can get the right download link from the first file, but I get another confirmation page file with another confirm code on the second try. I thought this was because of cookies, so I created my own WebClient class as you can see above.
Also I originally used DownloadFileAsync(), and changed it to DownloadFile() just in case, but the same result..
I'm still thinking it has something to do with cookie things.
What am I missing here?
I had this same problem but had solved it in an HttpClient. I tried via your approach with WebClient and was able to get it to work. You don't show your GetRealUrl() source, but i'm willing to bet in there lies the issue. Here's how I did it:
You need to parse the html response to get the url in the href attribute of the "download anyway" button. It will only have the relative url, (the /uc?export=download... part)
You need to replace the xml escape character & with &
Then you can build the url using thte domain https://drive.google.com
At which point you can download the file. Here's the source (used in a test WPF application):
class MyWebClient : WebClient
{
CookieContainer c = new CookieContainer();
protected override WebRequest GetWebRequest(Uri u)
{
var r = (HttpWebRequest)base.GetWebRequest(u);
r.CookieContainer = c;
return r;
}
}
private async void WebClientTestButtonGdrive_Click(object sender, RoutedEventArgs e)
{
using (MyWebClient client = new MyWebClient())
{
//get the warning page
string htmlPage = await client.DownloadStringTaskAsync("https://drive.google.com/uc?id=XXXXXXX&export=download");
//use HtmlAgilityPack to get the url with the confirm parameter in the url
HtmlDocument document = new HtmlDocument();
document.LoadHtml(htmlPage);
HtmlNode node = document.DocumentNode;
HtmlNode urlNode = node.SelectSingleNode(#"//a[contains(#href, 'XXXXXXX') and contains(#id, 'uc-download-link')]//#href");
string downloadUrl = urlNode.Attributes["href"].Value;
downloadUrl = downloadUrl.Replace("&", "&");
downloadUrl = "https://drive.google.com" + downloadUrl;
//download the file
if (File.Exists("FileToDownload.zip"))
File.Delete("FileToDownload.zip");
await client.DownloadFileTaskAsync(downloadUrl, "FileToDownload.zip");
}
}

how to Post Json Data to URL..?

i'm new to wp8 and i don't have any idea to post and update my data in URL so please can any one help me to post/Update data in the url..
my header and content type...
Header - Accept: application/json
Content-Type application/json
MY Class Register with the variables...
public class Register
{
public string email { get; set; }
public string password { get; set; }
}
My Design..
when i click ADD button it should post the data in my url.. so plz help me to do it..
MY CODE for post method..
WebClient client = new WebClient();
Register res = new Register();
res.email = txt_email.Text;
res.password = txt_password.Text;
String json = JsonConvert.SerializeObject(res);
client.Headers[HttpRequestHeader.Accept] = "application/json";
client.Headers[HttpRequestHeader.ContentType] = "application/json";
client.UploadStringCompleted += (object source, UploadStringCompletedEventArgs ex) =>
{
if (ex.Error != null || ex.Cancelled)
{
// Error or cancelled
MessageBox.Show(ex.Result);
}
};
var uri = new Uri(url, UriKind.Absolute);
// client.Encoding = System.Text.Encoding.UTF8;
client.UploadStringAsync(uri,json); // message is the json content in string
ERROR.. on Adding content..
I use RestSharp in my projects for that kind of thing. It simplifies things a bit particularly if you want to access cookies.
There's some examples on their wiki that should show you what to do.
http://restsharp.org/
You can use WebClient
public void PostJSON()
{
client = new WebClient();
client.Headers[HttpRequestHeader.Accept] = "application/json";
client.Headers[HttpRequestHeader.ContentType] = "application/json";
client.UploadStringCompleted += (object source, UploadStringCompletedEventArgs e) =>
{
if (e.Error != null || e.Cancelled)
{
// Error or cancelled
}
};
client.UploadStringAsync(url, message); // message is the json content in string
}
Your code seems legit to me. Since you get the error at runtime, I doubt that you might not have a proper Internet connection in your emulator. Or, if you are running your web service from localhost, you must help your emulator reach your local service.
Case #1: No proper Internet connection
Refer the following link and troubleshoot your network problem as stated in the MSDN page.
http://msdn.microsoft.com/en-us/library/windowsphone/develop/jj681694(v=vs.105).aspx
Case #2: Help emulator to connect to a local web service
Even when you can connect to external web content, you still need to configure your emulator to access your local web service. Go through the MSDN article given at the link below.
http://msdn.microsoft.com/en-us/library/windowsphone/develop/jj684580(v=vs.105).aspx
Feel free to leave a comment if you need further assistance.

Categories

Resources