What uri pattern do I need to communicate with my PC from my handheld device? - httpwebrequest

As I was reminded here, I need to probably use "ppp_peer" to programmatically connect from my Compact Framework app to my Web API app running on my PC.
I have tried this (replacing an IPAddress with "ppp_peer"):
string uri = string.Format("http://ppp_peer:28642/api/FileTransfer/GetHHSetupUpdate?serialNum={0}&clientVersion={1}", serNum, clientVer);
...but I get, "NullReferenceException" in "Main" (prior to this I got "Unable to Connect to the Remote Server").
I have a breakpoint in the server code, but it doesn't reach that, so it must be somewhere in the client where this is occurring.
The client code in context is:
string uri = string.Format("http://ppp_peer:28642/api/FileTransfer/GetHHSetupUpdate?serialNum={0}&clientVersion={1}", serNum, clientVer);
RESTfulMethods.DownloadNewerVersionOfHHSetup(uri);
. . .
public static void DownloadNewerVersionOfHHSetup(string uri)
{
string dateElements = DateTime.Now.ToString("yyyyMMddHHmmssfff", CultureInfo.InvariantCulture);
var outputFileName = string.Format("HHSetup_{0}.exe", dateElements);
try
{
var webRequest = (HttpWebRequest)WebRequest.Create(uri);
var webResponse = (HttpWebResponse)webRequest.GetResponse();
string statusCode = webResponse.StatusCode.ToString();
if (statusCode == "NoContent")
{
MessageBox.Show("You already have the newest available version.");
}
else
{
var responseStream = webResponse.GetResponseStream();
using (Stream file = File.Create(outputFileName))
{
CopyStream(responseStream, file);
MessageBox.Show(string.Format("New version downloaded to {0}", outputFileName));
}
}
}
catch (WebException webex)
{
string msg = webex.Message;
string innerEx = webex.InnerException.ToString();
string status = webex.Status.ToString();
MessageBox.Show(string.Format("Message: {0}; Status: {1}; inner Ex: {2}", msg, status, innerEx));
}
}
Do I need an IPAddress in addition to ppp_peer, or is my formatting of the URI wrong, or...???
UPDATE
After the "NRE" I also see, ""...encountered a serious error and must shut down"
I changed the code from above to see just what ppp_peer is translated as:
IPAddress ipAd = Dns.Resolve("PPP_PEER").AddressList[0];
string IPAddr = ipAd.ToString();
MessageBox.Show(IPAddr);
string uri = string.Format("http://{0}:28642/api/FileTransfer/GetHHSetupUpdate?serialNum={1}&clientVersion={2}", IPAddr, serNum, clientVer);
The MessageBox call shows me "192.168.55.100" which is different from what I thought my PC's IPAddress was...???
I get the same with:
IPAddress ipAd = Dns.GetHostEntry("PPP_PEER").AddressList[0];
UPDATE 2
Using this instead (I got it from here [Get ip address of host pc from windows mobile when connected via ActiveSync):
IPAddress ipAd = Dns.GetHostEntry(Dns.GetHostName()).AddressList[0];
...the IP Address displayed is "one up" (192.168.55.101), and instead of an NRE, I get:
Message: Unable to connect to the remote server; Status: ConnectFailure; inner Ex: System.Net.Sockets.SocketException: No connection could be made because the target machine actively refused it at System.Net.Sockets.SocketConnectNoCheck(EndPoint remoteEP) ...
So it seems I'm doing all I can on the client end, and the server hears the knock, but is not opening the door - am I right?
BTW, out of curiosity I also added this code:
string hostName = Dns.GetHostName();
MessageBox.Show(string.Format("host name is {0}", hostName));
...and I see "WindowsCE"
UPDATE 3
According to this post by Andy Wiggly (the cat/bloke who wrote "MS .NET Compact Framework"), you do use "ppp_peer":
HttpWebRequest request = REST.CreateRequest(#"http://ppp_peer/DataServicesWebsite/NorthwindService.svc/Customers",
HttpMethods.GET, String.Empty, #"application/atom+xml", "", "");
The interestingest thing about this is the lack of a port assignment (":28642" or whatever); however, this style also gives me an NRE (yes, kind of like a Null Ready to Eat).
UPDATE 4
So what uri will it take to access the host machine from the handheld device?
I have tried all of the following permutations from the client/Compact Framework app, and none work:
IPAddress ipAd = Dns.GetHostEntry(Dns.GetHostName()).AddressList[0];
string IPAddr = ipAd.ToString();
//string uri = string.Format("http://ppp_peer/api/...
//string uri = string.Format("http://ppp_peer:28642/api...
//string uri = string.Format("http://PPP_PEER/api/...
string uri = string.Format("http://PPP_PEER:28642/api/...
//string uri = string.Format("http://{0}:28642/api/...
//string uri = string.Format("http://192.168.125.50:28642/api/...
//string uri = string.Format("http://Platypus:28642/api/...
RESTfulMethods.DownloadNewerVersionOfHHSetup(uri);
The error is happening somewhere in that client code (can't step through it, so I don't know exactly where), because I have a breakpoint on the last line shown, and it is never reached.
SERVER (Web API) code:
[Route("api/FileTransfer/GetUpdatedHHSetup")]
public HttpResponseMessage GetUpdate(string serialNum, string clientVersion)
{
return _fileTransfer.GetHHSetupUpdate(serialNum, clientVersion);
}
public HttpResponseMessage GetHHSetupUpdate(string serialNum, string clientVersion)
{
HttpResponseMessage result;
string filePath = GetAvailableUpdateForCustomer(serialNum); // <= breakpoint on this
line
I put some debug lines in DownloadNewerVersionOfHHSetup() so that it now looks like this:
public static void DownloadNewerVersionOfHHSetup(string uri)
{
MessageBox.Show("Made it into DownloadNewerVersionOfHHSetup");
string dateElements = DateTime.Now.ToString("yyyyMMddHHmmssfff",
CultureInfo.InvariantCulture);
var outputFileName = string.Format("HHSetup_{0}.exe", dateElements);
try
{
var webRequest = (HttpWebRequest)WebRequest.Create(uri);
MessageBox.Show("Made it into DownloadNewerVersionOfHHSetup #2");
var webResponse = (HttpWebResponse)webRequest.GetResponse();
MessageBox.Show("Made it into DownloadNewerVersionOfHHSetup #3");
. . .
I never see "#3", so it must be a problem inside the call to GetResponse(), but how can I find out exactly what? I get the NRE, then "...encountered a serious error and must shut down"
This is where it tries to call the server but, as mentioned, it never makes it to the server method being called...
UPDATE 5
It turns out that this now works:
http://192.168.125.50:28642/api/
...and the main reason that it does is because there was a mismatch between my routing attribute (GetUpdatedHHSetup) and what I was calling from the client (GetHHSetupUpdate). Once I aligned those planets, the NRE went away, and I got the expected result.

PPP_PEER is not needed in the uri/connection string. Using the host PC's IP Address (and port number for the server/Web API app) works now (after fixing the mismatch between the routing attribute and what the client was calling it).
I reckon using the machine name would work just as well, too.

Related

Asp.net core website intermittently refusing connections

I have an asp.net core 3.0 website. It has a controller that implements an HttpGet function that does some database stuff then returns a Json object (https://localhost:44356/api/runner/match).
I have a console application that uses an HttpClient to hit that url. I launch the site locally and then I launch my console app. About 50% of the time it works. The other 50% of the time I get:
HttpRequestException: No connection could be made because the target machine actively refused it.
SocketException: No connection could be made because the target machine actively refused it.
I'm trying to figure out why my console app's connection is being blocked. I don't know how to start debugging this. I tried to implement a retry on the request, but once I get the exception, I keep getting it. So I think it's something non-deterministic happening in my website, potentially related to SSL?
I'm able to hit the url in Chrome locally just fine.
How do I figure out what is blocking the connection from being made?
Is there any chance this is something IIS Express is doing?
Calling code in console app:
static async Task<List<Deck>> GetMatchData()
{
string baseUrl = "https://localhost:44356/api/runner/match";
using (HttpClient client = new HttpClient())
{
HttpResponseMessage res = null;
res = await client.GetAsync(baseUrl);
Controller function:
[HttpGet("match")]
public async Task<ActionResult> GetMatchup()
{
int count = db.Decks.Count();
Random r = new Random();
int d1 = r.Next(count) + 1; // database ids start at 1 for some reason
int d2 = r.Next(count - 1) + 1;
if (d1 == d2)
d2++;
List<Deck> result = new List<Deck>();
result.Add(await db.Decks.FindAsync(d1));
result.Add(await db.Decks.FindAsync(d2));
if (result[0] == null || result[1] == null)
{
return BadRequest();
}
return Ok(result);
}
try
HttpClient httpClient = new HttpClient();
//specify to use TLS 1.2 as default connection
System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls;
string baseUrl = "https://localhost:44356/api/runner/match";
httpClient.BaseAddress = new Uri(baseUrl );
httpClient.DefaultRequestHeaders.Accept.Clear();
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var getResult = await httpClient.GetAsync(baseUrl);

Windows Phone Silverlight request does not update

I'm quite new to the Windows Phone dev and I have to do an application to communicate with a Restful API. Everything works fine to get the informations back from the API but my problem occurs when I try to update the content. For example, I have a profile and I try to update the user's information (change the city let's say). On the server side I can see that my update worked properly but when I go back to my profile in my WP app nothing has changed, the city is still the same as the old one. This is my code :
public MainPage()
{
InitializeComponent();
this.ApplicationBar = this.Resources["HomeBar"] as ApplicationBar;
Requester requester = new Requester();
requester.initGetRequest("/me/", GetResponseCallback, true);
}
private void GetResponseCallback(IAsyncResult asynchronousResult)
{
try
{
HttpWebRequest request = (HttpWebRequest)asynchronousResult.AsyncState;
HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(asynchronousResult);
Stream streamResponse = response.GetResponseStream();
StreamReader streamRead = new StreamReader(streamResponse);
string read = streamRead.ReadToEnd();
GlobalData.GetInstance().user = JsonConvert.DeserializeObject<MeClass>(read);
Dispatcher.BeginInvoke(() =>
{
MessageBox.Show(read);
});
//Create the profile and stuff
streamResponse.Close();
streamRead.Close();
response.Close();
}
catch (WebException webException)
{
HttpStatusCode status = ((HttpWebResponse)webException.Response).StatusCode;
Dispatcher.BeginInvoke(() =>
{
MessageBox.Show(status.ToString());
});
}
}
I figured out that the string 'read' is always equal to the old one, even after the update so this is why the content is not updated but how can the response be exactly the same as before, even if the update worked fine on the server side (if I check in Postman after my update, I can see that my city is the new one). If I restart my app I can see the update.
I can also show you my initGetRequest() :
public void initGetRequest(String endPoint, Action<IAsyncResult> callback, Boolean header)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url + endPoint);
if (header == true)
request.Headers["Authorization"] = GlobalData.GetInstance().Header;
request.BeginGetResponse(new AsyncCallback(callback), request);
}
Thank you for your help !
I finally found why my request was still the same even after the update. The HttpWebRequest uses a cache by default. I only added a small bit of code before calling my request :
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url + endPoint);
if (header == true)
request.Headers["Authorization"] = GlobalData.GetInstance().Header;
request.Headers[HttpRequestHeader.IfModifiedSince] = DateTime.UtcNow.ToString();
request.BeginGetResponse(new AsyncCallback(callback), request);
I had no idea about that cache so I hope this answer will help someone having the same issue !

Timeout using ServiceStack.Client

I have been using service stack via AJAX calls for some time without issue, but have recently created a quick winforms app which utilizes the service stack client (specifically JsonServiceClient).
However - I have hit a problem whereby I consistently get a timeout on a call which works successfully on the the first TWO attempts. It looks like either the service stack client is holding on to some resource, or I am using the client in the wrong way. It only occurs when running against a remote service (works every time on a local machine). Here is my code, and the exception:
var url = "http://www.TestServer.com/api";
var taskId = Guid.Parse("30fed418-214b-e411-80c1-22000a5b9fe5");
var email = "admin#example.com";
using (var client = new JsonServiceClient(url))
{
var result = client.Send(new Authenticate {UserName = "username", Password = "Password01", RememberMe = true});
client.Put(new AssignTask { AdminTaskId = taskId, Assignee = email });//Call #1 - works fine
client.Put(new AssignTask { AdminTaskId = taskId, Assignee = email });//Call #2 - works fine
try
{
client.Put(new AssignTask { AdminTaskId = taskId, Assignee = email });//Call #3 - works fine
}
catch (WebException ex)
{
//Times out every time
//at System.Net.HttpWebRequest.GetRequestStream(TransportContext& context)
//at System.Net.HttpWebRequest.GetRequestStream()
//at ServiceStack.Net40PclExport.GetRequestStream(WebRequest webRequest)
//at ServiceStack.ServiceClientBase.<>c__DisplayClassa.<SendRequest>b__9(HttpWebRequest client)
//at ServiceStack.ServiceClientBase.PrepareWebRequest(String httpMethod, String requestUri, Object request, Action`1 sendRequestAction)
//at ServiceStack.ServiceClientBase.SendRequest(String httpMethod, String requestUri, Object request)
//at ServiceStack.ServiceClientBase.Send[TResponse](String httpMethod, String relativeOrAbsoluteUrl, Object request)
//at ServiceStack.ServiceClientBase.Put[TResponse](String relativeOrAbsoluteUrl, Object requestDto)
//at ServiceStack.ServiceClientBase.Put(Object requestDto)
//at SSClientIssue.Program.Main(String[] args) in c:\Users\David\Documents\Visual Studio 2013\Projects\SSClientIssue\SSClientIssue\Program.cs:line 27
throw;
}
}
After the timeout, I can close and reload the app (server stays up), and then get same behavior again (two successful calls). IIS logs show that the 3rd call does not make it to the server, so looks like a Client issue.
I have been looking at this for 8 hours and I think my eyes are starting to bleed...If anyone can help I will buy you a beer!
The issue is due to your ServiceClient requests not specifying a known response type.
Response types can either be marked on the Request DTO using the IReturn<T> marker (recommended):
public class GetAllAdminUsernamesRequest : IReturn<List<string>> { ... }
By adding this on the Request DTO, the ServiceClient is able to automatically infer and convert the response, e.g:
List<string> response = client.Get(new GetCurrentAdminUserAdminTasks());
Otherwise an alternative to specifying the Response on the Request DTO, is to specify it on the call-site, e.g:
List<string> response = client.Get<List<string>>(new GetCurrentAdminUserAdminTasks());
If you don't do this the Response is unknown so the ServiceClient will just return the underlying HttpWebResponse so you can inspect the response yourself.
HttpWebResponse tasks = client.Get(new GetCurrentAdminUserAdminTasks());
In order to be able to inspect and read from the HttpWebResponse the response cannot be disposed by the ServiceClient, so it's up to the call-site making the request to properly dispose of it, i.e:
using (HttpWebResponse tasks = client.Get(new GetCurrentAdminUserAdminTasks())) {}
using (HttpWebResponse adminUsers = client.Get(new GetAllAdminUsernames())) {}
try
{
using (client.Put(new AssignTask { AdminTaskId = taskId, Assignee = user })) {}
using (client.Put(new AssignTask { AdminTaskId = taskId, Assignee = user })) {}
using (client.Put(new AssignTask { AdminTaskId = taskId, Assignee = user })) {}
using (client.Put(new AssignTask { AdminTaskId = taskId, Assignee = user })) {}
}
...
Disposing of your WebResponses responses will resolve your issue.
If you don't do this the underlying WebRequest will throttle open connections and only let a limited number of simultaneous connections through at any one time, possibly as a safe-guard to prevent DDOS attacks. This is what keeps the underlying connections open and WebRequest to block, waiting for them to be released.

Google Spellcheck

I'm unable to access the Google spell check service located at this address:
https://www.google.com/tbproxy/spell
is anyone else having this problem? I keep getting "bad gateway" when I try to connect. I'm pretty sure the service is offline.
Is there any news on what's going on? I know Google Drive went down a few weeks ago with the same set of error messages.
You can try this below Java code. This doesn't require any API Key. But please note, if you run it frequently, it will stop working as google blocks the IP Address from making future calls. You can use it on small data set. Not ideal solution, but if it is part of some batch job which runs in a while, then this approach may be acceptable to you.
public static String getSpellCheckedText(String Text) throws Exception {
String google = "http://www.google.com/complete/search?output=toolbar&q=";
String search = Text;
String charset = "UTF-8";
String spellCheckedText = Text;
URL url = new URL(google + URLEncoder.encode(search, charset));
Reader reader = new InputStreamReader(url.openStream(), charset);
BufferedReader bufReader = new BufferedReader(reader);
String line = bufReader.readLine();
StringBuffer sBuffer = new StringBuffer();
while (line != null) {
sBuffer.append(line).append("\n");
line = bufReader.readLine();
}
String content = sBuffer.toString();
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
InputSource is = new InputSource(new StringReader(content));
Document document = builder.parse(is);
NodeList nodeList = document.getElementsByTagName("suggestion");
if (nodeList != null && nodeList.getLength() > 0) {
org.w3c.dom.Node elm = nodeList.item(0);
if (elm.getNodeType() == Node.ELEMENT_NODE) {
Element suggestionElement = (Element)elm;
String suggestedString = suggestionElement.getAttribute("data");
if (suggestedString != null && suggestedString.trim().length() != 0) {
spellCheckedText = suggestedString.trim();
System.out.println(Text + " => "+ spellCheckedText);
}
}
}
return spellCheckedText;
}
I am also having this problem. I am getting a 503 Server Error. The problem is definitely on Google's end. (N.B. I am on Safari 6.0.3)
In specific...
503. That's an error.
The service you requested is not available at this time.
Service error -27. That’s all we know.
It seems as though Google is having some problems with their services. Hopefully they fix it soon!
Ditto, here. I really depend on it to check spelling in text boxes. It says "Unable to connect to Google spelling servers. Please check your internet connection and try again"

httpwebrequest in windows phone 8 app throws "The remote server returned an error: NotFound."?

i am developing an windows phone 8 app , in my app i am calling services and downloading some data into my app.
i am testing my app in windows phone 8 emulator, many times it throws this error :
"The remote server returned an error: NotFound."
This is how i have created and used my httpwebrequest :-
public async Task<string> ServiceRequest(string serviceurl, string request, string methodname)
{
string response = "";
try
{
var httpwebrequest = WebRequest.Create(new Uri(serviceurl)) as HttpWebRequest;
httpwebrequest.Method = "POST";
httpwebrequest.Headers["SOAPAction"] = "http://tempuri.org/" + iTestservice + "/" + methodname + "";
httpwebrequest.ContentType = "text/xml";
byte[] data = Encoding.UTF8.GetBytes(request);
using (var requestStream = await Task<Stream>.Factory.FromAsync(httpwebrequest.BeginGetRequestStream, httpwebrequest.EndGetRequestStream, null))
{
await requestStream.WriteAsync(data, 0, data.Length);
}
var httpTask = httpRequest(httpwebrequest);
var completeTask = await Task.WhenAny(httpTask, TaskEx.Delay(300000));
if (completeTask == httpTask)
return await httpTask;
else
httpwebrequest.Abort();
throw new TimeoutException("Service Timed Out");
}
catch (TimeoutException Tex)
{
throw Tex;
}
catch (Exception ex)
{
throw ex;
}
}
public async Task<string> httpRequest(HttpWebRequest request)
{
string received;
using (var response = (HttpWebResponse)(await Task<WebResponse>.Factory.FromAsync(request.BeginGetResponse, request.EndGetResponse, null)))
{
using (var responseStream = response.GetResponseStream())
{
using (var sr = new StreamReader(responseStream))
{
received = await sr.ReadToEndAsync();
}
}
}
return received;
}
i am really not able to figure what was the issue
Please note :-
i tried to open the site (service URL which my app is trying to access) in my emulator browser , it opened correctly , i wasn't facing any issues.
1)is that the problem with my code, if so i request you please correct me ??
2)is this any emulator issue or any connectivity issue ??
3)is this any certification issue opening in emulator ??
Even after a long research to how to fix the issue i was not able to fix it .
Please Help me out.
Thanks in Advance.
I have come across this issue when the webservice requests take longer than 60 seconds. I have read reports that the emulator does not throw this error, but only an actual device. In my experience however, I have had this happen on both emulator and device. This is a default timeout setting that cannot be altered, even if you change it in the config. This issue has been around since WP7.
I've only found this question asked/blogged about once elsewhere. Seems that not a lot of people have picked this up.
AFAIK, Microsoft are aware of this, but don't plan on fixing it. (Proven by the fact that it has been around since WP7, and wasn't fixed for WP8). My guess is that they are of the opinion that web calls shouldn't be taking longer than 60 seconds in any case.
I just resolved it adding empty credentials to https requests, like this
httpwebrequest.Credentials = new NetworkCredential("", "");
here he explains why
http://blog.toetapz.com/2010/11/15/windows-phone-7-and-making-https-rest-api-calls-with-basic-authentication/