1

I am working on an web based application in which I want to display a twitter stream on a specific query. User does need to refresh the webpage view and it will load the tweets automatically.

So far, I have created a simple console application using tweetinvi which read tweeets and performs all the custom logic on the tweets.

Next I need to know that how do I create project layout/infrastructure that my web app gets the constant feeds without client interaction.

Haseeb Asif
  • 1,766
  • 2
  • 23
  • 41

2 Answers2

4

As Nathan Cooper notes, SignalR is the best way of achieving this. As I've literally just built what you've described, I'll give you a detailed rundown of what you need to do..

Create a new ASP.NET MVC project, and install ASP.NET SignalR using NuGet as well as Tweetinvi

Right click on the App_Start folder and add a new OWIN Startup class (this should be listed in the contextual menu if you have installed SignalR using NuGet).

Your OWIN startup class should look like this:

[assembly: OwinStartup(typeof(TwitterClient.Web.App_Start.Startup))]

namespace TwitterClient.Web.App_Start
{
    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {            
            app.MapSignalR();
        }
    }
}

Add a new Folder to the project called "Hubs" and add a new SignalR Hub class (this should also be available as a template in the new file dialog in Visual Studio).

Create a new class called "TwitterConnection" wherever you feel like in the project. In the constructor for this class, do all of the stuff you did in your console application to connect to the Twitter API with Tweetinvi. Usually when you broadcast data from server to client in SignalR, you do it from within the Hub class, but you can obtain a reference to the SignalR hub outside of the hub class itself by using GlobalHost.ConnectionManager.GetHubContext<HUBNAME>(); where HUBNAME is the name of your hub. So your TwitterConnection class should look something like this:

public class TwitterConnection {
        private string _consumerKey = ConfigurationManager.AppSettings.Get("consumerKey");
        private string _consumerSecret = ConfigurationManager.AppSettings.Get("consumerSecret");
        private string _accessKey = ConfigurationManager.AppSettings.Get("accessToken");
        private string _accessToken = ConfigurationManager.AppSettings.Get("accessTokenSecret");

        private IHubContext _context = GlobalHost.ConnectionManager.GetHubContext<TwitterHub>();

        public TwitterConnection()
        {
            // Access the filtered stream
            var filteredStream = Stream.CreateFilteredStream();

            filteredStream.MatchingTweetReceived += (sender, args) => 
            { 
                _context.Clients.All.broadcast(args.Tweet.Text);
            };

            filteredStream.StartStreamMatchingAllConditions();

        }
}

In terms of the server-side stuff, you need to find a way of ensuring that there is only one instance of a stream open to Twitter at any one time. My quick and dirty way of doing this was to use Task.Factory.StartNew to create a new Task to manage to stream in the Global.asax file:

protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);

            // Start a new instance of the TwitterConnection class
            Task.Factory.StartNew(() => new TwitterConnection());
        }

Finally, you need to hook up the client-side element of SignalR. In your MVC Layout view (i.e. Views/Shared/_Layout.cshtml), add in a reference at the bottom of the HTML markup to the SignalR JavaScript library, the generated Hub proxy and to your external JavaScript file where your boilerplate SignalR JavaScript will go:

<!--Reference the SignalR library. -->
<script src="../../Scripts/jquery.signalR-2.2.0.min.js"></script>
<!--Reference the autogenerated SignalR hub script. -->
<script src="signalr/hubs"></script>
<script src="../../Scripts/application.js"></script>

Finally, your boilerplate code in application.js (or whatever you want to call it), will look something like this:

// document ready shorthand
$(function () {
    // obtain reference to the hub proxy and hub itself
    var theHub = $.connection.twitterHub;


    // this is the function that the server will call to broadcast new tweets
    theHub.client.broadcast = function (tweet) {
        var item = '<li>' + tweet.text + '</li>';
        $('ul.tweets').prepend(item);
    };

    // this is a function that indicates that connection to the hub has been successful
    $.connection.hub.start().done(function () {
        console.log("connected");
    });
});

Your Index.cshtml file will simply have an empty <ul> in it, where new tweets will be prepended to as and when they are received:

@{
    ViewBag.Title = "Home Page";
}

<div class="row">
    <div class="col-md-12">
        <ul class="tweets"></ul>
    </div>
</div>
adaam
  • 3,700
  • 7
  • 27
  • 51
3

You need to push live data to the browser. Use SignalR.

SignalR is great library for ASP.NET that allows you to write real time web applications. It uses Websockets under the covers, but has a number of fallback positions for older browsers. tutorial link

Nathan Cooper
  • 6,262
  • 4
  • 36
  • 75