Multiple threads in POCO HttpClient? - networking

I am working on a project in C++, with POCO/NET. The Network code can be seen below:
URI uri("http://my.url.se" );
HTTPClientSession session(uri.getHost(), uri.getPort());
// prepare path
string path(uri.getPathAndQuery());
if (path. empty()) path = "/";
// send request
HTTPRequest req(HTTPRequest::HTTP_GET, path, HTTPMessage::HTTP_1_1);
req.set("Accept", "AcceptString");
req.set("Consumer", "ALL");
req.set("Contract", "ALL");
session.sendRequest(req);
// recieve response
HTTPResponse res;
istream &is = session.receiveResponse(res);
The application is working on both Android 2.3.6 (Samsung Galaxy Gio) and the latest Android version, but according to the following post (and developer.android):
https://stackoverflow.com/questions/15606791/android-httppost-freezes-and-crashes-app
a NetworkOnMainThreadException would be thrown on the newest Android version (Honeycomb or higher) if the Networking part would not be in a separate thread. I have not created a new thread, so my question is:
Can anyone confirm my assumption that it is implemented already/automatically uses a new thread in the Poco Net library?
Greatful for help!

Can anyone confirm my assumption that it is implemented
already/automatically uses a new thread in the Poco Net library?
HTTPClientSession will not run on a separate thread, you will have to do that explicitly. You can use Poco:: Thread, Task or Activity.

Related

Xamarin Android project cannot connect to localhost API

I have been working on this problem for quite some time. I've read the many similar posts and their solutions don't help me (many posts are old and stale). I have a new Xamarin project and a localhost API that I am testing to. Initially I installed our production API locally and it doesn't connect. So I created a smaller test API and have had varying results in connecting. Xamarin Android will not connect with a "Failed to connect to localhost:XXXXX" message. I built a WPF project and get the same results. However I can connect to outside public API's (github) with both. I can connect to my localhost with a Windows forms desktop app and successfully get & post. Postman and httprepl both connect locally and successfully get & post. A couple of the other things the other posts suggested are 1) Client handler to ignore SSL - doesn't work, 2) Use the emulator's browser to connect to localhost - cannot connect. (this might be exposing where the problem really is but not sure).
Also The debugger seems to be behaving oddly. When the debugger gets to the HttpResponseMessageresponse.... line it rarely makes it to the next line so I cannot inspect the statuscode. The block I have below is in a try/catch and rarely makes it to the catch if the connection truly fails. Sometimes it will be caught at the catch and that's how I get the "failed to connect" message. Another developer here has run the project on his computer and gets the same results/errors on his computer.
HttpResponseMessage response = await client.SendAsync(request);
var Statuscode = response.StatusCode;
if (response.IsSuccessStatusCode)
{
var jsonbody = response.Content.ReadAsStringAsync().Result;
var ResponseBody = JsonConvert.DeserializeObject(response.Content.ReadAsStringAsync().Result);
}
else
{
string oops = "Nothing";
}
I seem to be running out of options and am looking for any advice.
Thanks in advance.

Microsft Graph Helper fails in the response

I have an ASP.Net App and I recent added login with office 365 consuming Graph Api. It works fine in my local machine and I get token and user info from the Graph Api. But when I deploy the solution in production server I m getting an error in the response from the API. Production server is a virtual windows server 2016
var graphClient = new GraphServiceClient(
new DelegateAuthenticationProvider(
async (requestMessage) =>
{
requestMessage.Headers.Authorization =
new AuthenticationHeaderValue("Bearer", accessToken);
}));
var user = await graphClient.Me.Request()
.Select(u => new {
u.DisplayName,
u.Mail,
u.UserPrincipalName
})
.GetAsync();
This is the code to get the info from the user, after calling this method I get an exeption with the next error:
Method not found: 'System.Threading.Tasks.Task`1<!!0>Microsoft.Graph.BaseRequest.SendAsyc(System.Object, System.Threading.CancellationToken, System.Net.Http.HttpCompletionOption)'.
The most rare is that this happen only in the production server, in test server and local machine it works fine. Thanks in advance!
You are likely missing some dependencies. make sure in your bin folder of the app in production you see the Microsoft.Graph.Core.dll file, sometimes when you deploy things it doesn't update the packages for whatever reason. you should see such a file in your test server and local machines. if not there, copy it over. if it is there, then check that you have the same .net versions installed in prod as you have in other environments. also make sure that in your development environment you have the latest graph api sdk being used.
Finally the solution to solve this problem was updating the .Net framework version in the server.

Web Service Call Stopped Processing

I have a bunch of Xamarin iOS applications running on our Corporate iPhones and iPads. I recently upgraded my Visual Studio and Mac Book Pro to latest release version and my applications are no longer PROCESSING data from my web service correctly. I did not change version of Xamarin.Forms
VS 2017 Version 15.9.13
Xamarin.Forms.2.4.0.282
The web services are http. I have my NSAppTransportSecurityNSAllowsArbitraryLoads
set to allow http.
I am using the flag true to generate the Task.Factory.FromAsync methods in the Web Service Reference.cs file.
I could go on with describing how everything works if anyone needs more info.
Luckily, my Mac Book Pro Simulator has old and new versions of my apps installed in different iPhone/iPad devices for me to test. I installed fiddler to make sure all the requests/responses were the same. My old App in one device works and my new App in a different device fails. Same thing for ALL of my Applications. Old one works and new one fails.
When I review fiddler, the requests and responses are all working the same:
Request is made
App gets an authentication prompt
Authentication happens
Request returns code 200 with the data requested
The only difference in Fiddler is that two of the headers are in a different order: Working one has SOAPAction first and Content-Type next, the one failing has Content-Type and then SOAPAction. I am grasping at straws here because the order of these headers should not matter.
This is for all the applications. The only problem is that my new applications are ignoring the response. It is almost like the endMethod function from the parameter passed to FromAsync is never called.
This is the function call:
public async Task<ProcessLogon> ExecuteSaveLogon(DeviceItem DeviceItem)
{
ResultLogin = new ProcessLogon();
try
{
var ProcessLogon = await Task<WebServiceTrading.ProcessLogon>.Factory.FromAsync(serviceTrading.BeginSaveLogon, serviceTrading.EndSaveLogon, ToServiceTrading(DeviceItem), TaskCreationOptions.None);
ResultLogin = FromServiceTrading(ProcessLogon);
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(#"ExecuteSaveLogon ERROR {0}", ex.Message);
}
return ResultLogin;
}
Does anyone know of any DEBUG or LOGGING tools that I could use to find out why my successful response is lost?

Do I need a new PayPal API to support TLS 1.2 on .Net server?

I am running ASP.Net 4.5, but using a very old version of the PayPal SOAP api. The reference is to paypal_base.dll with a reported version of 4.3.1.0. The code that calls the API has "using" statements that reference:
com.paypal.sdk.services
com.paypal.soap.api.
I have verified at the point where the call to the PayPal api is made, that this value
System.Net.ServicePointManager.SecurityProtocol
includes both ssl3 and tls1.2.
I am pointing at the "sandbox" mode.
But when the setExpressCheckout call is made, I get a runtime exception that says:
The request was aborted: Could not create SSL/TLS secure channel.
I have downloaded the PayPal API Samples project and using the same sandbox credentials, it works. Looking in Fiddler, the calls are nearly identical except the samples API call goes to api-3t.sandbox.paypal.com, while my code goes to api-aa.sandbox.paypal.com, but according to the documentation on TLS 1.2 readyness, both apis should work. I don't see anywhere in either API to set the endpoint other than switching between "live" and "sandbox".
In the fiddler response, both show:
"A SSLv3-compatible ServerHello handshake was found. Fiddler extracted the parameters below.
Version: 3.3 (TLS/1.2)"
And the responses are identical except for the "random" parameter. So the old API call is using TLS 1.2
My code and the Samples API code are only slightly different, the sample uses:
SetExpressCheckoutRequestType request = new SetExpressCheckoutRequestType();
populateRequestObject(request); //populate request data
SetExpressCheckoutReq wrapper = new SetExpressCheckoutReq();
wrapper.SetExpressCheckoutRequest = request;
Dictionary<string, string> configurationMap = Configuration.GetAcctAndConfig(); //set merchant config
PayPalAPIInterfaceServiceService service = new PayPalAPIInterfaceServiceService(configurationMap);
SetExpressCheckoutResponseType setECResponse = service.SetExpressCheckout(wrapper); //make the call
Where my (again, very old code looks like this):
CallerServices caller = new CallerServices();
caller.APIProfile = SetProfile.ApplicationProfile; //set merchant config
SetExpressCheckoutRequestType pp_request = new SetExpressCheckoutRequestType();
// Create the request details object
pp_request.SetExpressCheckoutRequestDetails = new SetExpressCheckoutRequestDetailsType();
pp_request.SetExpressCheckoutRequestDetails.PaymentAction = paymentAction;
pp_request.SetExpressCheckoutRequestDetails.PaymentActionSpecified = true;
pp_request.SetExpressCheckoutRequestDetails.OrderTotal = new BasicAmountType();
pp_request.SetExpressCheckoutRequestDetails.OrderTotal.currencyID = currencyCodeType;
pp_request.SetExpressCheckoutRequestDetails.OrderTotal.Value = paymentAmount;
pp_request.SetExpressCheckoutRequestDetails.CancelURL = cancelURL;
pp_request.SetExpressCheckoutRequestDetails.ReturnURL = returnURL;
return (SetExpressCheckoutResponseType) caller.Call("SetExpressCheckout", pp_request); //do the call
The sample code works, my code throws the SSL/TLS error. I tried upgrading to the latest SDK, but so much has changed, it will be quite a large effort to migrate all that code.
From fiddler, it seems to be using TLS 1.2 even with the old API, but I get a runtime exception about the SSL/TLS connection. Is it because of the different endpoint? Is the old API just too old?
Thanks in advance for any help - I would love to avoid migrating all that ancient code!.
EDIT: I should mention I am using the UserName/Password/Signature credentials, not certificate based credentials.
As TLS1.2 is supported in .Net4.5 but it is not a default protocol. you need to opt-in to use it. The following code will make TLS 1.2 default, make sure to execute it before making a connection to secured resource:
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12
I was having a similar issue, with a PP Sandbox credentialing "HttpWebRequest" in C# Web Application 4.5, receiving the following error: "You must write ContentLength bytes to the request stream before calling [Begin]GetResponse".
I read this Q/A and applied the ServicePointManager reference from above answer - as the first line in my HttpWebRequest call method, and it worked. Thanks to all.
FYI, the example code I am building is from //learn.microsoft.com, "Getting Started with ASP.NET 4.5 Web Forms and Visual Studio 2017".

Blackberry http connection not working on 3g

hi friends i'm a newbie in blackberry programming and have managed to make a small application... The application downloads an xml file through http and parses it and displays it on the screen... now the problem is that though it works fine on my simulator... the client complains that he's getting an error in connection if he connects it through 3G... do i need to add anything other than the following...
// Build a document based on the XML file.
url = <my clients url file>;
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
hc = (HttpConnection)Connector.open(url+";deviceside=true");
hc.setRequestMethod(HttpConnection.GET);
InputStream inputStream = hc.openInputStream();
hc.getFile();
Document document = builder.parse(inputStream);
hc.close();
inputStream.close();
Do i need to add anything to make it download http content through 3G also??
Specifying "deviceside=true" requires the device have the APN correctly configured, or you include APN specification in the URL. Have a look at this video.
You need to be able to detect what sort of connection the device is using as was said above deviceside=true works only for APN. If you want to just test it out try using
;deviceside=false //for mds
;deviceside=false;ConnectionType=mds-public //for bis-b
;interface=wifi //for wifi

Resources