A system.net.webException when using httpclient on xamarin android - xamarin

error: NameResolutionFailure
public class JsonConverter
{
public async Task<string> GetStringbyJson(string link)
{
HttpClient client = new HttpClient ();
HttpResponseMessage message = await client.GetAsync (link);
return await message.Content.ReadAsStringAsync ();
}
}
public async override void OnActivityCreated (Bundle savedInstanceState)
{
base.OnActivityCreated (savedInstanceState);
lst = View.FindViewById<ListView> (Resource.Id.lstHome);
var result = await json.GetStringbyJson ("https://api-v2.soundcloud.com/explore/Popular+Music?tag=out-of-experiment&limit=30&linked_partitioning=1&client_id=9ac2b330e1b3&offset="+offset);
}
App just run when I removed "var result". I test app on device

The error is exactly what it says - it is unable to resolve the domain name you've given it.
The most likely cause is neglecting to enable INTERNET_PERMISSION in the app's manifest. But it could also be a general networking issue on the device. Can you resolve the domain from the device's browser?

Related

Store Workflow Activity Data When Publishing

I Need to store a specific activity data in another collection in database whenever a user publish a workflow in elsa.
I dont find any documentation, Please suggest me some resource or suggestion to achieve this. I have try to implement this with middleware. The Middleware code is
namespace WorkFlowV3
{
// You may need to install the Microsoft.AspNetCore.Http.Abstractions package into your project
public class CustomMiddleware
{
private readonly RequestDelegate _next;
static HttpClient client = new HttpClient();
public CustomMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task Invoke(HttpContext httpContext)
{
//Write Custom Logic Here....
client.BaseAddress = new Uri("#");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
string path = "/api/test-middleware-call";
HttpResponseMessage response = await client.GetAsync(path);
await _next(httpContext);
}
}
// Extension method used to add the middleware to the HTTP request pipeline.
public static class CustomMiddlewareExtensions
{
public static IApplicationBuilder UseCustomMiddleware(this IApplicationBuilder builder)
{
return builder.UseMiddleware<CustomMiddleware>();
}
}
}
But in this process, I cant fetch the specific activity data.
The easiest way to store information in your own DB in response to the "workflow published" event is by implementing a notification handler (from MediatR) that handles the WorkflowDefinitionPublished notification.
For example:
public class MyWorkflowPublishedhandler : INotificationhandler<WorkflowDefinitionPublished>
{
private readonly IMyDatabaseStore _someRepository;
public MyWorkflowPublishedhandler(IMyDatabaseStore someRepository)
{
_someRepository = someRepository;
}
public async Task Handle(WorkflowDefinitionPublished notification, CancellationToken cancellationToken)
{
var workflowDefinition = notification.WorkflowDefinition;
// Your logic to do a thing.
}
}
To register this handler, from your Startup or Program class, add the following code:
services.AddNotificationHandler<MyWorkflowPublishedhandler>();
Your handler will be invoked every time a workflow gets published.

Disable Auth doesn't work with BF nuget package 4.7.1

Version
Microsoft.Bot.Streaming and Microsoft.Bot.Builder
"4.7.1"
Describe the bug
For direct line speech local test, set IsAuthenticationDisabledAsync to true in building a BotFrameworkHttpAdapter. SendActivityAsync() fails to send response back with below error
Failed to fetch token before processing outgoing activity. An IIdentity is required in TurnState for this operation.
For webchat test, it failed at Conversation:: ReplyToActivityWithHttpMessagesAsync, I get 401 unauthorized issue
To Reproduce
Update nuget package of BF to 4.7.1
Implement public class DisabledAuthCredentialProvider : ICredentialProvider which set IsAuthenticationDisabledAsync to true
Build BotFrameworkHttpAdapterv with DisabledAuthCredentialProvider
See exception in SendActivitiesAsync
(await this.GetAppCredentialsAsync(this.GetBotAppId(turnContext), (string) null, new CancellationToken()).ConfigureAwait(false)).GetTokenAsync(false);
Seems to work for me (in Emulator). Running 4.7.1. Here's what I have in DisabledAuthCredentialProvider
public class DisabledAuthCredentialProvider : ICredentialProvider
{
public Task<string> GetAppPasswordAsync(string appId)
{
throw new NotImplementedException();
}
public Task<bool> IsAuthenticationDisabledAsync()
{
return Task.FromResult(true);
}
public Task<bool> IsValidAppIdAsync(string appId)
{
throw new NotImplementedException();
}
}
I can share my bot if that helps.

How to implement HttpClient in Xamarin.Forms applications using better CPU and Memory?

I am bit confused about all those problems and workarounds of httpclient usage in xamarin.forms. I would like to summarize my understanding and hesitations/questions
Disposing every time vs Singleton HttpClient and Static Client: It is said that dont use using around httpClient and use singleton implementation as stated in this article
Wrong;
var httpClient = new HttpClient(new HttpClientHandler
{
//Some settings
});
Correct:
public class HttpService
{
private readonly HttpClient _httpClient;
public HttpService()
{
_httpClient = CreateHttpClient();
}
Here the first question, if we dont use static what is the advantage of this?
Because HttpService will start a new client for each thread, not? If we use static client, will this cause any memory cycle?
Xamarin forms is very fragile about static dependency, if you are holding a static value inside a ViewModel and ViewModel is coupled with View using Freshmvvm, Prism etc., usually View wont be disposed and instance remains in the memory and causes memory leak even after popping the page.
DNS changes problem: it looks like that there is a problem to use singleton HttpClient whenever DNs changes as described here. How to overcome this problem in a xamarin.forms application? I dont see any ServicePointManager defined in .net standard 2.0. Do I really have to worry about this?
ReadAsStreamAsync vs ReadAsStringAsync when getting response. Does it make a big difference to use ReadAsStreamAsync? and is there any side effect to use as stream?
Should we dispose HttpResponseMessage with a using like below?
using (HttpResponseMessage response = await client.GetAsync(uri))
{
if (!response.IsSuccessStatusCode)
{
//Do something
}
else
{
//Do something
}
}
Finally my Class looks like as below; Do you see any problem with this?
proxy setting are described in this article
namespace myApp
{
public class HttpService
{
private readonly HttpClient client;
private JsonSerializer _serializer = new JsonSerializer();
public HttpService()
{
if (client == null)
{
try
{
HttpClientHandler handler = new HttpClientHandler
{
Proxy = Xamarin.Forms.DependencyService.Get<IProxyInfoProvider>().GetProxySettings()
};
client = new HttpClient(handler);
}
catch (Exception ex)
{
}
}
}
public async Task<T> GetItemAsync<T>(string url, CancellationToken cancellationToken=default(CancellationToken))
{
T returnObject = default(T);
Uri uri = new Uri(url);
try
{
using (HttpResponseMessage response = await client.GetAsync(uri,cancellationToken))
{
if (!response.IsSuccessStatusCode)
{
//Handle error
}
else
{
returnObject = await getReturnObject<T>(response);
}
}
}
catch (OperationCanceledException)
{
}
catch (System.Net.Http.HttpRequestException)
{
}
catch (Exception ex)
{
}
return returnObject;
}
public async Task<T> getReturnObject<T>(HttpResponseMessage response)
{
T returnObject = default(T);
if (response.IsSuccessStatusCode)
{
using (System.IO.Stream stream = await response.Content.ReadAsStreamAsync())
using (System.IO.StreamReader reader = new System.IO.StreamReader(stream))
using (JsonTextReader json = new JsonTextReader(reader))
{
returnObject = _serializer.Deserialize<T>(json);
}
//string content = await response.Content.ReadAsStringAsync();
//returnObject = JsonConvert.DeserializeObject<T>(content);
}
return returnObject;
}
}
}

Xamarin Android Share Link/Text via social media from custom renderer

I wan't to share a link via social media from custom renderer
public class CustomActions : ICustomActions
{
Context context = Android.App.Application.Context;
public void ShareThisLink()
{
Intent sharingInt = new Intent(Android.Content.Intent.ActionSend);
sharingInt.SetType("text/plain");
string shareBody = "https://www.google.com";
sharingInt.PutExtra(Android.Content.Intent.ExtraSubject, "Subject");
sharingInt.PutExtra(Android.Content.Intent.ExtraText, shareBody);
context.StartActivity(Intent.CreateChooser(sharingInt, "Share via"));
}
}
This error occur
Android.Util.AndroidRuntimeException: Calling startActivity() from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want?
even when I added the below code I still get same error
sharingInt.AddFlags(ActivityFlags.NewTask);
The problem is that Intent.CreateChooser creates yet another Intent. What you want to do is to set the flag on this new intent:
public void ShareThisLink()
{
Intent sharingInt = new Intent(Android.Content.Intent.ActionSend);
sharingInt.SetType("text/plain");
string shareBody = "https://www.google.com";
sharingInt.PutExtra(Android.Content.Intent.ExtraSubject, "Subject");
sharingInt.PutExtra(Android.Content.Intent.ExtraText, shareBody);
var intent = Intent.CreateChooser(sharingInt, "Share via");
intent.AddFlags(ActivityFlags.NewTask);
context.StartActivity(intent);
}
Alternatively to avoid the need to do this, you could cache the MainActivity instance Xamarin.Forms uses:
public MainActivity
{
public static MainActivity Instance {get;private set;}
protected override void OnCreate(Bundle bundle)
{
Instance = this;
...
}
}
And then use the Instance as the Context in your code instead of the Application.Context

Xamarin.Android auth AD B2C without forms. Use MSAL or AppAuth?

I'm trying to use AD B2C with my Mobile App using Xamarin.Android, but not Forms.
All examples on how to use AD B2C with Xamarin are using the MSAL, which seems to rely on using Xamarin.Forms. I was not able to find an example or documentation on how to integrate it into Xamarin.Android.
Examples I was able to find but did not meet my needs:
https://github.com/Azure-Samples/active-directory-android-native-appauth-b2c
https://github.com/Azure-Samples/active-directory-b2c-xamarin-native
Documentation I read and tried to apply, but did not result in a succesful authentication or where not applicable to my situation:
https://developer.xamarin.com/guides/xamarin-forms/cloud-services/authentication/azure/
https://developer.xamarin.com/guides/xamarin-forms/cloud-services/authentication/azure-ad-b2c/
https://developer.xamarin.com/guides/xamarin-forms/cloud-services/authentication/azure-ad-b2c-mobile-app/
Is there a way to use MSAL in Xamarin.Android without using Forms or do I have to use some other library like AppAuth?
UPDATE:
How I tried to use MSAL:
public static string ClientId = "MyClientId";
public static string SignUpSignInPolicy = "B2C_1_MyPolicyName";
public static string Authority = "My Authority";
public static string[] Scopes = { ClientId };
private AuthenticationManager()
{
AuthenticationClient = new PublicClientApplication(ClientId, Authority);
}
public async Task<AuthenticationResult> AuthenticateAsync()
{
if (!Initialized)
throw new InvalidOperationException("Cannot authenticate before AuthenticationManager has been initialized.");
AuthResult = await AuthenticationClient.AcquireTokenAsync(Scopes,
"",
UiOptions.SelectAccount,
string.Empty,
null,
Authority,
SignUpSignInPolicy);
return AuthResult;
}
public void Initialize(Activity activity)
{
if (Initialized)
return;
// Load shared prefrences (skipped)
AuthenticationClient.PlatformParameters = new PlatformParameters(activity);
Initialized = true;
}
In the call for AquireTokenAsync(..), this results in NullPointerException:
"Value cannot be null. Parameter name: clientId"
I'm using the same parameters as in the examples (and they don't crash), everything should be initialized.
One reason for this error could be that the parameters for AquireTokenAsync(..) are different when calling it from android. (Please see the source of PublicClientApplication and look for the precompiler directives.)
But if that's the case I don't really know how to build the project with, so that the correct version for android is selected.
UPDATE2:
Added code from activity which should launch the authentication process:
public class LoginActivity : Activity
{
private async void LoginButtonClicked()
{
try
{
AuthenticationManager.AuthManager.Initialize(this);
await AuthenticationManager.AuthManager.AuthenticateAsync();
}
// Create your application here
catch (Exception e)
{
CreateAndShowDialog(e, Resources.GetString(Resource.String.error_sync));
}
}
protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
{
base.OnActivityResult(requestCode, resultCode, data);
AuthenticationAgentContinuationHelper.SetAuthenticationAgentContinuationEventArgs(requestCode, resultCode, data);
}
Do you have this in your MainActivity.cs?
protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
{
base.OnActivityResult(requestCode, resultCode, data);
AuthenticationAgentContinuationHelper
.SetAuthenticationAgentContinuationEventArgs(requestCode, resultCode, data);
}
This is old.
But if anyone has the same problem it's highly unlikely that he did the same stupid error as I did:
Field members are initialized in order.
There was some dependency between my field members and due to wrong order one value evaluated to null when initializing the dependent part.

Resources