I would like to build an app that i'll use for myself so i'm targeting the simple authentification through Token.
I had my token from Discog and i know it works because i tried it in a third party app.
I'm using DiscogClient which seems to be the most popular client.
I'm following the Sample usage in the following way :
var tokenInformation = new TokenAuthenticationInformation("My token"); // i'm using my real token of course
//Create discogs client using the authentication
var discogsClient = new DiscogsClient.DiscogsClient(tokenInformation);
var discogsSearch = new DiscogsSearch()
{
artist = "Michael Jackson"
};
//Retrieve observable result from search
var observable = discogsClient.Search(discogsSearch);
I dont have any exception when i run that code, but if i look at the observable var in debug mode, there is no result whatsoever.
I'm lost and am seeking help.
Thanks in advance
ok so this is how i made it work, sound simple but i'm not used to thread programming.
var tokenInformation = new TokenAuthenticationInformation("My token"); // i'm using my real token of course
{
//Create discogs client using the authentication
var discogsClient = new DiscogsClient.DiscogsClient(tokenInformation);
var discogsSearch = new DiscogsSearch()
{
artist = "Michael Jackson"
};
await SearchDis(discogsClient, discogsSearch);
}
then the function
private async static Task SearchDis (DiscogsClient.DiscogsClient dc, DiscogsSearch ds)
{
var res = await dc.SearchAsync (ds);
}
Related
I read that StartActivityForResult is deprecated and it is anyway not nice to have the callback in MainActivity.OnActivityResult() when you start the login process elsewhere.
Unfortunately I couldn't get any of the examples translated, seems Xamarin is missing essential things?
The missing part was that there is no implementation of IActivityResultCallback anywhere, so I created my own. Hope this will be included in Xamarin some time.
public class ActivityResultCallback : Java.Lang.Object, IActivityResultCallback
{
readonly Action<ActivityResult> _callback;
public ActivityResultCallback(Action<ActivityResult> callback) => _callback = callback;
public ActivityResultCallback(TaskCompletionSource<ActivityResult> tcs) => _callback = tcs.SetResult;
public void OnActivityResult(Java.Lang.Object p0) => _callback((ActivityResult)p0);
}
Using the TaskCompletionSource approach you can even await the callback. Here is how I used it for GoogleSignIn:
readonly Func<Task<GoogleSignInResult>> _googleSignInAsync = PrepareGoogleSignIn(
MainActivity.SharedInstance, "123-321.apps.googleusercontent.com"); //TODO: read from google-services.json
static Func<Task<GoogleSignInResult>> PrepareGoogleSignIn(ComponentActivity activity, string serverClientId)
{
var googleSignInOptions = new GoogleSignInOptions.Builder(GoogleSignInOptions.DefaultSignIn)
.RequestIdToken(serverClientId)
.RequestEmail()
.Build();
var googleSignInClient = GoogleSignIn.GetClient(activity, googleSignInOptions);
TaskCompletionSource<GoogleSignInResult> taskCompletionSource = null;
var activityResultLauncher = activity.RegisterForActivityResult(
new ActivityResultContracts.StartActivityForResult(),
new ActivityResultCallback(activityResult => taskCompletionSource?.SetResult(
Auth.GoogleSignInApi.GetSignInResultFromIntent(activityResult.Data))));
return () => {
taskCompletionSource = new TaskCompletionSource<GoogleSignInResult>();
activityResultLauncher.Launch(googleSignInClient.SignInIntent);
return taskCompletionSource.Task;
};
}
I have this in the Android implementation of my authentication service. You can also prepare it in MainActivity.OnCreate() with parameter this. Make sure it is called before the app goes to running state.
Later you can just await _googleSignInAsync(). Neat!
Some bonus code how to use it and forward to Firebase auth:
using Android.Gms.Auth.Api;
using Android.Gms.Auth.Api.SignIn;
using Android.Gms.Extensions;
using AndroidX.Activity;
using AndroidX.Activity.Result;
using AndroidX.Activity.Result.Contract;
using Firebase.Auth;
var signInResult = await _googleSignInAsync();
Console.WriteLine($"{signInResult.Status} {signInResult.SignInAccount?.DisplayName}");
if (!signInResult.IsSuccess || signInResult.SignInAccount == null)
throw new GoogleSignInCanceledException();
var credential = GoogleAuthProvider.GetCredential(signInResult.SignInAccount.IdToken, null);
var authResult = await FirebaseAuth.Instance.SignInWithCredentialAsync(credential);
AuthToken = (await authResult.User.GetIdToken(false).AsAsync<GetTokenResult>()).Token;
Any improvements? I'm happy to hear from you. Or are you looking for the iOS implementation?
I'm trying to send an activity through DirectLineClient library to my bot :
var directLineClient = new DirectLineClient($"{secret}");
directLineClient.BaseUri = new Uri($"https://directline.botframework.com/");
var conversation = await directLineClient.Conversations.StartConversationAsync().ConfigureAwait(false);
var activity = new Microsoft.Bot.Connector.DirectLine.Activity();
activity.From = new Microsoft.Bot.Connector.DirectLine.ChannelAccount();
activity.From.Name = "Morgan";
activity.Text = message;
activity.Type = "message";
var resourceResponse = await directLineClient.Conversations.PostActivityAsync(conversation.ConversationId, activity).ConfigureAwait(false);
await ReadBotMessagesAsync(directLineClient, conversation.ConversationId);
resourceResponse is always null.
Edit after Nicolas R answer
I added a method to wait for a response from the bot :
private static async Task ReadBotMessagesAsync(DirectLineClient client, string conversationId)
{
string watermark = null;
while (true)
{
var activitySet = await client.Conversations.GetActivitiesAsync(conversationId, watermark);
watermark = activitySet?.Watermark;
foreach (Microsoft.Bot.Connector.DirectLine.Activity activity in activitySet.Activities)
{
Console.WriteLine(activity.Text);
if (activity.Attachments != null)
{
foreach (Microsoft.Bot.Connector.DirectLine.Attachment attachment in activity.Attachments)
{
Console.WriteLine(attachment.ContentType);
}
}
}
if (activitySet.Activities.Count > 0)
{
return;
}
await Task.Delay(TimeSpan.FromSeconds(1)).ConfigureAwait(false);
}
}
But I never get out of ReadBotMessagesAsync.
I precise that I can communicate with my bot through HTTP request (tested with Postman), and it should be sending a response message whenever a message is sent.
Edited after OP precision
Methods always returns null
Based on the documentation/samples, it looks like this PostActivityAsync return is never used so the value may not be relevant.
From the samples:
await client.Conversations.PostActivityAsync(conversation.ConversationId, userMessage);
See example here.
For those who want more details, because this answer is only limited to the comparison with the sample use, this package is sadly not open-source: https://github.com/Microsoft/BotBuilder/issues/2756
Remarks (for those who would be using the wrong packages)
I would not recommend to use this DirectLineClient Nuget package located here:
https://www.nuget.org/packages/DirectLineClient as it is not maintained since May 2016 and the Bot Framework has changed a lot since that time.
Moreover, it is using DirectLine API 1.0, which is not the best practice at the time. See documentation here:
Important
This article introduces key concepts in Direct Line API 1.1 and
provides information about relevant developer resources. If you are
creating a new connection between your client application and bot, use
Direct Line API 3.0 instead.
I want to call GET method repeatedly to get random strings , as
while (!isFinished)
{
using (var client = new HttpClient())
{
string result = await client.GetStringAsync(new Uri("the consistent url"));
//I tried this as well
//var res = await client.GetAsync(new Uri("the consistent url"));
//string outp = await res.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
}
It should return different strings (I'm sure) but the return values are always the same as the first execution . Then I used Fiddler to watch my network traffic , I found that there is only one GET method called and the program are still in loop and returns same value . I don't know why.
In comparison , I tried to call another API by POST method , it works well . So what's the problem?
You can create the HttpClient with a IHttpFilter to set up cache usage:
HttpBaseProtocolFilter filter = new HttpBaseProtocolFilter();
// Setting it to .NoCache always forces a new request
filter.CacheControl.ReadBehavior = HttpCacheReadBehavior.NoCache;
filter.CacheControl.WriteBehavior = HttpCacheWriteBehavior.Default;
HttpClient client = new HttpClient(filter);
// .. your request code
The old code I've inherited for Twilio retrieves messages using the absolute PageNumber property of the MessageListRequest but according to the documentation this is obsolete and I should be using GetNextPage and GetPrevPage.
The API metadata shows this as obsolete with the message "Use GetNextPage and GetPreviousPage for paging. Page parameter is scheduled for end of life https://www.twilio.com/engineering/2015/04/16/replacing-absolute-paging-with-relative-paging".
Are there any examples of this usage? I couldn't find any in the documentation except in one of the API test methods and I'm not sure how well I can get to processing multiple pages with this example as a guide.
public class Foo : TwilioBase
{
public string Bar { get; set; }
}
public class FooResult : TwilioListBase
{
public List<Foo> Foos { get; set; }
}
[Test]
public void ShouldGetNextPage()
{
IRestRequest savedRequest = null;
FooResult firstPage = new FooResult();
firstPage.NextPageUri = new Uri("/Foos?PageToken=abc123", UriKind.Relative);
mockClient.Setup(trc => trc.Execute<FooResult>(It.IsAny<IRestRequest>()))
.Callback<IRestRequest>((request) => savedRequest = request)
.Returns(new FooResult());
var client = mockClient.Object;
var response = client.GetNextPage<FooResult>(firstPage);
mockClient.Verify(trc => trc.Execute<FooResult>(It.IsAny<IRestRequest>()), Times.Once);
Assert.IsNotNull(savedRequest);
Assert.AreEqual("/Foos?PageToken=abc123", savedRequest.Resource);
Assert.AreEqual(Method.GET, savedRequest.Method);
Assert.IsNotNull(response);
}
The old usage might look something like so:
var twilio = new TwilioRestClient(config.AccountSid, config.AuthToken);
var result = new List<Message>();
MessageResult tempResult;
int page = 0;
do
{
var request = new MessageListRequest();
request = new MessageListRequest { Count = 1000, DateSent = newestDate, DateSentComparison = ComparisonType.GreaterThanOrEqualTo, PageNumber = page++, To = config.FromNumber };
tempResult = twilio.ListMessages(request);
result.AddRange(tempResult.Messages);
} while (tempResult.NextPageUri != null);
Finally, I built the Twilio API 3.4.1.0 from the twilio-csharp GitHub project instead of NuGet since I need to update it to use the MessagingServiceSid which isn't included in the API yet.
Thanks for any pointers. I'll post a solution if I can figure it out on my own.
Actually, I got it to work now!
MessageResult messages = twilio.ListMessages(request);
do
{
if (messages.Messages != null)
{
foreach (var message in messages.Messages)
{
... process results
}
if (messages.NextPageUri != null)
{
messages = twilio.GetNextPage<MessageResult>(messages);
}
}
} while (messages.NextPageUri != null);
Did you try the example from the API Explorer?
https://www.twilio.com/console/dev-tools/api-explorer/sms/sms-mms-list
var twilio = new TwilioRestClient(AccountSid, AuthToken);
// Build the parameters
var options = new MessageListRequest();
var messages = twilio.ListMessages(options);
foreach (var message in messages.Messages)
{
Console.WriteLine(message.Body);
}
The helper library will automatically fetch from the API as you loop over the list until all records matching your criteria are processed.
You can limit the results with MessageListRequest.
Please give that a try and let me know how it goes.
I am creating a small program to get a instagram users following list using C# and instasharp. The code below will get me the first 50. I believe I have to use the pagination option to get the next url to get to the next page. Thats where Im stuck. How do I use pagination to loop through all of a users following?
var config = new InstaSharp.InstagramConfig("api", "oauth", "xxxxxx", "xxxxxxx", "xxxxxx");
var config1 = new InstaSharp.Endpoints.Relationships.Unauthenticated(config);
var result = config1.Follows(000000);
dynamic dyn = JsonConvert.DeserializeObject(result.Json);
foreach (var data in dyn.data)
{
listBox1.Items.Add(data.username);
}
Based on my response here: https://stackoverflow.com/a/25139236/88217
If you look at the unit tests on the InstaSharp github, you can see an example of how to use Pagination:
public async Task Follows_NextCursor()
{
//This test will fail if testing with an account with less than one page of follows
var result = await relationships.Follows();
result = await relationships.Follows(457273003/*ffujiy*/, result.Pagination.NextCursor);
Assert.IsTrue(result.Data.Count > 0);
}
In the case where you want to loop through and get all of them, I would expect you to do something like this:
int userID = 000000;
var result = await relationships.Follows(userID);
while(result.Data.Count > 0)
{
dynamic dyn = JsonConvert.DeserializeObject(result.Json);
foreach (var data in dyn.data)
{
listBox1.Items.Add(data.username);
}
result = await relationships.Follows(userID, result.Pagination.NextCursor)
}
Because this code uses await, you will have to mark the method as async, for more information on what that entails, I would suggest looking at the async/await keywords, a good introduction can be found at Stephen Cleary's Blog