Await in Windows Phone 7? - c#

I am trying to go through the Windows Phone Live tutorial but I get stuck when trying to implement the code example as it seems to be missing information.
using System;
using System.Windows;
using System.Collections.Generic;
using Microsoft.Phone.Controls;
using Microsoft.Live;
using Microsoft.Live.Controls;
namespace WindowsPhoneCodeSample
{
public partial class MainPage : PhoneApplicationPage
{
private LiveConnectClient client;
public MainPage()
{
InitializeComponent();
}
private async void btnSignin_SessionChanged(object sender, LiveConnectSessionChangedEventArgs e)
{
if (e.Status == LiveConnectSessionStatus.Connected)
{
client = new LiveConnectClient(e.Session);
LiveOperationResult operationResult = await client.GetAsync("me");
try
{
dynamic meResult = operationResult.Result;
if (meResult.first_name != null &&
meResult.last_name != null)
{
infoTextBlock.Text = "Hello " +
meResult.first_name + " " +
meResult.last_name + "!";
}
else
{
infoTextBlock.Text = "Hello, signed-in user!";
}
}
catch (LiveConnectException exception)
{
this.infoTextBlock.Text = "Error calling API: " +
exception.Message;
}
}
else
{
infoTextBlock.Text = "Not signed in.";
}
}
}
}
I get
Error 2 The name 'await' does not exist in the current context
Error 3 One or more types required to compile a dynamic expression cannot be found. Are you missing references to Microsoft.CSharp.dll and System.Core.dll?
Am I missing some reference or something?
Edit
the tutorial seems to be poorly done or very out of date. I made a windows phone 8 application and it still does not build because of the "awai"t keyword.
The 'await' operator can only be used within an async method. Consider marking this method with the 'async' modifier and changing its return type to 'Task'.
client.GetAsync is also a void method. So not sure how it returns something as well.

await works only with awaitables - see ยง7.7.7.1 on the C# Language Specification.
Since client.GetAsync is a void returning method, it can never be an awaitable.

You need to install NuGet Package Microsoft.Bcl.Async (you can find it in NuGet Manager) so compiler recognize words await and async.
more info http://www.nuget.org/packages/Microsoft.Bcl.Async/

Related

The name 'DisplayPromptAsync' does not exist in the current context - Xamarin

I'm trying to implement a simple Dialog with a text input in Android Xamarin, using a DisplayPromptAsync:
private async void ShowDialogAsync() {
string result = await DisplayPromptAsync("Question 1", "What's your name?");
}
Source: https://learn.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/pop-ups
But I'm getting the next error:
CS0103 The name 'DisplayPromptAsync' does not exist in the current context
And it doesn't give me the option to import any library. My version of Xamarin Forms is 4.6.0.726
It's something I'm missing...?
Thanks in advance...
In the ViewModel, just add the App.Current.MainPage before the call of DisplayPromptAsync:
private async void ShowDialogAsync() {
string result = await App.Current.MainPage.DisplayPromptAsync("Question 1", "What's your name?");
// OK
if (result != null)
{
// do something here
} else {
// do something else here
}
}
Thanks to Jason for his reply...
Update NuGet for Xamarin.Forms
I have updated NuGet for Xamarin.Forms from 4.2.X to 4.3.X in all projects and now it works. Apparently in 4.2.X the method "appears" available with intellisense, but at runtime it fails with the mentioned error. Updating all NuGet packages seemed to solve the problem.

How do I await a Windows.Web.Http.HttpClient.GetAsync()? Getting Intellisense error

Edit: I am already using the Microsoft.Bcl.Async nuget package in my project, but the error persists.
I am writing an asnyc "make sure the URL is accessible" method using the following code:
public async Task<ConnectivityMonitorResult> TestModeUrlCheck(string url)
{
try
{
var filter = new HttpBaseProtocolFilter();
filter.IgnorableServerCertificateErrors.Add(Windows.Security.Cryptography.Certificates.ChainValidationResult.Expired);
filter.IgnorableServerCertificateErrors.Add(Windows.Security.Cryptography.Certificates.ChainValidationResult.Untrusted);
filter.IgnorableServerCertificateErrors.Add(Windows.Security.Cryptography.Certificates.ChainValidationResult.InvalidName);
using (var httpClient = new Windows.Web.Http.HttpClient(filter))
{
var resp = await httpClient.GetAsync(new Uri(url), Windows.Web.Http.HttpCompletionOption.ResponseHeadersRead);
if (resp.IsSuccessStatusCode)
return new ConnectivityMonitorResult(ConnectivityType.Connected);
else
return new ConnectivityMonitorResult(ConnectivityType.NotConnected);
}
}
catch(Exception ex)
{
return new ConnectivityMonitorResult(ConnectivityType.NotConnected, "Unhandled error: " + ex.Message);
}
}
This method will be for the "Test Mode" of my app. (The production Check method will fail with bad SSL certs). It will be hitting local dev servers with self-signed certs.
Problem is that this code won't build because of the following error on the var resp = await line:
'IAsyncOperationWithProgress' does
not contain a definition for 'GetAwaiter' and the best extension
method overload 'AwaitExtensions.GetAwaiter(Task)' requires a receiver
of type 'Task'
I have not been able to figure how to properly construct the GetAsync() call to get this to work.
Update
This is for a Windows 8 app using the portable class libraries. I am using await in other places in the project. And I have the Microsoft.Bcl and Microsoft.Bcl.Async Nuget packages already added to my project.
Update
I tried updating the code to this:
public async Task<ConnectivityMonitorResult> TestModeUrlCheck(string url)
{
try
{
var filter = new HttpBaseProtocolFilter();
filter.IgnorableServerCertificateErrors.Add(Windows.Security.Cryptography.Certificates.ChainValidationResult.Expired);
filter.IgnorableServerCertificateErrors.Add(Windows.Security.Cryptography.Certificates.ChainValidationResult.Untrusted);
filter.IgnorableServerCertificateErrors.Add(Windows.Security.Cryptography.Certificates.ChainValidationResult.InvalidName);
using (var httpClient = new Windows.Web.Http.HttpClient(filter))
{
var resp = await Test(httpClient, url);
if (resp.IsSuccessStatusCode)
return new ConnectivityMonitorResult(ConnectivityType.Connected);
else
return new ConnectivityMonitorResult(ConnectivityType.NotConnected);
}
}
catch(Exception ex)
{
return new ConnectivityMonitorResult(ConnectivityType.NotConnected, "Unhandled error: " + ex.Message);
}
}
private async Task<Windows.Web.Http.HttpResponseMessage> Test(Windows.Web.Http.HttpClient client, string apiUrl)
{
var asyncOp = client.GetAsync(new Uri(apiUrl), Windows.Web.Http.HttpCompletionOption.ResponseHeadersRead);
return await Task.Run(() => asyncOp.GetResults());
}
It compiled, but I got the runtime error:
WinRT information: A method was called at an unexpected time.
I solved this by updating the target of the project. The other projects in the solution were targeting Windows8.1, whereas this one was targeting Windows8. When I updated the target, the errors went away and the app built and ran.

Tring to get GitHub repo via Octokit

I'm building simple tool for downloading .lua files from online public GitHub repos via link given by user. I started learning async methods so I wanted to test myself.
It's a console application (for now). The ultimate goal is to get .lua files in a repo and ask the user which ones he wants downloaded, but I'll be happy if I connect to GH for now.
I'm using Octokit (https://github.com/octokit/octokit.net) GitHub API integration to .NET.
This is the reduced code; I removed some of unimportant stuff:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Octokit;
namespace GetThemLuas
{
class Program
{
static readonly GitHubClient Github = new GitHubClient(new ProductHeaderValue ("Testing123"), new Uri("https://www.github.com/"));
static void Main(string[] args)
{
Console.WriteLine("Welcome to GitHub repo downloader");
GetRepoTry4();
}
private static async void GetRepoTry4()
{
try
{
Console.WriteLine("Searching for data"); //returns here... code below is never ran
var searchResults = await Github.Search.SearchRepo(new SearchRepositoriesRequest("octokit"));
if (searchResults != null)
foreach (var result in searchResults.Items)
Console.WriteLine(result.FullName);
Console.WriteLine("Fetching data...."); //testing search
var myrepo = await Github.Repository.Get("Haacked", "octokit.net");
Console.WriteLine("Done! :)");
Console.WriteLine("Repo loaded successfully!");
Console.WriteLine("Repo owner: " + myrepo.Owner);
Console.WriteLine("Repo ID: " + myrepo.Id);
Console.WriteLine("Repo Date: " + myrepo.CreatedAt);
}
catch (Exception e)
{
Console.WriteLine("Ayyyy... troubles"); //never trigged
Console.WriteLine(e.Message);
}
}
}
}
The problem is the await` keyword as it terminates the method and returns.
I'm still learning async methods so it's possible I messed something up, but even my ReSharper says it fine.
I used var to replace task<T> stuff. It seams OK to me plus no warnings nor errors.
I fixed the await issue. Now when I finally connected to GH and tried to get the repo it threw an exeption at both calls to GH (tested with commenting first then second call). e.message was some huge stuff.
I logged it into a file and it looks like an HTML document. Here it is (http://pastebin.com/fxJD1dUb)
Change GetRepoTry4(); to Task.Run(async () => { await GetRepoTry4(); }).Wait(); and private static async void GetRepoTry4() to private static async Task GetRepoTry4().
This should get you at least wired up correctly enough to start debugging the real issue.
Generally speaking all async methods need to return a Task or Task<T> and all methods that return a Task or Task<T> should be async. Additionally, you should get your code into the dispatcher as quickly as possible and start using await.
The constructor with the Uri overload is intended for use with GitHub Enterprise installations, e.g:
static readonly GitHubClient Github = new GitHubClient(new ProductHeaderValue ("Testing123"), new Uri("https://github.enterprise.com/"));
If you're just using it to connect to GitHub, you don't need to specify this:
static readonly GitHubClient Github = new GitHubClient(new ProductHeaderValue ("Testing123"));
You're seeing a HTML page because the base address is incorrect - all of the API-related operations use api.github.com, which is the default.
Install Octokit Nuget Package for Github.Then add below function
public JsonResult GetRepositoryDeatil(long id)
{
var client = new GitHubClient(new ProductHeaderValue("demo"));
var tokenAuth = new Credentials("xxxxxxx"); // NOTE: not real token
client.Credentials = tokenAuth;
var content = client.Repository.Content.GetAllContents(id).Result;
List<RepositoryContent> objRepositoryContentList = content.ToList();
return Json(objRepositoryContentList, JsonRequestBehavior.AllowGet);
}
Due to the use of the async/await you should change the definition of the method GetRepoTry4 to the following:
private static async Task GetRepoTry4()
EDIT:
Then in the Main method call it like so GetRepoTry4().Wait();. This will enable the method GetRepoTry4() to be awaited.

Portable Class Library HttpClient

For one of my projects I want to develop a library that can be used in different platforms (Desktop, Mobile, Surface, etc). Hence have opted Porable Class Library.
I am developing a class for calling different API calls' using HttpClient. I am stuck with how to call the method, response and work around. This is my code :-
public static async Task<JObject> ExecuteGet(string uri)
{
using (HttpClient client = new HttpClient())
{
// TODO - Send HTTP requests
HttpRequestMessage reqMsg = new HttpRequestMessage(HttpMethod.Get, uri);
reqMsg.Headers.Add(apiIdTag, apiIdKey);
reqMsg.Headers.Add(apiSecretTag, ApiSecret);
reqMsg.Headers.Add("Content-Type", "text/json");
reqMsg.Headers.Add("Accept", "application/json");
//response = await client.SendAsync(reqMsg);
//return response;
//if (response.IsSuccessStatusCode)
//{
string content = await response.Content.ReadAsStringAsync();
return (JObject.Parse(content));
//}
}
}
// Perform AGENT LOGIN Process
public static bool agentStatus() {
bool loginSuccess = false;
try
{
API_Utility.ExecuteGet("http://api.mintchat.com/agent/autoonline").Wait();
// ACCESS Response, JObject ???
}
catch
{
}
finally
{
}
Like ExecuteGet, I will also create for ExecutePost. My query is from ExecuteGet, if (1) I pass JObject on parsing when IsSuccessStatusCode only, then how can I know about any other errors or messages to inform the user. (2) If I pass response, then how do I assign it here
response = API_Utility.ExecuteGet("http://api.mintchat.com/agent/autoonline").Wait();
that is giving error.
What would be the best approach to handle this situation ? And I got to call multiple API's, so different API will have different result sets.
Also, can you confirm that designing this way and adding PCL reference I will be able to access in multiple projects.
UPDATE :-
As mentioned in below 2 answers I have updated my code. As mentioned in the provided link I am calling the from the other project. This is my code :-
Portable Class Library :-
private static HttpRequestMessage getGetRequest(string url)
{
HttpRequestMessage reqMsg = new HttpRequestMessage(HttpMethod.Get, url);
reqMsg.Headers.Add(apiIdTag, apiIdKey);
reqMsg.Headers.Add(apiSecretTag, ApiSecret);
reqMsg.Headers.Add("Content-Type", "text/json");
reqMsg.Headers.Add("Accept", "application/json");
return reqMsg;
}
// Perform AGENT LOGIN Process
public static async Task<bool> agentStatus() {
bool loginSuccess = false;
HttpClient client = null;
HttpRequestMessage request = null;
try
{
client = new HttpClient();
request = getGetRequest("http://api.mintchat.com/agent/autoonline");
response = await client.SendAsync(request).ConfigureAwait(false);
if (response.IsSuccessStatusCode)
{
string content = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
JObject o = JObject.Parse(content);
bool stat = bool.Parse(o["status"].ToString());
///[MainAppDataObject sharedAppDataObject].authLogin.chatStatus = str;
o = null;
}
loginSuccess = true;
}
catch
{
}
finally
{
request = null;
client = null;
response = null;
}
return loginSuccess;
}
From the other WPF project, in a btn click event I am calling this as follows :-
private async void btnSignin_Click(object sender, RoutedEventArgs e)
{
/// Other code goes here
// ..........
agent = doLogin(emailid, encPswd);
if (agent != null)
{
//agent.OnlineStatus = getAgentStatus();
// Compile Error at this line
bool stat = await MintWinLib.Helpers.API_Utility.agentStatus();
...
I get these 4 errors :-
Error 1 Predefined type 'System.Runtime.CompilerServices.IAsyncStateMachine' is not defined or imported D:\...\MiveChat\CSC
Error 2 The type 'System.Threading.Tasks.Task`1<T0>' is defined in an assembly that is not referenced. You must add a reference to assembly 'System.Threading.Tasks, Version=1.5.11.0, Culture=neutral, PublicKeyToken=b03f5f7f89d50a3a'. D:\...\Login Form.xaml.cs 97 21
Error 3 Cannot find all types required by the 'async' modifier. Are you targeting the wrong framework version, or missing a reference to an assembly? D:\...\Login Form.xaml.cs 97 33
Error 4 Cannot find all types required by the 'async' modifier. Are you targeting the wrong framework version, or missing a reference to an assembly? D:\...\Login Form.xaml.cs 47 28
I tried adding System.Threading.Tasks from the PCL library only, that gave 7 different errors. Where am I going wrong ? What to do to make this working ?
Please guide me on this. Have spend lots of hours figuring the best to develop a library accessible to desktop app & Win Phone app.
Any help is highly appreciative. Thanks.
If you call an async api when making the http calls, you should also expose that async endpoint to the user, and not block the request using Task.Wait.
Also, when creating a third party library, it is recommanded to use ConfigureAwait(false) to avoid deadlocks when the calling code tries to access the Result property or the Wait method. You should also follow guidelines and mark any async method with Async, so the method should be called ExecuteStatusAsync
public static Task<bool> AgentStatusAsync()
{
bool loginSuccess = false;
try
{
// awaiting the task will unwrap it and return the JObject
var jObject = await API_Utility.ExecuteGet("http://api.mintchat.com/agent/autoonline").ConfigureAwait(false);
}
catch
{
}
}
And inside ExecuteGet:
response = await client.SendAsync(reqMsg).ConfigureAwait(false);
string content = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
In case IsSuccessStatusCode is false, you may throw an exception to the calling code to show something went wrong. To do that, you can use the HttpResponseMessage.EnsureSuccessStatusCode which throws an exception if the status code != 200 OK.
Personally, if ExecuteGet is a public API method i would definitely not expose it as a JObject but a strongly typed type.
If you want the result of the task, you need to use the Result property:
var obj = API_Utility.ExecuteGet("http://api.mintchat.com/agent/autoonline").Result;
However, it's usually not a good idea to wait synchronously for an async method to complete, because it can cause deadlocks. The better approach is to await the method:
var obj = await API_Utility.ExecuteGet("http://api.mintchat.com/agent/autoonline");
Note that you need to make the calling method async as well:
public static async Task<bool> agentStatus()
Sync and async code don't play together very well, so async tends to propagate across the whole code base.

Cannot await 'void' error in windows phone

I am stuck in this problem. I am creating a Windows Phone application. Here is the code.
private async void btn_signup_Click(object sender, RoutedEventArgs e)
{
obj = new ServiceReference2.Service1Client();
if (!txt_id.Text.Equals("") && !txt_name.Text.Equals("") && !txt_password.Equals(""))
{
user r = new user();
r.ID = txt_id.Text;
r.FULLNAME = txt_name.Text;
r.PASSWORD = txt_password.Text;
var g = await obj.GetDataAsync(r);
string message = g;
if (message.Equals("done"))
{
lbl_show.Text = "you have signed up !! Hurrah";
NavigationService.Navigate(new Uri("/mainmenu.xaml", UriKind.Relative));
}
else
{
lbl_show.Text = " Please fill all the field.Enter again";
}
}
}
I am getting this error "cannot await void". I am using WCF service to access the db.
Please guide me with the appropriate solution.
GetDataAsync is not a TAP method; it is an EAP method.
Try to re-create the WCF proxy and tell it to create TAP asynchronous methods. If Visual Studio doesn't give you that option, then see if the proxy has Begin*/End* methods that you can wrap into a TAP method.
If nothing else, you can wrap the EAP method/event into a TAP method.

Categories