How to send text from Windows Phone 8.1 via HttpWebRequest / POST? - post

I have a web service that expects (unicode UTF-8 encoded) text data as an HTTP POST message.
I'd like to use it from a Windows Phone 8.1 runtime client.
I created the client, but it does not invoke the web URI.
Here's the code I use on the client:
Can anyone tell what am I missing?
Thanks,
B
{
...
SendText("http://192.168.1.107:58709/UploadText.aspx"); // The IP belongs to the web server, port is correct. I can invoke it from a browser.
...
}
string StringToSend = "This is a test string uploaded via HTTP POST from WP8";
private void SendText(string Url)
{
System.Net.HttpWebRequest request = (System.Net.HttpWebRequest)WebRequest.Create(Url);
request.ContentType = "application/x-www-form-urlencoded";
request.Method = "POST";
request.BeginGetRequestStream(new AsyncCallback(UploadText_GetRequestStreamCallback), request);
}
public void UploadText_GetRequestStreamCallback(IAsyncResult asyncResult)
{
System.Net.HttpWebRequest request = (System.Net.HttpWebRequest)asyncResult.AsyncState;
Stream postStream = request.EndGetRequestStream(asyncResult);
byte[] postDataAsBytes = System.Text.Encoding.UTF8.GetBytes(StringToSend);
postStream.Write(postDataAsBytes, 0, postDataAsBytes.Length);
postStream.Flush();
// postStream.Close(); // Close is not available in Windows Phone 8.1 runtime project.
// request.ContentLength = postDataAsBytes.ToString(); // request.ContentLength is not available in Windows Phone 8.1 runtime project.
request.Headers["Content-length"] = postDataAsBytes.ToString();
request.BeginGetResponse(new AsyncCallback(GetResponseCallback), request);
}

OK, it seems the code was correct...
Problem was, that the phone emulator could not connect to the development server (IIS Express). I searched the web over, tried a number of solutions, but I could not make it happen. In the meantime I trashed my wifi connection, had to remove and reinstall Hyper-V to make it work again.
The workaround was to publish the test web app to the local IIS (make sure it is the Debug version that is published) then attach to it from the debugger, call from WP8.1 emulator - and it works.

Related

Send data from ESP32 to a server via WiFi

I am not new here but this is my first question.
I have searched a lot and quite frankly can't understand how this is supposed to work.
I get data periodically (temperature) to my ESP32 and while having it set as a WiFi client, connect to my router and somehow store this data on my Laptop(or somewhere else, like a local/web site, don't know if that's possible/better).
How is the connection supposed to work? I have installed XAMPP and run the Apache and MySQL servers and I tried to connect to my Laptop with some sketches from Arduino using the ESP32 libraries
// Use WiFiClient class to create TCP connections
WiFiClient client;
const int httpPort = 80;
const char* host = "192.168.1.109"; //The local IP of my Laptop
if (!client.connect(host, httpPort)) {
Serial.println("connection failed");
return;
}
but it doesn't connect.
Can someone please explain to me how this connection is supposed to take form or is this question too vague? I really just wanna know the "how-things-should-work-together" in this situation.
Thank you in advance.
OK, so after a lot of research and trying, I managed to work it out. I can now send an HTTP request (like GET or POST) from my ESP32 to a local server that is running on my laptop using XAMP and get a response. I can also connect to my local IP from my mobile phone (which is also in the same WiFi network).
Just for anyone else who wants to connect to a location in a server hosted on a PC in a local network, the steps are:
Create a local server on your PC, laptop whatever using an application like XAMPP (I have Windows 10 so WAMP would also work), download, install, open and start Apache.
Make sure that the Firewall lets your requests pass through (for me it was open by default, but I had seen elsewhere Firewall being an issue)
Go to your network settings, select the network that your devices(ESP32, phone, etc.)are connected and change its profile to Private, meaning that you trust this network, making your PC discoverable and able to accept requests. (That is really simple but took me hours to find)
Now, in order to connect from your phone to your PC, open a browser and enter the local IP (that is the IP that is given to your PC from the router as a local network name) of your PC to a browser and that's it, you are connected.
If you installed and ran XAMP, when connecting to your local IP(from same PC or other local device), it will forward you to 192.168.x.x/dashboard. If you want to create new workspaces and files, browse the XAMP folder in the installed location and inside the '/htdocs' subfolder do your testing.
For the ESP32 communication in Arduino(basic steps, not full code):
#include <WiFi.h>
#include <HTTPClient.h>
String host = "http://192.168.x.x/testfolder/";
String file_to_access = "test_post.php";
String URL = host + file_to_access;
void setup(){
WiFi.begin(ssid, password); //Connect to WiFi
HTTPClient http;
bool http_begin = http.begin(URL);
String message_name = "message_sent";
String message_value = "This is the value of a message sent by the ESP32 to local server
via HTTP POST request";
String payload_request = message_name + "=" + message_value; //Combine the name and value
http.addHeader("Content-Type", "application/x-www-form-urlencoded");
int httpResponseCode = http.sendRequest("POST", payload_request);
String payload_response = http.getString();
}
In the test_post.php (located in "C:\xampp\htdocs\testfolder\") file I used a simple script to echo a message received using a POST request, so it's only 'readable' from POST requests. Connecting to it from your browser will give you the "Sorry, accepting..." message.
<?php
$message_received = "";
if ($_SERVER["REQUEST_METHOD"] == "POST"){
$message_received = $_POST["message_sent"];
echo "Welcome ESP32, the message you sent me is: " . $message_received;
}
else {
echo "Sorry, accepting only POST requests...";
}
?>
Finally, using Serial prints, the output is:
Response Code: 200
Payload: Welcome ESP32, the message you sent me is: This is the value of a message sent by the ESP32 to local server via HTTP POST request
There it is, hope that this helps someone.

TfsTeamProjectCollection does not ask for credential

Dears
Please help me with VS add-in Tfs connection question.
I've wrote VS 2017 plugin that uses TfsTeamProjectCollection class to connect to the tfs server. Tfs server is hosted in the https://dev.azure.com
However on certain computers it fails to connect to the Tfs server.
For example, I've tried to reproduce this and cleared all caches like described here. After clearing/connecting several cycles I've got the following:
VS Team Explorer is connected to the Tfs. I can checkout/checkin files, load history etc.
My add-in fails to connect with 401 non authorized error.
unity test started by VS is able to connect to the same Tfs using the same code
I've created sample console application that uses exactly the same class and method from add-in to connect and it works too.
Here is the source code I'm using to connect:
public override TfsTeamProjectCollection CreateCollection(WorkspaceInfo wi)
{
var s = (overrideConfig ?? Config);
var u = wi.ServerUri;
var vssCred = new VssClientCredentials(); // GetCredentials(s.Vsts);
Logger.Debug("getting collection for url:{0}", u);
TfsTeamProjectCollection tpc = null;
try
{
tpc = new TfsTeamProjectCollection(u, vssCred);
Logger.Debug("authenticating");
tpc.Authenticate(); // 401 non authorized exception here
}
I've tried to add vssCred.Storage = new VssClientCredentialStorage(); before Autheticate() but no luck
Then I've checked network packets using Fiddler application.
It shows the same request packet is sent using unit test, console application and add-in.
But console application and unit test produces initial request
POST
https://dev.azure.com/quipu-cwnet/Services/v3.0/LocationService.asmx
HTTP/1.1
and response is
HTTP/1.1 401 Unauthorized
X-TFS-FedAuthRedirect:
https://app.vssps.visualstudio.com/_signin?realm=dev.azure.com&reply_to=https%3A%2F%2Fdev.azure.com%2F...
Then console and unit test sends packet to the redirect url and asks for user credentials.
When add-in tries to connect to the Tfs server fiddler shows only first POST request and 401 response (with the same X-TFS-FedAuthRedirect header. But there is no redirection. From user side it looks like application freezes for some period after 401 response is obtained and then fails with 401 error.
Both Unit test and add-in assemblies has the same references to the 15.0.0 assemblies like Microsoft.TeamFoundation.VersionControl.Client and related.
I've tried VssConnection but the same
VssConnection connection = new VssConnection(u, vssCred);
connection.ConnectAsync().SyncResult();
var prj = connection.GetClient<ProjectHttpClient>();
var prjCollection = prj.GetProjects().Result; // 401 error here when is executed as VS add-in
foreach (var pc in prjCollection)
Logger.Debug("\tVssConnection project {0} {1}", pc.Id, pc.Name);
I'm using the same user to start VS (and add-in) and console. No elevated permissions.
Is there anything I can do with TfsConnection when used as VS add-in ?
the answer is to execute Authenticate() in the separate thread (non GUI) :crazy
var authTask = Task.Run(() => tpc.Authenticate());
authTask.Wait();
Please note that I'm using VS 2017 15.9.11 and Microsoft.TeamFoundationServer.ExtendedClient.15.112.1
upd1: I've upgraded Microsoft.TeamFoundationServer.ExtendedClient to 15.113.1
it works on my machine but still fails on my colleague machine.
Tfs credentials are working like a charm on both machines:
var tfsClientCredentials = TfsClientCredentials.LoadCachedCredentials(wi.ServerUri, false, false);
var res = new TfsTeamProjectCollection(wi.ServerUri, tfsClientCredentials);
res.EnsureAuthenticated();
despite the fact it is marked as obsolete.

Simple POST from website to external web api fails

I have an asp .net MVC-page
Im trying to connect to Eventbrite:s api
Simply put, it requires you to send client id to one url, using HttpGET and HttpPOST the result and some more info to another url.
The GET goes fine and I get the required (auth)"code". When I try to make the POST to the second url I get
"Socket Exception: An existing connection was forcibly closed by the
remote host"
I can POST to the second url, using Postman and the info from the GET-request it works ok, I get the auth token just fine.
This is the code Im using
var parameters = new Dictionary<string,string>();
parameters.Add("code", pCode);
parameters.Add("client_secret", CLIENT_SECRET);
parameters.Add("client_id", CLIENT_APP_KEY);
parameters.Add("grant_type", "authorization_code");
using (var client = new HttpClient())
{
var req = new HttpRequestMessage(HttpMethod.Post, pUrl) { Content = new FormUrlEncodedContent(parameters) };
var response = client.SendAsync(req).Result;
return response.Content.ReadAsStringAsync().Result;
}
I have a vague memory of a similar problem when publishing to Azure. Since I have to register my app with a public return url I cant look at the request with fiddler.
My site is running https.
I have also tested adding the below line (from some googling)
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
But then I get 404-error...
I have also tested this (with same result)
using (var client = new HttpClient())
{
var response = client.PostAsync(pUrl, content).Result;
authToken = response.Content.ReadAsStringAsync().Result;
}
Ive tested getting the auth code and and running the POST from local machine, same result...
I have contacted eventbrite developer support to see if they can help me as well...
This POST must contain the following urlencoded data, along with a Content-type: application/x-www-form-urlencoded header.
Since your content-type is application/x-www-form-urlencoded you'll need to encode the POST body, especially if it contains characters like & which have special meaning in a form.
Then use the following function to post your data:
using (var httpClient = new HttpClient())
{
using (var content = new FormUrlEncodedContent(parameters))
{
content.Headers.Clear();
content.Headers.Add("Content-Type", "application/x-www-form-urlencoded");
HttpResponseMessage response = await httpClient.PostAsync(url, content);
return await response.Content.ReadAsAsync<TResult>();
}
}
The error message you provided means the remote side closed the connection, the causes are:
·You are sending malformed data to the application.
·The network link between the client and server is going down for some reason.
·You have triggered a bug in the third-party application that caused it to crash.
·The third-party application has exhausted system resources.
·Set ServicePointManager.SecurityProtocol = ServicePointManager.SecurityProtocol | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;
For more details, you could refer to this case.
Changed OAuth access token URL from
https://www.eventbrite.com/oauth/token/
to (as specified)
https://www.eventbrite.com/oauth/token
(ie without trailing slash). Now it works

HttpWebRequest timeout (being blocked) c#

I have a c# application that downloads multiple tiny files from websites (torrents). Some sites restrict the number of downloads per IP per day.
I do a HttpWebRequest and if the stream is a valid torrent, I save it to disk.
Is there a way for my c# application to spoof my IP when performing the HttpWebRequest, so that the download will not fail ?
I spaced out the download time to one per 10 minutes, but no luck. I still get blocked eventually.
I have heard that "TOR" can use diffrent IPs, but I don't want the people using my desktop app to have to install TOR browser separately.
HttpWebResponse resp = null;
try
{
var req = (HttpWebRequest)WebRequest.Create("http://www.exampe.com/test.torrent);
req.Headers.Add(HttpRequestHeader.AcceptEncoding, "gzip,deflate");
req.AutomaticDecompression = DecompressionMethods.Deflate | DecompressionMethods.GZip;
req.Timeout = 30000;
req.KeepAlive = true;
resp = (HttpWebResponse)(req.GetResponse());
}
Any solutions ?
To do so, you need to manipulate tcp/ip packets. This means that you need to capture the outgoing packet created by HttpWebRequest and change its source IP to the spoofed one.
I found this forum post that seemingly has to do with what you want to do, check it out : http://pcapdotnet.codeplex.com/discussions/349978
As far as I know you can do it through PCap.net or SharpPcap libraries.

Configuring Windows user that an MVC application run under

I am writing an MVC application which needs to request owner names for ip addresses from ARIN.net. Here is the snippet of program code that I have written to do this:
.
.
.
string requestUrl = "http://whois.arin.net/rest/ip/17.151.229.4";
WebResponse response = null;
WebRequest request = WebRequest.Create(requestUrl);
request.Proxy.Credentials = CredentialCache.DefaultCredentials;
response = request.GetResponse();
StreamReader sr = new StreamReader(response.GetResponseStream());
XElement responseElmn = XElement.Parse(sr.ReadToEnd());
.
.
.
This snippet of code is successfully able to send a request to http://whois.arin.net/rest/ip/17.151.229.4 and receive the appropriate response when it is run from a console application on my machine. However, when I attempt to put this snippet of code in my MVC application, I get an exception stating
A connection attempt failed because the connected party did not
properly respond after a period of time, or established connection
failed because connected host has failed to respond .
My local machine, where these applications run, is inside the network of a very large corporation and therefore this snippet must send its request to ARIN through a proxy server when it is run by the previously mentioned applications. I believe that I'm probably receiving this discrepancy in results due to the console application running under a different user than the MVC application. I'm running both applications in debug mode in Visual Studio 2013. The MVC application is hosted by IIS Express when it is run in debug mode.
My questions are:
How can I find out what user the console application and the MVC application are run under?
How can I configure IIS Express to run the MVC application under a different user?
I have been unable to find answers to the questions in my research, any help is appreciated.
I discovered the cause of the problem. The MVC application didn't have a proxy server assigned to the proxy object member of the WebRequest instance by default, while the one in the console application did.
I therefore had to assign the proxy server to the proxy object instance of the WebRequest instance in my code before attempting to retrieve a response:
string requestUrl = "http://whois.arin.net/rest/ip/17.151.229.4";
WebResponse response = null;
WebRequest request = WebRequest.Create(requestUrl);
Uri newUri = new Uri("http://proxy.bigcorp.com:8080");
WebProxy myProxy = new WebProxy(newUri);
request.Proxy = myProxy;
request.Proxy.Credentials = CredentialCache.DefaultCredentials;
response = request.GetResponse();
StreamReader sr = new StreamReader(response.GetResponseStream());
XElement responseElmn = XElement.Parse(sr.ReadToEnd());
Thank you Brendan Green for your help!

Resources