How to get result from UploadValuesAsync - WebClient C# - c#

I'm doing on a Xamarin Android app and I have a class with bunch of methods for interaction with web service. Every of these methods should return something (true/false to be sure if the database transaction is completed or some other data from database). For example, I have a method:
public bool AddNewUser(User user)
{
WebClient client = new WebClient();
Uri url = new Uri(web + "AddNewUser.php");
NameValueCollection parameters = new NameValueCollection();
bool result = false;
parameters.Add("FirstName", user.FirstName);
parameters.Add("LastName", user.LastName);
parameters.Add("Email", user.Email);
parameters.Add("MobileNumber", user.MobileNumber);
client.UploadValuesAsync(url, parameters);
client.UploadValuesCompleted += (object sender, UploadValuesCompletedEventArgs e) =>
{
if (Encoding.UTF8.GetString(e.Result) == "true")
{
result = true;
}
};
return result;
}
This method returns the result as true or false(if the transaction is completed or if the transaction is not completed).
This is my PHP file:
<?php
require_once(dirname(__FILE__).'/Connection.php');
if(isset($_POST['FirstName']) && isset($_POST['LastName']) && isset($_POST['Email']) && isset($_POST['MobileNumber']))
{
$firstName = $_POST['FirstName'];
$lastName = $_POST['LastName'];
$email = $_POST['Email'];
$mobileNumber = $_POST['MobileNumber'];
$connection = new Connection();
$connection->GetConnection();
if(!$connection->conn)
{
echo 'Error: '.mysqli_connect_error();
}
else
{
$sql = 'INSERT INTO tb_user(name,lastname,mail,phone) VALUES ("'.$firstName.'","'.$lastName.'","'.$email.'","'.$mobileNumber.'")';
$result = mysqli_query($connection->conn,$sql);
if(!$result)
{
echo 'Error: '.mysqli_error($connection->conn);
}
else
{
echo true;
}
}
}
?>
But app crashes with no error and also user is not added. Now, I'm wondering what I'm doing wrong.
Thank you in advance.
UPDATE:
Error in UploadValuesCompletedEventArgs is equal to null. Is then something wrong with my PHP file?
UPDATE 2:
So, I used only UploadValues instead of UploadValuesAsync,like this:
WebClient client = new WebClient();
Uri url = new Uri(web + "AddNewUser.php");
NameValueCollection parameters = new NameValueCollection();
bool result = false;
parameters.Add("FirstName", user.FirstName);
parameters.Add("LastName", user.LastName);
parameters.Add("Email", user.Email);
parameters.Add("MobileNumber",user.MobileNumber);
byte[] r = client.UploadValues(url,parameters);
if (Encoding.UTF8.GetString(r) == "true")
{
result = true;
}
return result;
In android device logging this error is written:
FATAL EXCEPTION: main
java.lang.RuntimeException: java.lang.reflect.InvocationTargetException

Related

result of call back function return to view from model asynchronously

i have one call back function in my model. i.e void method.
how to pass that result to view.
my problem is while uploading file to amazon s3, it's returning progress value. i need to get that value in view.
my code as follows
public bool sendMyFileToS3(EmployeeModel e, string bucketName, string subDirectoryInBucket)
{
IAmazonS3 client = new AmazonS3Client(RegionEndpoint.USEast2);
TransferUtility utility = new TransferUtility(client);
TransferUtilityUploadRequest request = new TransferUtilityUploadRequest();
if (subDirectoryInBucket == "" || subDirectoryInBucket == null)
{
request.BucketName = bucketName; //no subdirectory just bucket name
}
else
{ // subdirectory and bucket name
request.BucketName = bucketName + #"/" + subDirectoryInBucket;
}
try
{
request.Key = RandomString() + Path.GetExtension(e.File.FileName); //file name up in S3
request.InputStream = e.File.InputStream;
request.CannedACL = S3CannedACL.PublicRead;
request.UploadProgressEvent += new EventHandler<UploadProgressArgs>(UploadFile_ProgressBar); //call bcak function
utility.Upload(request);
}
catch(AmazonS3Exception)
{
throw;
}
//commensing the transfer
//Generate link with expiry date.
Amazon.S3.Model.GetPreSignedUrlRequest aa = new Amazon.S3.Model.GetPreSignedUrlRequest();
aa.BucketName = request.BucketName;
aa.Key = request.Key;
aa.Expires = new DateTime().AddDays(2);
string url = client.GetPreSignedURL(aa);
url = url.Remove(url.IndexOf('?'));
return true;
}
public void UploadFile_ProgressBar(object sender, UploadProgressArgs e)
{
int pctProgress = (int)(e.TransferredBytes * 100 / e.TotalBytes);
}
every second "pctProgress" this parameter is replacing with new value. when ever replacing with new value it should pass to view.
how to do this.
please any suggestions.

Remembering log in credentials/permissions UWP/C# (Microsoft Cloud API)

I'm creating an app that access the Microsoft Cloud API to get health data. It uses OAuth to log in when you hit the Sign In Button
private void signinButton_Click(object sender, RoutedEventArgs e)
{
UriBuilder uri = new UriBuilder("https://login.live.com/oauth20_authorize.srf");
var query = new StringBuilder();
query.AppendFormat("redirect_uri={0}", Uri.EscapeDataString(RedirectUri));
query.AppendFormat("&client_id={0}", Uri.EscapeDataString(ClientId));
query.AppendFormat("&scope={0}", Uri.EscapeDataString(Scopes));
query.Append("&response_type=code");
uri.Query = query.ToString();
this.webView.Visibility = Visibility.Visible;
this.webView.Navigate(uri.Uri);
}
This brings up a webView with the page to log in using Microsoft credentials. Once completed, it leads to this:
private async void WebView_NavigationCompleted(WebView sender, WebViewNavigationCompletedEventArgs args)
{
//
// When the web view navigates to our redirect URI, extract the authorization code from
// the URI and use it to fetch our access token. If no authorization code is present,
// we're completing a sign-out flow.
//
if (args.Uri.LocalPath.StartsWith("/oauth20_desktop.srf", StringComparison.OrdinalIgnoreCase))
{
WwwFormUrlDecoder decoder = new WwwFormUrlDecoder(args.Uri.Query);
var code = decoder.FirstOrDefault((entry) => entry.Name.Equals("code", StringComparison.OrdinalIgnoreCase));
var error = decoder.FirstOrDefault((entry) => entry.Name.Equals("error", StringComparison.OrdinalIgnoreCase));
var errorDesc = decoder.FirstOrDefault((entry) => entry.Name.Equals("error_description", StringComparison.OrdinalIgnoreCase));
// Check the code to see if this is sign-in or sign-out
if (code != null)
{
// Hide the browser again, no matter what happened...
sender.Visibility = Visibility.Collapsed;
if (error != null)
{
this.responseText.Text = string.Format("{0}\r\n{1}", error.Value, errorDesc.Value);
return;
}
var tokenError = await this.GetToken(code.Value, false);
if (string.IsNullOrEmpty(tokenError))
{
this.responseText.Text = "Successful sign-in!";
this.signoutButton.IsEnabled = true;
this.signinButton.IsEnabled = false;
this.getProfileButton.IsEnabled = true;
this.getDevicesButton.IsEnabled = true;
this.getActivitiesButton.IsEnabled = true;
this.getDailySummaryButton.IsEnabled = true;
this.getHourlySummaryButton.IsEnabled = true;
}
else
{
this.responseText.Text = tokenError;
}
}
else
{
this.responseText.Text = "Successful sign-out!";
this.signoutButton.IsEnabled = false;
this.signinButton.IsEnabled = true;
this.getProfileButton.IsEnabled = false;
this.getDevicesButton.IsEnabled = false;
this.getActivitiesButton.IsEnabled = false;
this.getDailySummaryButton.IsEnabled = true;
this.getHourlySummaryButton.IsEnabled = false;
}
}
}
private async Task<string> GetToken(string code, bool isRefresh)
{
UriBuilder uri = new UriBuilder("https://login.live.com/oauth20_token.srf");
var query = new StringBuilder();
query.AppendFormat("redirect_uri={0}", Uri.EscapeDataString(RedirectUri));
query.AppendFormat("&client_id={0}", Uri.EscapeDataString(ClientId));
query.AppendFormat("&client_secret={0}", Uri.EscapeDataString(ClientSecret));
if (isRefresh)
{
query.AppendFormat("&refresh_token={0}", Uri.EscapeDataString(code));
query.Append("&grant_type=refresh_token");
}
else
{
query.AppendFormat("&code={0}", Uri.EscapeDataString(code));
query.Append("&grant_type=authorization_code");
}
uri.Query = query.ToString();
var request = WebRequest.Create(uri.Uri);
try
{
using (var response = await request.GetResponseAsync())
{
using (var stream = response.GetResponseStream())
{
using (var streamReader = new StreamReader(stream))
{
var responseString = streamReader.ReadToEnd();
var jsonResponse = JObject.Parse(responseString);
this.creds.AccessToken = (string)jsonResponse["access_token"];
this.creds.ExpiresIn = (long)jsonResponse["expires_in"];
this.creds.RefreshToken = (string)jsonResponse["refresh_token"];
string error = (string)jsonResponse["error"];
return error;
}
}
}
}
catch (Exception ex)
{
return ex.Message;
}
}
I don't want users to have to accept the permissions every time the app is launched. Is there a way to save credentials locally so that it automatically authenticates on launch? Thanks!
You can use
Windows.Storage.ApplicationData.Current.LocalSettings
This process good described by this answer Best Way to keep Settings for a WinRT App?
The code in link identity to UWP
Store the needed oauth parts in the credential locker API. Never store these kind of information in the normal settings API.
On start read the oauth information and use the refreshtoken to get a new access token.
More Information here.
https://msdn.microsoft.com/en-us/library/windows/apps/mt270189.aspx

HTTP Post Request with Windows Phone Webclient C#

I have a php file on my local server which looks like this: (The database variables are in the config.php and are correct!)
<?php
require_once "config.php";
try
{
$con = new PDO("mysql:host=".$db_host.";dbname=".$db_name,$db_user,$db_password);
$con->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
catch (PDOException $e)
{
echo "Error: ".$e->getMessage();
exit();
}
if (empty($_POST["number"]) || !isset($_POST["number"]))
{
echo "Error: no number!";
exit();
}
else if (empty($_POST["password"]) || !isset($_POST["password"]))
{
echo "Error: no password!";
exit();
}
else
{
$number = $_POST["number"];
$password = md5($_POST["password"]);
$salt = sha1($_POST["password"]);
}
if (!empty($_POST["login"]))
{
$sql = $con->prepare("SELECT COUNT(`ID`) FROM ".$db_table_login_students." WHERE `number` = ? AND `password` = ? AND `salt` = ? AND user_deleted=0");
$sql->bindParam(1, $number);
$sql->bindParam(2, $password);
$sql->bindParam(3, $salt);
$sql->execute();
if($sql->fetchColumn() > 0)
{
$login = array('Login' => 'Yes');
echo json_encode($login);
$_sql = $con->prepare("UPDATE ".$db_table_login_students." SET last_login=NOW() WHERE number = ?");
$_sql->bindParam(1, $matrikelnummer);
$_sql->execute();
exit();
}
else
{
$login = array('Login' => 'No');
echo json_encode($login);
exit();
}
}
?>
And now I want to make a HTTP Post Request with Windows Phone in C# and it looks now like this:
void PostJsonRequestWebClient()
{
WebClient webclient = new WebClient();
Uri uristring = null;
uristring = new Uri("http://localhost/login.php?");
webclient.Headers["ContentType"] = "application/x-www-form-urlencoded";
string WebUrlRegistration = "";
string JsonStringParams = "login=yes&number=4340490&password=test";
webclient.UploadStringCompleted += wc_UploadStringCompleted;
webclient.UploadStringAsync(uristring, "POST", JsonStringParams);
}
private void wc_UploadStringCompleted(object sender, UploadStringCompletedEventArgs e)
{
try
{
if (e.Result != null)
{
string response = e.Result.ToString();
textblock1.Text = response;
}
}
catch
{
}
}
The login data with number and password are correct in my database. When I make a Get request instead of a Post I became as answer from the php script "{Login:Yes}". But when I make a Post request like the one above I became "Error: no number!". So I think the Post query string is false, but I find nothing. Can anybody help me?
Maybe, the HTTP Header should be Content-Type instead of ContentType.

Getting internet connection status from WinRT

Below if the code I've been using for some time to get the connection status of the device that my store app in running on. What appears to have happened recently is, whilst it still finds the correct connection profile, it returns the level as Local, rather than Internet access.
IReadOnlyList<ConnectionProfile> p = NetworkInformation.GetConnectionProfiles();
foreach (ConnectionProfile prof in p)
{
NetworkConnectivityLevel lev = prof.GetNetworkConnectivityLevel();
if (lev == NetworkConnectivityLevel.InternetAccess)
{
return true;
}
}
return false;
Can anyone tell me why this might be, and how I can persuade it that I do, in fact, have a working internet connection (which I can prove by being able to post this question :-) )?
try this one
private bool roaming;
private string connectionProfileInfo;
private async Task<bool> IsConnectedToInternet()
{
HttpWebRequest webReq;
HttpWebResponse resp = null;
// HttpStatusCode respcode;
Uri url = null;
url = new Uri("http://www.dartinnovations.com");
webReq = (HttpWebRequest)WebRequest.Create(url);
try
{
resp = (HttpWebResponse)await webReq.GetResponseAsync();
// Debug.WriteLine(resp.StatusCode);
webReq.Abort();
webReq = null;
url = null;
resp = null;
return true;
}
catch
{
webReq.Abort();
webReq = null;
return false;
}
}
private async Task<bool> CheckForConnection()
{
bool isConnected = await IsConnectedToInternet();
Debug.WriteLine(isConnected);
ConnectionProfile internetConnectionProfile = NetworkInformation.GetInternetConnectionProfile();
if (isConnected)
{
if (internetConnectionProfile != null)//Gets metereing info, Connectionprofile gives false positives when used to check for internet connectivity
{
Debug.WriteLine("internet available");
GetMeteringInformation(internetConnCectionProfile);
}
else
{
connectionProfileInfo = "Roaming information not available";
roaming = false;
// Debug.WriteLine("no connections");
}
return true;
}
return false;
}
private async Task GetMeteringInformation(ConnectionProfile connectionProfile)
{
ConnectionCost connectionCost = connectionProfile.GetConnectionCost();
roaming = connectionCost.Roaming;
connectionProfileInfo = "Over Data Limit :" + connectionCost.OverDataLimit + " | Approaching Data Limit :" +
connectionCost.ApproachingDataLimit;
}

Accessing Google Docs with GData

Working Platform: ASP.NET 4.0 C# ( Framework Agnostic )
Google GData is my dependency
using Google.GData.Client;
using Google.GData.Extensions;
using Google.GData.Documents;
I have two pages Auth and List.
Auth redirects to Google Server like this
public ActionResult Auth()
{
var target = Request.Url.ToString().ToLowerInvariant().Replace("auth", "list");
var scope = "https://docs.google.com/feeds/";
bool secure = false, session = true;
var authSubUrl = AuthSubUtil.getRequestUrl(target, scope, secure, session);
return new RedirectResult(authSubUrl);
}
Now it reaches the List Page if Authentication is successful.
public ActionResult List()
{
if (Request.QueryString["token"] != null)
{
String singleUseToken = Request.QueryString["token"];
string consumerKey = "www.blahblah.net";
string consumerSecret = "my_key";
string sessionToken = AuthSubUtil.exchangeForSessionToken(singleUseToken, null).ToString();
var authFactory = new GOAuthRequestFactory("writely", "qwd-asd-01");
authFactory.Token = sessionToken;
authFactory.ConsumerKey = consumerKey;
authFactory.ConsumerSecret = consumerSecret;
//authFactory.TokenSecret = "";
try
{
var service = new DocumentsService(authFactory.ApplicationName) { RequestFactory = authFactory };
var query = new DocumentsListQuery();
query.Title = "project";
var feed = service.Query(query);
var result = feed.Entries.ToList().ConvertAll(a => a.Title.Text);
return View(result);
}
catch (GDataRequestException gdre)
{
throw;
}
}
}
This fails at the line var feed = service.Query(query); with the error
Execution of request failed: https://docs.google.com/feeds/default/private/full?title=project
The HttpStatusCode recieved on the catch block is HttpStatusCode.Unauthorized
What is wrong with this code? Do I need to get TokenSecret? If so how?
You need to request a token from Google and use it to intialize your DocumentsService instance.
Here's an example using Google's ContactsService. It should be the same for the DocumentsService.
Service service = new ContactsService("My Contacts Application");
service.setUserCredentials("your_email_address_here#gmail.com", "yourpassword");
var token = service.QueryClientLoginToken();
service.SetAuthenticationToken(token);
But as you mentioned, you are using AuthSub. I jumped the gun a bit too fast.
I see that you are requesting a session token. According to the documentation of the API you must use the session token to authenticate requests to the service by placing the token in the Authorization header. After you've set the session token, you can use the Google Data APIs client library.
Here's a complete example (by Google) on how to use AuthSub with the .NET client library:
http://code.google.com/intl/nl-NL/apis/gdata/articles/authsub_dotnet.html
Let me include a shortened example:
GAuthSubRequestFactory authFactory =
new GAuthSubRequestFactory("cl", "TesterApp");
authFactory.Token = (String) Session["token"];
CalendarService service = new CalendarService(authFactory.ApplicationName);
service.RequestFactory = authFactory;
EventQuery query = new EventQuery();
query.Uri = new Uri("http://www.google.com/calendar/feeds/default/private/full");
EventFeed calFeed = service.Query(query);
foreach (Google.GData.Calendar.EventEntry entry in calFeed.Entries)
{
//...
}
And if I see correctly your example code pretty follows the same steps, except that you set the ConsumerKey and ConsumerSecret for the AuthFactory which is not done in the example by Google.
Used the 3-legged OAuth in the Google Data Protocol Client Libraries
Sample Code
string CONSUMER_KEY = "www.bherila.net";
string CONSUMER_SECRET = "RpKF7ykWt8C6At74TR4_wyIb";
string APPLICATION_NAME = "bwh-wssearch-01";
string SCOPE = "https://docs.google.com/feeds/";
public ActionResult Auth()
{
string callbackURL = String.Format("{0}{1}", Request.Url.ToString(), "List");
OAuthParameters parameters = new OAuthParameters()
{
ConsumerKey = CONSUMER_KEY,
ConsumerSecret = CONSUMER_SECRET,
Scope = SCOPE,
Callback = callbackURL,
SignatureMethod = "HMAC-SHA1"
};
OAuthUtil.GetUnauthorizedRequestToken(parameters);
string authorizationUrl = OAuthUtil.CreateUserAuthorizationUrl(parameters);
Session["parameters"] = parameters;
ViewBag.AuthUrl = authorizationUrl;
return View();
}
public ActionResult List()
{
if (Session["parameters"] != null)
{
OAuthParameters parameters = Session["parameters"] as OAuthParameters;
OAuthUtil.UpdateOAuthParametersFromCallback(Request.Url.Query, parameters);
try
{
OAuthUtil.GetAccessToken(parameters);
GOAuthRequestFactory authFactory = new GOAuthRequestFactory("writely", APPLICATION_NAME, parameters);
var service = new DocumentsService(authFactory.ApplicationName);
service.RequestFactory = authFactory;
var query = new DocumentsListQuery();
//query.Title = "recipe";
var feed = service.Query(query);
var docs = new List<string>();
foreach (DocumentEntry entry in feed.Entries)
{
docs.Add(entry.Title.Text);
}
//var result = feed.Entries.ToList().ConvertAll(a => a.Title.Text);
return View(docs);
}
catch (GDataRequestException gdre)
{
HttpWebResponse response = (HttpWebResponse)gdre.Response;
//bad auth token, clear session and refresh the page
if (response.StatusCode == HttpStatusCode.Unauthorized)
{
Session.Clear();
Response.Write(gdre.Message);
}
else
{
Response.Write("Error processing request: " + gdre.ToString());
}
throw;
}
}
else
{
return RedirectToAction("Index");
}
}
This 2-legged sample never worked for me for google docs.

Categories

Resources