AKO
AKO

Reputation: 131

async and await with Twitter direct_messages/events using LinqToTwitter

I'm really stuck in this for days. I'm using LinqToTwitter with ASP.Net C#

I'm trying to get the new DirectMessages work, I followed the examples but with no luck.

I want the function to work on Button click, so what I tried is:

  1. BtnClick:

`

protected void Btn1_Click(object sender, EventArgs e)
        {
            string x = MyTest().Result;
        }

`

  1. MyTest:

`

static async Task<string> mytest()
{
        AspNetAuthorizer auth = DoAuthorization();
        var twitterCtx = new TwitterContext(auth);
        List<DMEvent> AllDmEvents = new List<DMEvent>();
        string Cursor;
        DirectMessageEvents dmResponse =
            await
                (from dm in twitterCtx.DirectMessageEvents
                 where dm.Type == DirectMessageEventsType.List &&
                 dm.Count == 10
                 select dm)
                .SingleOrDefaultAsync(); //In debugging mode, after this line is executed, it will go away and keep loading forever and never come back
        AllDmEvents.AddRange(dmResponse.Value.DMEvents);
        Cursor = dmResponse.Value.NextCursor;
        string xxx = (JsonConvert.SerializeObject(AllDmEvents, Formatting.None));
        return xxx;
}

`

  1. DoAuthorization:

`

static AspNetAuthorizer DoAuthorization()
    {
        AspNetAuthorizer auth = new AspNetAuthorizer();
        auth = new AspNetAuthorizer
        {
            CredentialStore = new SessionStateCredentialStore
            {
                ConsumerKey = "MyConsumerKey",
                ConsumerSecret = "MyConsumerSecret ",
                OAuthToken = "MyOAuthToken ",
                OAuthTokenSecret = "MyOAuthTokenSecret ",
                ScreenName = "MyUserName",
                UserID = 12345678
            }
        };
        return auth;
    }`

Any help would be SO much appreciated!

Upvotes: 1

Views: 184

Answers (1)

Joe Mayo
Joe Mayo

Reputation: 7513

The DoAuthorization() in your code looks like it came from the Console sample and that won't work with ASP.NET. The reason is that ASP.NET is stateless and the OAuth process brings you to the Twitter site and back. So, you have to break up the authorization into two pieces: Begin and Complete.

I'm guessing that you're using ASP.NET MVC, but the concept is similar (but different) if you're using WebForms). Here's the Begin part:

public class OAuthController : AsyncController
{
    public ActionResult Index()
    {
        return View();
    }

    public async Task<ActionResult> BeginAsync()
    {
        var auth = new MvcAuthorizer
        {
            CredentialStore = new SessionStateCredentialStore
            {
                ConsumerKey = ConfigurationManager.AppSettings["consumerKey"],
                ConsumerSecret = ConfigurationManager.AppSettings["consumerSecret"]
            }
        };

Notice that it uses an MvcAuthorizer, populating credentials. Once you have the MvcAuthorizer instance, redirect the user to Twitter for authorization, like this:

        string twitterCallbackUrl = Request.Url.ToString().Replace("Begin", "Complete");
        return await auth.BeginAuthorizationAsync(new Uri(twitterCallbackUrl));
    }

That send the user to the Twitter authorization page, where they give your app permission to operate on their behalf. Twitter will redirect the user back to twitterCallback, which is why the code above modified the URL to replace the Begin with Complete in your URL. So, Twitter redirect the user back to your app, which calls the CompleteAsync() action below:

    public async Task<ActionResult> CompleteAsync()
    {
        var auth = new MvcAuthorizer
        {
            CredentialStore = new SessionStateCredentialStore()
        };

        await auth.CompleteAuthorizeAsync(Request.Url);

        // This is how you access credentials after authorization.
        // The oauthToken and oauthTokenSecret do not expire.
        // You can use the userID to associate the credentials with the user.
        // You can save credentials any way you want - database, 
        //   isolated storage, etc. - it's up to you.
        // You can retrieve and load all 4 credentials on subsequent 
        //   queries to avoid the need to re-authorize.
        // When you've loaded all 4 credentials, LINQ to Twitter will let 
        //   you make queries without re-authorizing.
        //
        //var credentials = auth.CredentialStore;
        //string oauthToken = credentials.OAuthToken;
        //string oauthTokenSecret = credentials.OAuthTokenSecret;
        //string screenName = credentials.ScreenName;
        //ulong userID = credentials.UserID;
        //

        return RedirectToAction("Index", "Home");
    }

Now that your app has the user's permissions, grab their tokens and hold them for subsequent queries so you don't have to continue the OAuth process every time the user wants to use your app. Please see the notes in the code on how to get those credentials.

Now, when you want to perform a query, instantiate an MvcAuthorizer, like this:

static async Task<string> mytest()
{
    var auth = new MvcAuthorizer
    {
        CredentialStore = new SessionStateCredentialStore()
    };

    var twitterCtx = new TwitterContext(auth);
    List<DMEvent> AllDmEvents = new List<DMEvent>();
    string Cursor;
    DirectMessageEvents dmResponse =
        await
            (from dm in twitterCtx.DirectMessageEvents
             where dm.Type == DirectMessageEventsType.List &&
             dm.Count == 10
             select dm)
            .SingleOrDefaultAsync(); //In debugging mode, after this line is executed, it will go away and keep loading forever and never come back
    AllDmEvents.AddRange(dmResponse.Value.DMEvents);
    Cursor = dmResponse.Value.NextCursor;
    string xxx = (JsonConvert.SerializeObject(AllDmEvents, Formatting.None));
    return xxx;

}

You can see how the first statement of your modified myTest() method instantiates MvcAuthorizer with SessionStateCredentialStore, holding your credentials.

Finally, at the point in time where you want the user to authorize your app with Twitter (log in, on first query, or any other timing of your choice), check to see whether they're already authorized and re-direct if not, like this:

    public ActionResult Index()
    {
        if (!new SessionStateCredentialStore().HasAllCredentials())
            return RedirectToAction("Index", "OAuth");

        return View();
    }

Notice how the code above calls HasAllCredentials() on a SessionStateCredentialStore instance. I assume that you'll be adding your own logic to determine when to load the user's credentials, but wanted you to be aware of the HasAllCredentials() helper method to make it easier to know when the user must be authorized.

For more info, visit the LINQ to Twitter OAuth docs. The LINQ to Twitter source code also has Samples on how to use OAuth.

Upvotes: 1

Related Questions