I have a Xamarin IOS app that uses remote notifications with actions. When an action button is pressed, I want to post a message back to the server to record the response. This is mostly working. If the app is active it always works. If the app is in the background then I am sometimes getting the following exception:
System.Net.Http.HttpRequestException: The network connection was lost. ---> Foundation.NSErrorException: Error Domain=NSURLErrorDomain Code=-1005 "The network connection was lost." UserInfo={_kCFStreamErrorCodeKey=-4, NSUnderlyingError=0x2815e27c0 {Error Domain=kCFErrorDomainCFNetwork Code=-1005 "(null)" UserInfo={NSErrorPeerAddressKey={length = 16, capacity = 16, bytes = 0x100201bb0d42d4cd0000000000000000}, _kCFStreamErrorCodeKey=-4, _kCFStreamErrorDomainKey=4}}, _NSURLErrorFailingURLSessionTaskErrorKey=LocalDataTask <8A9B9110-D44C-46F5-B67E-B11231D82319>.<18>, _NSURLErrorRelatedURLSessionTaskErrorKey=(
"LocalDataTask <8A9B9110-D44C-46F5-B67E-B11231D82319>.<18>"
), NSLocalizedDescription=The network connection was lost., NSErrorFailingURLStringKey=https://callservice-v2.azurewebsites.net/api/callaction, NSErrorFailingURLKey=https://callservice-v2.azurewebsites.net/api/callaction, _kCFStreamErrorDomainKey=4}
--- End of inner exception stack trace ---
at System.Net.Http.NSUrlSessionHandler.SendAsync (System.Net.Http.HttpRequestMessage request, System.Threading.CancellationToken cancellationToken) <0x105b568a0 + 0x009a3> in :0
at System.Net.Http.HttpClient.FinishSendAsyncBuffered (System.Threading.Tasks.Task`1[TResult] sendTask, System.Net.Http.HttpRequestMessage request, System.Threading.CancellationTokenSource cts, System.Boolean disposeCts) <0x105a960c0 + 0x005f4> in <692b89da4aac4c12a3ac3af90678ac25#21125a282fd7860e37414196dba0c548>:0
at Dialer.Models.HttpDataServerClient.PostAsync (System.String api, System.Object message) <0x105f01a70 + 0x0047b> in <8e7629d69d3341bfa512d35c83fa84e0#21125a282fd7860e37414196dba0c548>:0
I have a UNUserNotificationCenterDelegate that has the following method:
public override void DidReceiveNotificationResponse(UNUserNotificationCenter center, UNNotificationResponse response, Action completionHandler)
{
try
{
_logger.TraceInfo($"DidReceiveNotificationReponse entered");
var userInfo = response.Notification.Request.Content.UserInfo;
var token = GetUserInfoItem(userInfo, "CallToken");
var subscriberPhoneNumber = GetUserInfoItem(userInfo, "SubscriberPhoneNumber");
var clientCallingNumber = GetUserInfoItem(userInfo, "ClientCallingNumber");
var clientDialedNumber = GetUserInfoItem(userInfo, "ClientDialedNumber");
_logger.TraceInfo($"Notification received, action: {response.ActionIdentifier}, token: {token}, phone #: {subscriberPhoneNumber}");
// Take action based on Action ID
switch (response.ActionIdentifier)
{
case "accept-call":
_callActionsHandler.SendAction(token, subscriberPhoneNumber, CallActions.Accept);
break;
case "send-to-voice-mail":
_callActionsHandler.SendAction(token, subscriberPhoneNumber, CallActions.VoiceMail);
break;
}
// Save the incoming call in the call history
_callHistoryAccess.AddCallToHistory(
new CallHistoryInstance()
{
CallerIdNumber = clientDialedNumber,
CallTime = DateTime.UtcNow,
CustomerPhoneNumber = clientCallingNumber,
Type = CallHistoryInstance.CallType.Inbound
});
}
catch (Exception ex)
{
_logger.TraceException($"An exception occurred while processing the notification", ex);
}
// Inform caller it has been handled
completionHandler();
}
The important thing here is the _callActionsHandler.SendAction call. That code is here:
public void SendAction(string callToken, string subscriberPhoneNumber, CallActions action)
{
Task.Run(async () =>
{
await SendActionAsync(new CallActionMessage(subscriberPhoneNumber, action, callToken));
});
}
private async Task SendActionAsync(CallActionMessage msg)
{
_logger.TraceInfo($"Registering call action for {msg.CallToken} to {msg.CallAction}");
var result = await _client.PostAsync(Constants.CallActionsApi, msg);
if (result != 200)
{
throw new CallActionsException($"HTTP status {result}");
}
}
This code has a wrapper around HttpClient. The PostAsync method is here:
public async Task<int> PostAsync(string api, object message)
{
var apiUrl = Constants.DefaultAppApi + api;
var contentText = JsonConvert.SerializeObject(message);
var content = new StringContent(contentText, Encoding.UTF8, "application/json");
var backOff = 10;
var retryCount = 5;
HttpResponseMessage response = null;
for (var attempt = 1; attempt <= retryCount; attempt++)
{
_logger.TraceInfo($"DataServerClient Post message: {message.GetType().Name}, attempt = {attempt}");
try
{
response = await _client.PostAsync(apiUrl, content);
}
catch (Exception ex)
{
if (attempt == retryCount)
_logger.TraceException($"DataServerClient Post failed", ex);
}
if (response != null && response.IsSuccessStatusCode)
{
_logger.TraceInfo($"DataServerClient post was successful at retry count: {attempt}");
break;
}
backOff *= 2;
await Task.Delay(backOff);
}
return (int)response.StatusCode;
}
I suspected an issue with the await and possibly needing a ConfigureAwait(). I have experimented with both ConfigureAwait(true) and ConfigureAwait(false) with no success. The results are very similar.
I am at a loss right now for why this is failing. Can anyone provide some information here why this is failing? Or, does anyone have code that does an HTTP post in response to a notification action?
I am new to xamarin and Rest API.
I am Trying to call Rest API from Xamrine IOS code as follow. My moto is to get List(From API) and Display in list view(Device). But it is giving me error "Bad Request". but when put same URL in POSTMAN , gives me proper response. Please help me out here.
Postman Call Image
Call from Postman
URL: http://localhost/MobileAppAPI/
Client Code:
static List<AuditModel> _audits = new List<AuditModel>();
public static string GetAudits()
{
string URL = "http://localhost/MobileAppAPI/api/Values/Get?id=1000";
string data = CreateObject(URL);
return APIHelper.APIHelper.CreateObject(URL);
}
public static string CreateObject(string URL)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(URL);
request.Method = "GET";
request.ContentType = "application/json";
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3;
try
{
using (Stream webStream = request.GetRequestStream())
using (StreamWriter requestWriter = new StreamWriter(webStream, System.Text.Encoding.ASCII))
{
requestWriter.Write("");
}
WebResponse webResponse = request.GetResponse();
using (Stream webStream = webResponse.GetResponseStream())
{
if (webStream != null)
{
using (StreamReader responseReader = new StreamReader(webStream))
{
string response = responseReader.ReadToEnd();
return response;
}
}
}
}
catch (Exception e)
{
Console.Out.WriteLine("-----------------");
Console.Out.WriteLine(e.Message);
return e.Message;
}
return "";
}
API Code:
// GET api/values/5
public string Get(int id)
{
return "value";
}
Exception:
Unhandled Exception:
System.Net.WebException: Error: ConnectFailure (Connection refused)
I am getting an error
javax.net.ssl.SSLHandshakeException: Connection closed by peer
when i am trying to access a HTTPS url.
my code is:
private void executeHTTRequestVerifyingLogin(String userid, String pwd, String key) throws Exception {
String strReturn = "";
BufferedReader in = null;
HttpClient hc = CUtils.getNewHttpClient();
HttpPost hp = new HttpPost(CGlobalVariables.VERIFYING_LOGIN);
try {
hp.setEntity(new UrlEncodedFormEntity(getNameValuePairs_Login(userid, pwd, key), HTTP.UTF_8));
HttpResponse response = hc.execute(hp);
in = new BufferedReader(new InputStreamReader(response.getEntity()
.getContent()));
StringBuffer sb = new StringBuffer("");
String data = "";
while ((data = in.readLine()) != null)
sb.append(data);
in.close();
setVerifyingLoginValue(sb.toString());
} catch (Exception e) {
throw e;
}
}
My code is working upto api level 23. I don't know why this exception is thrown in Nougat(Android 7.0) only.
This question already has answers here:
httpclient exception "org.apache.http.conn.ConnectionPoolTimeoutException: Timeout waiting for connection"
(10 answers)
Closed 8 years ago.
I use Multi-thread to scan the different URL in the same time in java. There was the bug,if the sum of request time exceed 100,000. I have already close which i should close. Here the code from my servlet
private String proyGetHttp(String url) throws ParseException, IOException,
InterruptedException {
String content = "";
getMethod = new HttpGet(url);
HttpResponse response = null;
HttpEntity httpEntity = null;
boolean success = false;
while (!success) {
System.out.println("url:" + url + ",connect...");
try {
response = client.execute(getMethod);
httpEntity = response.getEntity();
StringBuffer sb = new StringBuffer();
if (httpEntity != null) {
BufferedReader in = null;
InputStream instream = httpEntity.getContent();
try {
in = new BufferedReader(new InputStreamReader(instream));
String lineContent = "";
while(lineContent != null){
sb.append(lineContent);
lineContent = in.readLine();
}
} catch (Exception ex)
getMethod.abort();
throw ex;
} finally {
// Closing the input stream will trigger connection release
try { instream.close(); in.close();} catch (Exception ignore) {}
}
}
content = sb.toString();
success = true;
System.out.println("connect successfully...");
} catch (Exception e) {
e.printStackTrace();
getMethod.abort();
System.out.println("connect fail, please waitting...");
Thread.sleep(sleepTime);
}finally{
getMethod.releaseConnection();
}
}
return content;
}
Here code create the default client
PoolingClientConnectionManager cm = new PoolingClientConnectionManager();
cm.setMaxTotal(100);
DefaultHttpClient client = null;
client = new DefaultHttpClient(cm);
client.getParams().setParameter("http.protocol.cookie-policy", CookiePolicy.BROWSER_COMPATIBILITY);
client.getParams().setParameter(HttpConnectionParams.CONNECTION_TIMEOUT, 5000);
I have the same problem and I found the fix. This timeout is because of a connection leak. In my case, I'm using httpDelete method and not consuming the response. Instead, I'm checking the status of the response.
The fix is, the response entity need to be consumed. In order to ensure the proper release of system resources, one must close the content stream associated with the entity.
So I used EntityUtils.consumeQuietly(response.getEntity()); which ensures that the entity content is fully consumed and the content stream, if exists, is closed.
This is my code where the connection problem occuring.
HttpConnection is not getting a response from an connection obj in a input stream. The occuring error is:
Datagram(ConnectionBase).receive (Datagram) line 538
HttpConnection httpCon = null;
InputStream iStream = null;
String url = null;
String result = "";
public GetXmlHttp(String str)
{
url=str;
}
public String RESULT()
{
try
{
httpCon = (HttpConnection)Connector.open(url);
httpCon.setRequestMethod(HttpConnection.GET);
iStream = httpCon.openInputStream();//error is here
int httpResponse = httpCon.getResponseCode();
System.out.println("httpResponse code"+httpResponse);
System.out.println(httpResponse);
if(httpResponse != 200)
return null;
InputStreamReader in = new InputStreamReader(iStream);
StringBuffer sb=new StringBuffer();
char[] ch=new char[1020];
while(in.read(ch)!=-1)
{
sb.append(ch);
}
}
}
Posting the exception would help, but allso have a look at the API documentation for HttpConnection. There is sample code posted there for getting via an HttpConnection which has at least one significant difference from yours. getResponseCode is called before openInputStream:
void getViaHttpConnection(String url) throws IOException {
HttpConnection c = null;
InputStream is = null;
int rc;
try {
c = (HttpConnection)Connector.open(url);
// Getting the response code will open the connection,
// send the request, and read the HTTP response headers.
// The headers are stored until requested.
rc = c.getResponseCode();
if (rc != HttpConnection.HTTP_OK) {
throw new IOException("HTTP response code: " + rc);
}
is = c.openInputStream();