I have the following method in Xamarin that makes an API call that returns a list of Items. When I start Visual Studio and run it returns a string of JSON with the information I expect it to. However when I run it several times and more often than not it hits the string returnedJson = await client.GetStringAsync line then just breaks out of the method, returning nothing.
I dont think its related to restarting Visual Studio, because sometimes after it not working several times it will work once again then stop again.
public async Task<IEnumerable<ItemModel>> GetItemsAsync(bool forceRefresh = false)
{
var baseAddr = new Uri("https://www.domain.co.uk");
var client = new HttpClient
{
BaseAddress = baseAddr
};
client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", Settings.ApiToken);
// NOW PROTECTED
try
{
string returnedJson = await client.GetStringAsync("/api/Items/Index");
var convert = JsonConvert.DeserializeObject<List<ItemModel>>(returnedJson);
return convert;
}
catch (Exception ex)
{
return null;
}
return null;
}
The WebAPI method -
[Authorize]
[HttpGet("[action]")]
public async Task<List<ItemModel>> Index()
{
return await itemService.Get();
}
Related
I am using the Microsoft Cognitive Face API for implementing the Face Detection to Authenticate the person and login to the application.
For that, I am creating a PersonGroup and add the Person and then Face of Person. Train Person group and so on.
I want to implement it in the MVC Web Application. I have written the same code in MVC Web Application. But the API is not returning anything and just hanged at the Http request call.
So Do we need to get some different API Key for a Web application or Do we need to make any changes in Web.Config file to make a successful call?
I have tried the same code in the Console Application and WPF Application. There everything works perfectly fine.
public class HttpClientHelper
{
HttpClient httpClient = new HttpClient();
private const string subscriptionKey = "XXXXXXXXXXXXXXXXXXXXXXXXXX";
private const string faceEndpoint = "https://southeastasia.api.cognitive.microsoft.com/face/v1.0/";
public HttpClientHelper()
{
httpClient.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", subscriptionKey);
httpClient.BaseAddress = new Uri(faceEndpoint);
}
public async Task<T> GetAsync<T>(string url)
{
var response = await httpClient.GetAsync(url);
string contentString = await response.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject<T>(contentString);
}
}
public static async Task CreatePersonGroup(UserGroup userGroup)
{
bool isGroupExists = false;
PersonGroup personGroup;
try
{
HttpClientHelper httpClientHelper = new HttpClientHelper();
var response = httpClientHelper.GetAsync<PersonGroup>(string.Format("persongroups/{0}", userGroup.UserGroupId)).Result;
isGroupExists = true;
}
catch (APIErrorException ex)
{
if (ex.Body.Error.Code == "PersonGroupNotFound")
isGroupExists = false;
}
if (isGroupExists == false)
{
await faceClient.PersonGroup.CreateAsync(userGroup.UserGroupId, userGroup.Name);
}
}
I expect the same code must be working fine in Web Application also. As there is not a big logic in it. Just a simple API call.
private const string faceEndpoint =
"https://southeastasia.api.cognitive.microsoft.com/";
hopefully, it should work
I know this should be simple, so I am obviously missing something.
I am writing a very simple Xamarin.Forms application with this as the MainPage.xaml.cs of the Shared project.
public partial class MainPage : ContentPage
{
public MyClass myClassInstance { get; set; }
public MainPage()
{
InitializeComponent();
DownloadDataAsync();
}
private async void DownloadDataAsync()
{
string page = #"http://www.blaw.com:80/foo/bar";
try
{
HttpClient client = new HttpClient();
var uri = new Uri(string.Format(page, string.Empty));
var response = await client.GetAsync(uri); <--- BONK!
if (response.IsSuccessStatusCode)
{
var responseString = await response.Content.ReadAsStringAsync();
XmlSerializer ser = new XmlSerializer(typeof(MyClass));
using (TextReader tr = new StringReader(responseString))
{
myClassInstance = (MyClass)ser.Deserialize(tr);
}
}
else
System.Diagnostics.Debug.WriteLine(response.StatusCode.ToString());
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.Message);
}
}
}
When I run this on my Android device, it never gets past the GetAsync line (marked with <-- BONK!). It doesn't throw an exception, and in never makes it to the if statement, it just returns from the method without doing anything at all.
I have enabled the ACCESS_NETWORK_STATE and INTERNET permissions in the Android Manifest.
What am I missing?
Calling asynchronous method from constructor is not a good idea. This will work in console applications but not on UI applications. Because this will block the UI thread, and control never returns to the code due to deadlock.
If you can call your async method in OnAppearing, it should work fine.
I have created a web API in AWS that I am trying to get some JSON back from using a web page built in ASP.NET Webforms (most up-to-date version). I can't get the asynchronous part to work. Either the GET method hangs seemingly forever, or - following the best practice approach from the Microsoft documentation - I get this error after a little while:
[TimeoutException: An asynchronous operation exceeded the page
timeout.] System.Web.UI.d__554.MoveNext() +984
I know this is something to do with the wait/async portion of the code and being in ASP.NET because of the following.
If I use very similar code in a console application it works fine.
If i call the web API using POSTMAN it works fine.
I have made async = true in the page directive. Here is my page load
protected void Page_Load(object sender, EventArgs e)
{
try
{
RegisterAsyncTask(new PageAsyncTask(GetStuffAsync));
}
catch (Exception ex)
{
renderStoreCards.Text = ex.Message;
}
}
Here is my method
private async Task GetStuffAsync()
{
string testHtml = string.Empty;
try
{
var signer = new AWS4RequestSigner("AccessKey", "SecretKey");
var request = new HttpRequestMessage
{
Method = HttpMethod.Get,
RequestUri = new Uri("https://some-aws-address-changed-for-stack-overflow.execute-api.ap-southeast-2.amazonaws.com/Prod/tables/InSiteStoreInformation/ServerName")
};
request = await signer.Sign(request, "execute-api", "ap-southeast-2");
var client = new HttpClient();
var response = await client.SendAsync(request).ConfigureAwait(false);
string responseString = await response.Content.ReadAsStringAsync();
}
catch (Exception ex)
{
renderStoreCards.Text = ex.Message;
}
}
The above example produces a TimeoutException. Previous to the above, I was trying the following code. This works fine in a console app, but not in the ASP.NET page.
class Program
{
static void Main(string[] args)
{
try
{
MainAsync().Wait();
}
catch (Exception ex)
{
Console.WriteLine($"Exception occured {ex.Message}");
Console.ReadKey();
}
}
static async Task MainAsync()
{
try
{
var signer = new AWS4RequestSigner("AccessKey", "SecretKey");
var request = new HttpRequestMessage
{
Method = HttpMethod.Get,
RequestUri = new Uri("https://<Hiddenforstackoverflowpost>.execute-api.ap-southeast-2.amazonaws.com/Prod/tables/InSiteStoreInformation/ServerName")
};
request = await signer.Sign(request, "execute-api", "ap-southeast-2");
var client = new HttpClient();
var response = await client.SendAsync(request);
var responseStr = await response.Content.ReadAsStringAsync();
dynamic sales = Newtonsoft.Json.JsonConvert.DeserializeObject(responseStr);
Console.WriteLine($"Server = {sales[0].ServerName}");
Console.ReadKey();
Console.Write(responseStr);
Console.ReadKey();
}
catch (Exception ex)
{
throw (ex);
}
}
}
I am by no means an expert in async/wait combinations, but it appears that the HttpClient I'm using has no synchronous alternative, so I have to figure this out.
I know this is an old question, but I just came across.
The timeouts are most likely caused by ReadAsStringAsync as you neglected to use '.ConfigureAwait(false)' on it. Running async tasks inside ASP.net can be very finicky especially around execution contexts. It most likely is some kind of dead-lock on the async method when it tries to restore the execution context on its return. This usually fails due to the nature of IIS hosting. I am not sure if it actually is a dead-lock or some other issue under the hood. Just make sure to always use .ConfigureAwait(false).
I know this is old, but maybe it helps someone else coming across this issue.
Can any one tell me how to retrive data from OData service using Simple.Odata.Client with in xamarin forms ?
I try by following way :
In Portable Project
public App()
{
GetDocument();
}
public async void GetDocument()
{
String result = await ODataServiceAgent.GetDocuments(skipCount);
}
In OData Service Calls
public static async Task<string> GetDocuments(int skipCount)
{
string json = string.Empty;
try
{
var client1 = new ODataClient(new ODataClientSettings(ServiceConstant.sURL_Base, new System.Net.NetworkCredential(ServiceConstant.NCUserName, ServiceConstant.NCPassword))
{
IgnoreResourceNotFoundException = true,
//OnTrace = (x, y) => Console.WriteLine(string.Format(x, y)),
});
string commands = string.Format(ServiceConstant.sURL_WholeDataByPagging, ServiceConstant.servicePaggingTopCount, skipCount);
IEnumerable<IDictionary<string, object>> configs = client1.FindEntriesAsync(commands).Result;
List<IDictionary<string, object>> configList = ((List<IDictionary<string, object>>)configs.ToList());
json = JsonConvert.SerializeObject(configList);
}
catch (Exception ex)
{
string excepstionMessage = ex.Message;
}
return json;
}
while actual call is happen using "FindEntriesAsync" line its not responding
It in the call to Result. In general it's not a good idea to call Result or Wait on async methods: it may work in some environments (like desktop Windows) but it will deadlock in others, especially mobile ones. So just await it, don't do .Result or .Wait.
I have been experimenting with WP7 apps today and have hit a bit of a wall.
I like to have seperation between the UI and the main app code but Ive hit a wall.
I have succesfully implemented a webclient request and gotten a result, but because the call is async I dont know how to pass this backup to the UI level. I cannot seem to hack in a wait for response to complete or anything.
I must be doing something wrong.
(this is the xbox360Voice library that I have for download on my website: http://www.jamesstuddart.co.uk/Projects/ASP.Net/Xbox_Feeds/ which I am porting to WP7 as a test)
here is the backend code snippet:
internal const string BaseUrlFormat = "http://www.360voice.com/api/gamertag-profile.asp?tag={0}";
internal static string ResponseXml { get; set; }
internal static WebClient Client = new WebClient();
public static XboxGamer? GetGamer(string gamerTag)
{
var url = string.Format(BaseUrlFormat, gamerTag);
var response = GetResponse(url, null, null);
return SerializeResponse(response);
}
internal static XboxGamer? SerializeResponse(string response)
{
if (string.IsNullOrEmpty(response))
{
return null;
}
var tempGamer = new XboxGamer();
var gamer = (XboxGamer)SerializationMethods.Deserialize(tempGamer, response);
return gamer;
}
internal static string GetResponse(string url, string userName, string password)
{
if (!string.IsNullOrEmpty(userName) && !string.IsNullOrEmpty(password))
{
Client.Credentials = new NetworkCredential(userName, password);
}
try
{
Client.DownloadStringCompleted += ClientDownloadStringCompleted;
Client.DownloadStringAsync(new Uri(url));
return ResponseXml;
}
catch (Exception ex)
{
return null;
}
}
internal static void ClientDownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
if (e.Error == null)
{
ResponseXml = e.Result;
}
}
and this is the front end code:
public void GetGamerDetails()
{
var xboxManager = XboxFactory.GetXboxManager("DarkV1p3r");
var xboxGamer = xboxManager.GetGamer();
if (xboxGamer.HasValue)
{
var profile = xboxGamer.Value.Profile[0];
imgAvatar.Source = new BitmapImage(new Uri(profile.ProfilePictureMiniUrl));
txtUserName.Text = profile.GamerTag;
txtGamerScore.Text = int.Parse(profile.GamerScore).ToString("G 0,000");
txtZone.Text = profile.PlayerZone;
}
else
{
txtUserName.Text = "Failed to load data";
}
}
Now I understand I need to place something in ClientDownloadStringCompleted but I am unsure what.
The problem you have is that as soon as an asynchronous operation is introduced in to the code path the entire code path needs to become asynchronous.
Because GetResponse calls DownloadStringAsync it must become asynchronous, it can't return a string, it can only do that on a callback
Because GetGamer calls GetResponse which is now asynchronous it can't return a XboxGamer, it can only do that on a callback
Because GetGamerDetails calls GetGamer which is now asynchronous it can't continue with its code following the call, it can only do that after it has received a call back from GetGamer.
Because GetGamerDetails is now asynchronous anything call it must also acknowledge this behaviour.
.... this continues all the way up to the top of the chain where a user event will have occured.
Here is some air code that knocks some asynchronicity in to the code.
public static void GetGamer(string gamerTag, Action<XboxGamer?> completed)
{
var url = string.Format(BaseUrlFormat, gamerTag);
var response = GetResponse(url, null, null, (response) =>
{
completed(SerializeResponse(response));
});
}
internal static string GetResponse(string url, string userName, string password, Action<string> completed)
{
WebClient client = new WebClient();
if (!string.IsNullOrEmpty(userName) && !string.IsNullOrEmpty(password))
{
client.Credentials = new NetworkCredential(userName, password);
}
try
{
client.DownloadStringCompleted += (s, args) =>
{
// Messy error handling needed here, out of scope
completed(args.Result);
};
client.DownloadStringAsync(new Uri(url));
}
catch
{
completed(null);
}
}
public void GetGamerDetails()
{
var xboxManager = XboxFactory.GetXboxManager("DarkV1p3r");
xboxManager.GetGamer( (xboxGamer) =>
{
// Need to move to the main UI thread.
Dispatcher.BeginInvoke(new Action<XboxGamer?>(DisplayGamerDetails), xboxGamer);
});
}
void DisplayGamerDetails(XboxGamer? xboxGamer)
{
if (xboxGamer.HasValue)
{
var profile = xboxGamer.Value.Profile[0];
imgAvatar.Source = new BitmapImage(new Uri(profile.ProfilePictureMiniUrl));
txtUserName.Text = profile.GamerTag;
txtGamerScore.Text = int.Parse(profile.GamerScore).ToString("G 0,000");
txtZone.Text = profile.PlayerZone;
}
else
{
txtUserName.Text = "Failed to load data";
}
}
As you can see async programming can get realy messy.
You generally have 2 options. Either you expose your backend code as an async API as well, or you need to wait for the call to complete in GetResponse.
Doing it the async way would mean starting the process one place, then return, and have the UI update when data is available. This is generally the preferred way, since calling a blocking method on the UI thread will make your app seem unresponsive as long as the method is running.
I think the "Silverlight Way" would be to use databinding. Your XboxGamer object should implement the INotifyPropertyChanged interface. When you call GetGamer() it returns immediately with an "empty" XboxGamer object (maybe with GamerTag=="Loading..." or something). In your ClientDownloadStringCompleted handler you should deserialize the returned XML and then fire the INotifyPropertyChanged.PropertyChanged event.
If you look at the "Windows Phone Databound Application" project template in the SDK, the ItemViewModel class is implemented this way.
Here is how you can expose asynchronous features to any type on WP7.