Check async connection to internet with Xam.Plugin.Connectivity - c#

I am trying to verify if my application has access to the internet, for this I occupy the Plugin Xam.Plugin.Connectivity in its version 4 ... The problem is that the answer I receive when Pinging a web is always false
This is the function that I call from the Login of my App ... as you can see it is an async function ...
private async void Login()
{
IsRunning = true;
IsEnabled = false;
var connection = await apiService.CheckConnection();
if (!connection.IsSuccess)
{
IsRunning = false;
IsEnabled = true;
await dialogService.ShowMessage("Error", connection.Message);
return;
}
}
and this is the class to verify the state of the connection
public async Task<Response> CheckConnection()
{
if (!CrossConnectivity.Current.IsConnected)
{
return new Response
{
IsSuccess = false,
Message = "Porfavor active su servicio de internet."
};
}
var isReachable = await CrossConnectivity.Current.IsRemoteReachable("www.google.com");
if (!isReachable)
{
return new Response
{
IsSuccess = false,
Message = "Verifique su conexion a internet."
};
}
else
{
return new Response
{
IsSuccess = true,
Message = "OK"
};
}
}
the problem occurs when it reaches the IsRecheable variable, it takes the false value and does not enter the if it follows ...
but it returns the state of the "null" connection immediately ...
and I'm also getting the following error
I have given the corresponding permissions to run the plugin
what's going on? Any call async that I'm doing wrong? any recommendation with this plugin? some help?

www.google.com is not a properly formatted URL as it is missing the protocol (i.e. http).
http://www.google.com would be a proper formatted URL that can be parsed into all of its URI components.
Example:
var isReachable = await CrossConnectivity.Current.IsRemoteReachable("http://www.google.com");
Note: IsRemoteReachable also can accept just a host name, so google.com or stackoverflow.com would also work.

Related

UWP AppServiceConnection not getting value

I'm trying to communicate between my host app and service via AppServiceConnection. I'm using the following code in my host app:
using (var connection = new AppServiceConnection())
{
connection.AppServiceName = extension.AppServiceName;
connection.PackageFamilyName = extension.PackageFamilyName;
var connectionStatus = await connection.OpenAsync();
if (connectionStatus == AppServiceConnectionStatus.Success)
{
var response = await connection.SendMessageAsync(requestMessage);
if (response.Status == AppServiceResponseStatus.Success)
returnValue = response.Message as ValueSet;
}
}
And my service code:
private async void OnRequestReceived(AppServiceConnection sender, AppServiceRequestReceivedEventArgs args)
{
var messageDeferral = args.GetDeferral();
var message = args.Request.Message;
var returnData = new ValueSet();
var command = message["Command"] as string;
switch (command)
{
case "ACTION":
var value = await AsyncAction();
returnData = new ValueSet { { "Value", JsonConvert.SerializeObject(value) } };
break;
default:
break;
}
await args.Request.SendResponseAsync(returnData);
messageDeferral.Complete();
}
This works some of the time, but other times the ValueSet (returnValue) is randomly empty when the host receives it. It has Value in it when returned in the service, but when I get the response in the host, nothing.
I've verified that the service is indeed setting the value, adding it to the ValueSet and returning it correctly.
Note that my service is receiving the request, the host is receiving the response and the response status is Success; a failed connection isn't the issue.
Sometimes this happens only once before requests start working again, other times it will happen ten times in a row.
The first working response after a failure always takes significantly longer than normal.
Also, I have no issues in the request from host to service. It's always service to host where the problem shows up.
Has anyone else run into this issue and figured it out?
In the process of creating a sample app I realized what the problem was. I was performing an asynchronous action (albeit a very short one) before my line var messageDeferral = args.GetDeferral();. It appears that this was allowing the background task to be closed before it had responded to the host. Simply moving that line to the beginning of the OnRequestReceived function fixed the problem for me.
So for anyone who runs into a similar issue, get your deferral before you do anything else! Spare yourself the pain I went through.

Limit Dns.GetHostAddresses by time

i'm writing a script that resolve ip address for domain using C#
the problem is that i have a lot of domains that does not resolve to an IP, so the code (Dns.GetHostAddresses) is running for a long time trying to resolve an IP for a domain that doesn't have an IP.
this is the code:
public string getIPfromHost(string host)
{
try
{
var domain = Dns.GetHostAddresses(host)[0];
return domain.ToString();
}
catch (Exception)
{
return "No IP";
}
}
what i want to do is if there is no IP after 1 sec i want to return "No IP"
how can i achieve that?
You can achieve this by using TPL(Task Parallel Library). You can create new task and wait for 1 sec, if this is succeed then return true otherwise false.
please use below code in getIPfromHost(string host) this method.
(This is solution for your question which needs to wait for 1 sec please ensure your previous method was working fine with your method implementation)
public string getIPfromHost(string host)
{
try
{
Task<string> task = Task<string>.Factory.StartNew(() =>
{
var domain = Dns.GetHostAddresses(host)[0];
return domain.ToString();
});
bool success = task.Wait(1000);
if (success)
{
return task.Result;
}
else
{
return "No IP";
}
}
catch (Exception)
{
return "No IP";
}
}

Async HTTP Request in Web Api

I have googled for this and have managed to find several links explaining the concept of Async HTTP Requests in C# and Web Api 2. However I failed to get any working examples of the same.
Just to clear the air, my requirement is as below.
When the client calls an API (which does long running processing), it must returns HTTP 202 (Accepted) as response almost immediately, and continue processing in the background. I am clear till this point. Below is my sample code as to how I have implemented the same. Where I am stuck is when this long processing task is complete in the background it must fire a callback to the same client and return with an HTTP 200 response. It may be possible that while the long processing task was executing in the background, the client has issued another concurrent request with different values.
Can anyone point me in the right direction. Is this possible only through code or would there be any settings to be implemnted at the IIS level. Appreciate your time and help in this.
Thanks to everyone in advance.
My Code so far.
public HttpResponseMessage Execute(string plugin, string pluginType, string grid, string version)
{
try
{
var type = this.LoadPlugin(plugin, pluginType, version);
if (type != null)
{
var method = type.GetMethod("Execute");
if (method != null)
{
new Task(() =>
{
// This line will take long to execute.
var filepath = method.Invoke(Activator.CreateInstance(type), new object[1] { grid });
// After this line it must invoke a callback to the client with the response as "filepath" and HTTP status code as 200
type = null;
}).Start();
}
else
{
return new HttpResponseMessage(HttpStatusCode.ServiceUnavailable);
}
}
else
{
return new HttpResponseMessage(HttpStatusCode.ServiceUnavailable);
}
}
catch (Exception ex)
{
return new HttpResponseMessage(HttpStatusCode.InternalServerError);
}
return new HttpResponseMessage(HttpStatusCode.Accepted);
}
private Type LoadPlugin(string plugin, string pluginType, string version)
{
Assembly assembly;
Type returnValue = null;
var pluginFile = new DirectoryInfo(this._pluginPath).GetFiles("*.dll")
.Where(file => FileVersionInfo.GetVersionInfo(file.FullName).OriginalFilename.ToUpper().Contains("TRANSFORMATION." + plugin.ToUpper()))
.OrderByDescending(time => time.LastWriteTime).FirstOrDefault();
if (pluginFile != null)
{
assembly = Assembly.LoadFrom(pluginFile.FullName);
AppDomain.CurrentDomain.Load(assembly.GetName());
returnValue = assembly.GetType("Transformation.Plugins." + pluginType);
assembly = null;
}
return returnValue;
}
I think you can solve this issue making your Web API method async:
public async Task<HttpResponseMessage> Execute(string plugin, string pluginType, string grid, string version)
{
// Your code here
}
Also, your task's invoke should be with await keyword, something like this:
await Task.Run(() =>
{
// Yor code here
});
You can have multiple await inside of your async method.
Let me know if this answer is useful.

Calling a method asynchronously using Task.Run

Can someone help me how to make the call to the method SendSms(textMessageItems) asynchronous? What is the best method/practice? I am presuming that Task.Run Async-Await can be used here since I am using .Net4.5 using MVC4 WebApi. But I would like to hear from the experts as I am new to this. I am using this code in my web Server which is in IIS7 and this method could take sometime to process and so would like to process it asynchronously so that the response can return right away to the caller.
Also since I am calling the SendSms inside a for loop would it cause any issue? Do you think I should pass it as a collection List and then process? Please advise.
using Twilio.Mvc;
using Twilio.TwiML.Mvc;
using Twilio.TwiML;
public class SmsController : ApiController
{
[HttpPost]
public HttpResponseMessage Post([FromBody]SmsRequest smsReq)
{
var response = new Twilio.TwiML.TwilioResponse();
//validation checks..
try
{
if ((txtMessageResponse != null) && (txtMessageResponse.SmsMessageInfo.Count > 0))
{
_smsStagingList = txtMessageResponse.SmsMessageInfo;
foreach (TextMessageStaging prepareTextMessageResponse in _smsStagingList)
{
smsDTO textMessageItems = new smsDTO();
textMessageItems.PhoneNumber = prepareTextMessageResponse.PhoneNumber;
textMessageItems.SmsMessage = prepareTextMessageResponse.SmsMessageBody;
isTxtMessageSent = SendSms(textMessageItems);
//If the messages were sent then no need to set the flag to be updated
if (isTxtMessageSent)
{
txtMessageStatusToBeUpdated = false;
}
}
return Request.CreateResponse(HttpStatusCode.OK, twilioResponse.Element);
}
else
{
//send error response
}
catch (Exception msgProcessingError)
{
//send error response again as processing error
}
finally
{
//set the outbound flag in the table
}
}
private bool SendSms(smsDTO textMessageItems)
{
bool isTxtMessageSent = false;
PushMessageRequest txtMessageRequest = new PushMessageRequest();
PushMessageResponse txtMessageResponse = null;
txtMessageRequest.SmsMessageInfo = new SendTextMessage(); //instantiate the dto
txtMessageRequest.SmsMessageInfo.ToPhone = textMessageItems.PhoneNumber;
txtMessageRequest.SmsMessageInfo.TextMessage = textMessageItems.SmsMessage;
try
{
using (ITextService textService = ObjectFactory.SendSmsMessage())
{
txtMessageResponse = textService.SendSmsMessage(txtMessageRequest);
}
isTxtMessageSent = txtMessageResponse.IsSuccessful;
}
catch (Exception ex)
{
isTxtMessageSent = false;
}
return isTxtMessageSent;
}
I recommend that you not use Task.Run. AFAIK, Twilio does not have an async API, so you should ask them about that. You could of course write your own, e.g., based on HttpClient.
would like to process it asynchronously so that the response can return right away to the caller
Please note that async does not change the HTTP protocol, as described on my blog. It is possible, but extremely dangerous, to return a response from ASP.NET while the request has not finished processing (also a link to my blog).

InvalidDataContractException using Azure Notification Hub

I'm pretty much copying this article about using the Windows Azure Notification Hub to send push notifications: http://www.windowsazure.com/en-us/manage/services/notification-hubs/notify-users-aspnet/
Unfortunately, I'm running into an InvalidDataContractException occurring in Microsoft.ServiceBus when I try to use the CreateWindowsNativeRegistrationAsync method. I can't see any difference in my code from the example and I'm not doing an serialisation. (about half way down the page):
UPDATE: Putting the same code in a console app with "http://test.com" as the channelURI causes an exception and the following error: "Unsupported channel uri: http://test.com"
public async Task<bool> NotificationRegistration(User user, NotificationRegistration reg)
{
var regs = await hubClient.GetRegistrationsByTagAsync(reg.InstallationID, 100);
bool updated = false;
bool firstRegistration = true;
RegistrationDescription registration = null;
foreach (var regDescription in regs)
{
if (firstRegistration)
{
regDescription.Tags = new HashSet<string>() { reg.InstallationID, user._id };
// We need to handle each platform separately.
switch (reg.Platform)
{
case "WP":
var winReg = regDescription as WindowsRegistrationDescription;
winReg.ChannelUri = new Uri(reg.ChannelUri);
registration = await hubClient.UpdateRegistrationAsync(winReg);
break;
}
updated = true;
firstRegistration = false;
}
else
{
// We shouldn't have any extra registrations; delete if we do.
await hubClient.DeleteRegistrationAsync(regDescription);
}
}
// Create a new registration.
if (!updated)
{
switch (reg.Platform)
{
case "WP":
//always fails here
registration = await hubClient.CreateWindowsNativeRegistrationAsync(reg.ChannelUri, new string [] { reg.InstallationID, user._id });
break;
}
}
}
Any guidance as to where I'm going wrong would be greatly appreciated....
From the platform it seems you are using WindowsPhone. If that is the case you have to create an MpnsRegistrationDescription. So you might be getting an exception because the CHannelURI is not a WIndows Store CHannelURI.
Let me know,
Elio

Resources