windows phone page initialization using async method error - c#

I have Windows phone page that fetch data from the web url using async. In my page class consructor I cannot call a async method. How do I initialize properties from the web url repsonse in the constructor.
public MyProfile()
{
InitializeComponent();
_populateFields();
}
private async void _populateFields()
{
try
{
var taskObj = await UserProfile.getUserProfile().getUserProfileFromServer();
//PoolCircle.UserProfile.ProfileResponseJson userObj = taskObj;
setDataContext(taskObj);
}
catch (Exception ex) { Debug.WriteLine(ex.Message); }
}
How do I fix this dependency? I am not sure how a factory method fix it. I am not creating object for the page class..

Try it from the OnNavigatedTo method. Overriding it. Its a method who you can put all your logic before the page appears
protected async override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
base.OnNavigatedTo(e);
_populateFields();
}
Documentation
hope helps! Greetings!

Make a method like PostData(); and call this after InitializeComponent();
private async void PostData()
{
try
{
var taskObj = await UserProfile.getUserProfile().getUserProfileFromServer();
//PoolCircle.UserProfile.ProfileResponseJson userObj = taskObj;
setDataContext(taskObj);
}
catch (Exception ex) { Debug.WriteLine(ex.Message); }
}

Related

Cannot throw an exception in catch block

I Have a class, that should not show any dialogs to final user. In case, that user passed wrong filepath, i tried to throw and exception and handle it in proper class.
However, despite 'throw' instruction, Visual Studio shows Exception Dialog and breaks application after it occurs (Debuging mode). In Release mode application just crashes after giving wrong filepath. What am i doing wrong?
GuyManager.cs:
private IStorageFile latestGuyFile;
public IStorageFile LatestGuyFile { get { return latestGuyFile; } }
public string Path { get; set; }
public async void ReadGuyAsync()
{
if (String.IsNullOrWhiteSpace(Path))
return;
try
{
latestGuyFile = await StorageFile.GetFileFromPathAsync(Path);
}
catch (Exception ex)
{
Debug.WriteLine("Error occured: " +ex.Message);
Debug.WriteLine(ex.StackTrace);
throw;
}
MainPage.xml.cs:
private async void loadGuy_Click(object sender, RoutedEventArgs e)
{
try
{
guyManager.ReadGuyAsync();
}
catch (Exception ex)
{
MessageDialog dialog = new MessageDialog("Error" + ex.Message);
await dialog.ShowAsync();
}
}
I see a problem in your Click event handler.
You define it as async, but you are not awaiting anything.
You should change the ReadGuyAsync method to return a Task instead of void, like this:
public async Task ReadGuyAsync()
and in the loadGuy_Click method, you should await it:
await guyManager.ReadGuyAync();

How to solve this deadlock?

I have an UWP application in which I am trying to store and retrieve some data from a local text file but no matter how I try to do it the application gets deadlocked. Due to synchronous stuff that needs to happen, I try to use a task and wait for its completion but nevertheless, the application locks.
I have a page in my UWP application called "MainPage" and in it's constructor I have the following code:
var listenkeyViewModel = new ListenkeyViewModel();
listenkeyViewModel.GetKey();
listenkey = listenkeyViewModel.Listenkey;
The get key is the issue here because it calls a method on the ViewModel (which I created to be synchronous because I thought making the call synchronous asap would be preferable.
public void GetKey()
{
try
{
var listenKeyTask = RetrieveListenKey();
_listenkey = listenKeyTask.Result;
}
catch (Exception e)
{
}
}
public static async Task<string> RetrieveListenKey()
{
try
{
var storageFolder = Windows.Storage.ApplicationData.Current.LocalFolder;
var listenkeyFile = await storageFolder.GetFileAsync("listenkey.txt");
return await Windows.Storage.FileIO.ReadTextAsync(listenkeyFile);
}
catch (Exception e)
{
throw new Exception("Could not load file");
}
}
I know the thing is "async all the way down" but this is not possible here. I cannot make the constructor where the original code lies asynchronous. How are you supposed to not get deadlocked? I do not understand.
Convert GetKey to async/await
public async Task GetKey() {
try {
var listenKeyTask = RetrieveListenKey();
_listenkey = await listenKeyTask;
} catch (Exception e) {
//...should handle/log error
}
}
Move the calling of this out of the constructor and into an event handler. like page load or some other event called early in the lifecycle of the page.
partial class MainPage : Page {
ListenkeyViewModel listenkeyViewModel;
string listenkey;
public MainPage() {
InitializeComponent();
listenkeyViewModel = new ListenkeyViewModel();
// add a handler to be called when the page has been loaded
this.Loaded += OnPageLoaded;
}
async void OnPageLoaded(object sender, RoutedEventArgs e) {
await listenkeyViewModel.GetKey();
listenkey = listenkeyViewModel.Listenkey;
}
// Shown for demonstration purposes only.
// This is typically autogenerated by Visual Studio.
private void InitializeComponent() {
}
}
async void is allowed on event handlers so this should allow the process to flow without deadlock.

How to store authenticated state through Office365 API in Xamarin.forms

I'm new to Xamarin and using the Office365 API. I'm attempting to learn through creating a Xamarin.Forms application that reads data from the Office365 server once the user is authenticated.
I've been following a tutorial and ended up with the following login page
namespace CMLender.Pages
{
public partial class Login
{
public IPlatformParameters PlatformParameters { get; set; }
public Login()
{
InitializeComponent();
LoginButton.Clicked += LoginButton_Clicked;
}
protected override void OnAppearing()
{
App.ClientApplication.PlatformParameters = PlatformParameters;
base.OnAppearing();
}
private async void LoginButton_Clicked(object sender, EventArgs e)
{
try
{
AuthenticationResult ar = await App.ClientApplication.AcquireTokenAsync(App.Scopes);
}
catch (MsalException ex)
{
WelcomeText.Text = ex.Message;
}
finally
{
await Navigation.PushAsync(new MainTab());
}
}
}
}
Once a user clicks on the login button they are taken through to the Office365 user authentication page. Once they have logged in with a valid username and password, the application then loads the MainTab XAML page.
Now this is where my problem starts. My MainTab page looks like this:
namespace CMLender.Pages
{
public partial class MainTab : ContentPage
{
public MainTab()
{
InitializeComponent();
DisplayMessage();
}
private async void DisplayMessage()
{
try
{
AuthenticationResult ar = await App.ClientApplication.AcquireTokenAsync(App.Scopes);
WelcomeText.Text = $"Welcome {ar.User.Name}";
}
catch (MsalException ex)
{
WelcomeText.Text = ex.Message;
}
finally
{
WelcomeTextTwo.Text = "BlaBlaBlab";
}
}
}
}
I wanted this page to write the logged in users name to a label (which it does) but first the user has to re-authenticate.
I'm pretty sure it's down to the AcquireTokenAsync task but it's the only way I can get it to work. How can I store the information that the user is already authenticated and access their user name?
I've done all the reading I can but the information just seems so far and wide on the subject.
For the most simplistic impllementation you can create a public static property in you App.cs or App.xaml.cs like :
public static AuthenticationResult LoggedInUser { get; set; }
In your login page add this to your login button click event :
private async void LoginButton_Clicked(object sender, EventArgs e)
{
try
{
AuthenticationResult ar = await App.ClientApplication.AcquireTokenAsync(App.Scopes);
App.LoggedInUser = ar;
}
catch (MsalException ex)
{
WelcomeText.Text = ex.Message;
}
finally
{
await Navigation.PushAsync(new MainTab());
}
}
And in you main page, get the data from the static property instead of calling the API again :
private async void DisplayMessage()
{
try
{
WelcomeText.Text = $"Welcome {App.LoggedInUser.User.Name}";
}
catch (MsalException ex)
{
WelcomeText.Text = ex.Message;
}
finally
{
WelcomeTextTwo.Text = "BlaBlaBlab";
}
}
Also, in your login method, It does not seem right to show the main page in finally because even if an exception occurs finally would get executed. I suggest you to move await Navigation.PushAsync(new MainTab()); to try and show exception to user in catch.

Windows Phone, Web Services and Catching Exceptions

I have the following code in Windows Phone:
public partial class MainPage : PhoneApplicationPage
{
public MainPage()
{
InitializeComponent();
}
private void Button_LogIn_Click(object sender, RoutedEventArgs e)
{
Service1SoapClient web_service = new Service1SoapClient();
web_service.LogInAsync(TextBox_Username.Text, TextBox_Password.Password);
web_service.LogInCompleted += new EventHandler<LogInCompletedEventArgs>(login_complete);
}
private void login_complete(object obj, ClientWebService.LogInCompletedEventArgs e)
{
string answer = e.Result.ToString();
if (answer.Equals("Success") || answer.Equals("success"))
{
NavigationService.Navigate(new Uri("/Authenticated.xaml", UriKind.Relative));
}
else
{
MessageBox.Show("The log-in details are invalid!");
}
}
}
The code makes use of a web service in order to log-in the user into the system. The log-in system works as it should.
My question is, where should I insert the try catch statement in order to catch exception when the web service is NOT running? I tried in the button_click event handler to no avail and even in the line when I am getting the result.
It's not clear what type your Service1SoapClient is based upon so the statements below may not be accurate. It doesn't appear that you're using the Mobile Services Client since you're passing in a username and password and returning some other state.
However, the ...Async suffix on the LoginAsync method name indicates that this API returns a Task<T> which means that this API is built to be used by the new async and await keywords of C# 5.
Therefore, I recommend altering your code to read as follows:
```
public partial class MainPage : PhoneApplicationPage
{
public MainPage()
{
InitializeComponent();
}
private async void Button_LogIn_Click(object sender, RoutedEventArgs e)
{
try
{
Service1SoapClient web_service = new Service1SoapClient();
string answer = await web_service.LogInAsync(TextBox_Username.Text, TextBox_Password.Password);
if (answer.ToLower().Equals("success"))
{
NavigationService.Navigate(new Uri("/Authenticated.xaml", UriKind.Relative));
}
else
{
MessageBox.Show("The log-in details are invalid!");
}
catch (<ExceptionType> e)
{
// ... handle exception here
}
}
}
```
Note that one of the side-benefits of async and await is that they allow you to write your code logically, including your exception handling code which, prior to async and await was hard to get right!

Multiple asynchronous calls on webservice method in application fails with exception

i'm trying to create an application which connects to internet and consume web services for every of it's operation.As far as i'm concerned i'll like to useasync method which i'm using already to get a collection of Contacts.I've realized that when i'm doing the same for groups (meaning getting groups async) i'm having errors in the calls , but when using normal call there ins't.So i did some research online and find that a lot of people has the same problem.
Some of them are asked to use WCF (for which i don't know jack).I'll like to know if there is another way to overcome this. if not can somebody point me to reliable resource online and help me get through it? thanks for reading and helping
here is my code:
public partial class main : Window
{
//...
private static vmcSession session;
private MyService service = new MyService();
private contactInfo[] loadedcontact;
//....
public main()
{
InitializeComponent();
//service.addContactCompleted +=new addContactCompletedEventHandler(addContactCompleted);
service.getContactsCompleted += new getContactsCompletedEventHandler(getContactsCompleted);
service.getGroupsCompleted += new getGroupsCompletedEventHandler(getGroupsCompleted);
fillContents();
}
private void getGroupsCompleted(object sender, getGroupsCompletedEventArgs e)
{
try
{
groupListBox.ItemsSource = e.Result;
}
catch (Exception ex)
{
MessageBox.Show(ex.InnerException.Message);
}
}
private void getContactsCompleted(object sender, getContactsCompletedEventArgs e)
{
try
{
loadedcontact = e.Result;
contactListBox.ItemsSource = loadedcontact;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private void addContactCompleted(object sender, addContactCompletedEventArgs e)
{
throw new NotImplementedException();
}
public void fillContents()
{
displayUserInformation();
loadContacts();
service.getGroupsAsync(session.key, null);
//groupListBox.ItemsSource = service.getGroups(session.key, null);
cmbSenderIds.ItemsSource = service.getSenderIds(session.key, null);
if (cmbSenderIds.Items.Count > 0)
{
cmbSenderIds.SelectedIndex = 0;
}
loadGrid();
}
public void loadContacts()
{
service.getContactsAsync(session.key, null);
}
public void displayUserInformation()
{
lblName.Content = session.user.firstName;
lblEmail.Content = session.user.email;
lblCreditValue.Content = Decimal.Ceiling(session.user.balance).ToString();
}
public void loadGrid()
{
try
{
hitoryGrid.ItemsSource = service.viewMessages(session.key, null).ToList();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}
solve it.there are 2 methods with async calls, one with additional parameter Unique ID.each of the call needed ID, so i pass new GUID to it and that's it.thanks for trying helping me

Categories

Resources