Issue with httpclient.getstringasync - asynchronous

I want to develop a Dragon Timer Windows Store App for GuildWars 2.
Whatever, I save a timestamp in a sql database. To get this timestamp in the app, I made a php script that writes the content of the database to a page. Now I'm trying to receive that string via the HttpClient.GetStringAsync() Method. Here's the code snipped:
async Task<Dictionary<String, DateTime>> GetKillTimes()
{
Dictionary<String, DateTime> killTimes = new Dictionary<String,DateTime>();
HttpClient httpClient = new HttpClient();
Task<string> getStringTask = httpClient.GetStringAsync("http://www.wp10454523.server-he.de/truhentimer/getTimes.php");
String rawKillTimes = await getStringTask;
//Parse to Dictionary...
return killTimes;
}
I tried some different Methods I got from google (WebRequest ...), but every one got stuck at the Get-Part. Am I maybe misinterpreting the function? Shouldn't I get the content of the page, which is a simple String?

You have to use await keyword as web request & response in WinRT are asynchronous so you have to use await keyword. await before httpClient.GetStringAsync(...)
Task<string> getStringTask = await httpClient.GetStringAsync("http://www.wp10454523.server-he.de/truhentimer/getTimes.php");

Related

Interacting with browser in MAUI Blazor hybrid for the purpose of google autenthication

I am working on implementing a firebase authentication in a MAUI Blazor hybrid app.
Using the web api wrapped in the popular FirebaseAutenthication.net library.
What I need to do is open a browser window with google consent screen and capture the url it redirects to.
#inject NavigationManager navmanager;
var client = new FirebaseAuthClient(config);
var userCredential = await client.SignInWithRedirectAsync(FirebaseProviderType.Google, async uri =>
{
navmanager.NavigateTo(uri);
//return credential
});
This works fine but I am not sure how to interact with browser at all after it has been opened.
Any tips please?
Edit:
I think i'm going to try something with JS interop. There must be a way to capture redirect event.
var userCredential = await client.SignInWithRedirectAsync(FirebaseProviderType.Google, async uri =>
{
string credential = "";
async Task OpenWindow()
{
await JSRuntime.InvokeAsync<string>("authURI", uri);
}
await OpenWindow();
//wait for redirect
return credential;
});
function authURI(uri) {
var newWindow = window.open(uri);
console.log(newWindow);
So that doesnt work and prints null to console
WebAuthenticator is a good choice to get the access token from the webpage. The API consists mainly of a single method AuthenticateAsync which takes two parameters: The first uri should be used to start the web browser flow. For the second uri, which you expect the flow to ultimately call back to can be able to be handleed because you have registered the firebase.
Here is the sample:
var authResult = await WebAuthenticator.AuthenticateAsync(
new Uri("https:"),
new Uri("myapp://"));
var accessToken = authResult?.AccessToken;

Xamarin forms: Method is left after callunt await client.GetAsync

I am getting data from a server via Rest API. But Whenever i am waiting for the client response the Methos is left by the Debugger and the Program start loading the GUI even though at this point there is no Data to Display. Im already stuck for a couple of days on it. How can i make the Code to wait for the Response? Iam already using Await
My Method to get The Data: (Client Call in Line 8)
public async Task<ObservableCollection<Datensatz>> getDataFromAzure()
{
string URL = URLForContent;
_client = new HttpClient();
_client.DefaultRequestHeaders.Add("ApiKey", PW);
var result1 = await _client.GetAsync(URL, HttpCompletionOption.ResponseHeadersRead).ConfigureAwait(false);
if (result1.StatusCode == System.Net.HttpStatusCode.OK)
{
var result = await result1.Content.ReadAsStringAsync();
var ContentFromJson = JsonConvert.DeserializeObject<ObservableCollection<Datensatz>>(result);
string json = JsonConvert.SerializeObject(ContentFromJson, Formatting.Indented);
var filename = #"data.json";
var destinatioPath = Path.Combine(Android.App.Application.Context.GetExternalFilesDir(null).ToString(), filename);
File.WriteAllText(destinatioPath, json);
App.Database_Main.FillMainDBWithJsonEntrys();
return ContentFromJson;
}
return null;
}
You can use the Wait method of the Task. Such as
Task result = getDataFromAzure()
result.Wait();
You can also use the Thread.sleep(1000) to make the main thread sleep for a while. But this will reduce the function of the application because we don't know how long time the async method need and if the time if more than 5 seconds will cause the ANR.

When calling AcquireTokenByRefreshToken on the AuthenticationContext instance with Microsoft.IdentityModel.Clients.ActiveDirectory?

I am developing a multi-tenant application registered on my Azure AD that consumes Office 365 apis, Graph API etc.
I followed this Microsoft sample to build my work which uses ADAL .NET library and OpenIdConnect: Microsoft.IdentityModel.Clients.ActiveDirectory, Version=2.19.0.0
In ADAL.NET, we use an AuthenticationContext instance with a custom inherited class for the TokenCache (see code the sample code here).
For each request to the authorized resources, depending on the API, we invoke one of these methods (see code below) to get the auth_token that will be put in the request Bearer parameter. Is it the correct way to do it?
We never make use of the method AcquireTokenByRefreshTokenAsync, does it mean that our application never uses the refresh_token? Does it mean that our user will have to relog after one hour? Should we implement a kind of refreshing procedure with AcquireTokenByRefreshTokenAsync in the catch statement? Can it be made without prompting anything to the end-user?
REMARK: I posted a question regarding OpenIdConnect authentication ticket lifetime. To me these two questions are unrelated but they may be.
string signInUserId = ClaimsPrincipal.Current.FindFirst(ClaimTypes.NameIdentifier).Value;
string userObjectId = ClaimsPrincipal.Current.FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier").Value;
string tenantId = ClaimsPrincipal.Current.FindFirst("http://schemas.microsoft.com/identity/claims/tenantid").Value;
public async Task<string> AcquireOutlook365TokenAsync()
{
AuthenticationContext authContext = new AuthenticationContext(string.Format("{0}/{1}", SettingsHelper.AuthorizationUri, tenantId), new ADALTokenCache(signInUserId));
try
{
var result = await authContext.AcquireTokenSilentAsync(#"https://outlook.office365.com/",
new ClientCredential(SettingsHelper.ClientId, SettingsHelper.AppKey),
new UserIdentifier(userObjectId, UserIdentifierType.UniqueId));
return result.AccessToken;
}
catch (AdalException exception)
{
//handle token acquisition failure
if (exception.ErrorCode == AdalError.FailedToAcquireTokenSilently)
{
authContext.TokenCache.Clear();
}
throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.Unauthorized));
}
}
public async Task<string> AcquireAzureGraphTokenAsync()
{
AuthenticationContext authContext = new AuthenticationContext(string.Format("{0}/{1}", SettingsHelper.AuthorizationUri, tenantId), new ADALTokenCache(signInUserId));
try
{
var result = await authContext.AcquireTokenSilentAsync(#"https://graph.windows.net/",
new ClientCredential(SettingsHelper.ClientId, SettingsHelper.AppKey),
new UserIdentifier(userObjectId, UserIdentifierType.UniqueId));
return result.AccessToken;
}
catch (AdalException exception)
{
//Same as other method
}
}
ADAL uses the stored refresh tokens automatically and transparently, you aren't required to perform any explicit action. AcquireTOkenByRefreshToken is in the ADAL surface for legacy reasons, and has been removed from version 3.x. More background at http://www.cloudidentity.com/blog/2015/08/13/adal-3-didnt-return-refresh-tokens-for-5-months-and-nobody-noticed/

Office 365 Rest Api Having issues getting access token

So far i have this.
public static async Task<OutlookServicesClient> CreateOutlookClientAsync(string capability)
{
try
{
string authority = CommonAuthority;
// Create an AuthenticationContext using this authority.
_authenticationContext = new AuthenticationContext(authority);
//See the Discovery Service Sample (https://github.com/OfficeDev/Office365-Discovery-Service-Sample)
//for an approach that improves performance by storing the discovery service information in a cache.
DiscoveryClient discoveryClient = new DiscoveryClient(
async () => await GetTokenHelperAsync(_authenticationContext, DiscoveryResourceId));
// Get the specified capability ("Contacts").
CapabilityDiscoveryResult result =
await discoveryClient.DiscoverCapabilityAsync(capability);
var client = new OutlookServicesClient(
result.ServiceEndpointUri,
async () =>
await GetTokenHelperAsync(_authenticationContext, result.ServiceResourceId));
return client;
}
catch (Exception e)
{
Console.WriteLine(e.Message);
if (_authenticationContext != null && _authenticationContext.TokenCache != null)
_authenticationContext.TokenCache.Clear();
return null;
}
}
}
private static async Task<string> GetTokenHelperAsync(AuthenticationContext context, string resourceId)
{
string accessToken = null;
AuthenticationResult result = null;
string myId = WebConfigurationManager.AppSettings["ida:ClientID"];
string myKey = WebConfigurationManager.AppSettings["ida:Password"];
ClientCredential client = new ClientCredential(myId,myKey);
result = await context.AcquireTokenAsync(resourceId, client);
//result =context.AcquireToken(resourceId, ClientID,_returnUri);
accessToken = result.AccessToken;
return accessToken;
}
When i get to result one of two things happen if i user AcquireTokenAsync i get an error stating Application with identifier XXXX was not found in directory api.office.com otherwise if i run AcquireToken i get the login modal to pop but an error occurs indicating the request must contain client_secret .
I have no idea how to resolve this issue i suspect it may have something to do with the actual app configuration i have tried both creating my own app in Azure AD and using VS Connected Service, Has Anyone Else ran into a similar issues?
Based on the errors you're seeing, there seems to be an issue with how your app is registered. The first error usually happens when the app is not marked as multi-tenant, and you login to the app with a tenant other than the one where the app is registered.
The second error is odd. Client secret is what you're reading out of the ida:Password element and passing in the ClientCredential object.
I just put a .NET tutorial up yesterday that walks through setting this stuff up. Take a look and see if that helps get you unblocked.

Asp.net Web API: HttpClient Download large files breaks

I have a web service (made in Asp.net Web API) that returns an xml file of about 10MB size.
The service has been tested with Fiddler and it is working
I am trying to download the file using HttpClient class. The problem is that the compilator never gets outside the await client.GetAsync() method, even if the API project returned the HttpResponseMessage.
This is my function
public async Task<XDocument> DownloadXmlAsync(string xmlFileName)
{
using (HttpClient client = new HttpClient())
{
client.BaseAddress = new Uri("http://localhost:51734/");
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("text/xml"));
// When the copiler enters this next command, it doesn't get outside anymore
HttpResponseMessage response = await client.GetAsync("api/applications/ApplicationXml?fileName=" + xmlFileName);
response.EnsureSuccessStatusCode();
string stringResponse = await response.Content.ReadAsStringAsync();
XDocument xDoc = new XDocument(stringResponse);
return xDoc;
}
}
I updated also the maxRequestLength in web.config
<httpRuntime maxRequestLength="15360" />
What i am doing wrong?
Edit
Calling the function
public async Task<ActionResult> Index()
{
var xmlTask = DownloadXmlAsync("1.xml");
// doesn't reach here
var result = xmlTask.Result;
return View();
}
You're causing a classic deadlock by calling Result. Instead, you should await the task:
public async Task<ActionResult> Index()
{
var xmlTask = DownloadXmlAsync("1.xml");
// doesn't reach here
var result = await xmlTask;
return View();
}
I explain this deadlock in full on my blog, but the general idea is like this:
ASP.NET only allows one thread to be processing a request at a time.
When you await a Task, the compiler will capture a "context" and use it to resume the method when the Task completes. In the case of ASP.NET, this "context" is a request context.
So when DownloadXmlAsync (asynchronously) waits for GetAsync to complete, it returns an incomplete task to Index.
Index synchronously blocks on that task. This means the request thread is blocked until that task completes.
When the file is received, GetAsync completes. However, DownloadXmlAsync cannot continue because it's trying to resume that "context", and the "context" already has a thread in it: the one blocked on the task.
Hence, deadlock.

Resources