Build a realtime counter using ASP.NET
A basic understanding of C# and JavaScript is needed to follow this tutorial.
It is common practice on websites and applications to make viewers aware of how many others have interacted with the same content e.g. YouTube videos. The practice of displaying this information emphasizes the relevance of the resource and draws more attention to it.
In this tutorial, we will emulate this practice by displaying the number of visits to a single page website. We will use C Sharp, C# for short, as our server-side language with ASP.NET MVC to build our webpage and Pusher to provide realtime updates of the page visits.
Let’s get started!
Building the frontend for our realtime counter in .NET
First, let’s start up Visual Studio
For this tutorial, we’ll be using Visual Studio. It’s an IDE that makes ASP.NET development easier and quicker. Visual Studio 2017 is free and available for the popularly used Operating Systems. You can find installation details here.
Creating our new project
We’ll start a new project by clicking New Project on the Visual Studio dashboard. Following the GUI prompts (in this order) we:
- Set C# as the language to use
- Select ASP.NET MVC Project as the template
- Include a Unit Test Project (this is optional and can be unticked)
- Fill in the Project name e.g. Notif (any name would do)
- Fill in the Solution name i.e. application name (again any name would do)
- Select the version control options to include git to the project
And then click Create.
The project gets created with a default HomeController.cs
. This is the HomeController class file. For the purpose of this tutorial, being a single page website, this single Controller class will be enough.
💡 ASP.NET MVC routes follow the pattern of /{ControllerName}/{ActionName} i.e assuming our HomeController.cs has a method named Index the route would be viewdotnet.com/Home/Index. ASP.NET MVC provides Home as the default controller name and Index as the default action name so that a route ‘/’ i.e. viewdotnet.com/ maps to the Index method in the Home controller.
In our HomeController.cs
we’ll have
public ActionResult Index()
{
var mvcName = typeof(Controller).Assembly.GetName();
var isMono = Type.GetType("Mono.Runtime") != null;
ViewData["Version"] = mvcName.Version.Major + "." + mvcName.Version.Minor;
ViewData["Runtime"] = isMono ? "Mono" : ".NET";
return View();
}
ActionResult is the return type of the method which specifies that it will return an action in the form of rendering a view, serving a streamed file, etc. ViewData is used to pass data from the method to the HTML file (our view file) that will be rendered. View() creates a view response which we return. Note that **Mono**
is only available on a Mac OS machine.
💡 In ASP.NET MVC the views (html files) rendered by a Controller Class must exist in the View folder and either under the Shared folder or the Folder bearing the name of the Controller. i.e. for the HomeController views must be in either
Views/Home/*``.cshtml
orViews/Shared/*``.cshtml
.Also when the view is unspecified in the View function it defaults to
index.cshtml
; these views extend_Layout.cshtml
found in the Shared folder.
Create the single web page
To achieve a quick and simple web page for our visitors to view we’ll be using Bootstrap.
//_Layout.cshtml file
<html>
<head>
<title>@ViewBag.Title</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
</head>
<body>
@RenderBody()
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"> </script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
</body>
</html>
We’ve used CDNs to include to Bootstrap CSS and JS files and also the jQuery JS file (it is needed for Bootstrap JS).
@ViewBag is another means of passing data to the view file from the controller
@RenderBody is where our actual viewindex.cshtml
will be inserted in this base view
// index.cshtml file
<div class="container">
<div class="row">
<h2>View Funny Memes, Have a good laugh</h2>
<div class="col-md-8">
<img src="http://i.imgur.com/gRWkE0j.jpg">
</div>
</div>
</div>
Our page has a header and a big image (pretty minimal stuff)
Keeping track of views
Now we’ll write the code to display the number of visitors to our page. We’ll need our code:
- To recognize a visit
- To store the visits so far (adding to this stored value every time someone visits)
- To pass the data (number of visitors) to our view to display
In our HomeController.cs
we’ll add the code to retrieve the visits so far, increment it and pass it on to the view. To keep things light and simple, we’ll be using file storage as our store (i.e. reading and writing the number of visits to a file such as visitors.txt).
//HomeController.cs
...
using System.IO;
namespace notif.Controllers
{
public class HomeController : Controller
{
public ActionResult Index()
{
ViewBag.Title = "Views Dot Net | A pusher - .Net Tutorial";
var visitors = 0;
if (System.IO.File.Exists("visitors.txt")) {
string noOfVisitors = System.IO.File.ReadAllText("visitors.txt");
visitors = Int32.Parse(noOfVisitors);
}
++visitors;
var visit_text = (visitors == 1) ? " view" : " views";
System.IO.File.WriteAllText("visitors.txt", visitors.ToString());
ViewData["visitors"] = visitors;
ViewData["visitors_txt"] = visit_text;
return View();
}
...
We create a visitors variable and initialize it to 0. Then we check if the visitors.txt
file exists, if it does then we’ve been visited in the past and we read the content into the visitors variable. Next, we increment the value of visitors by 1 (the visitor we are currently serving) and save the new value back into our file.
💡 To check if a file exists, read, and write into it, we’ll use the File class (available from ASP.NET) which is a member of the System.IO namespace so at the top of our class file we’ve added
using System.IO;
Now that we have the number of visitors in a variable, we’ll pass it on to our view using ViewData. We’ve also added some supporting text based on the value of the visitors variable to improve readability. In our view file we’ll add some markup to display the visitors value and text we’re passing along.
//index.cshtml
<div class="container">
<div class="row">
<h2>View Funny Memes, Have a good laugh</h2>
<div class="col-md-8">
<img src="http://i.imgur.com/gRWkE0j.jpg">
</div>
</div>
<br>
<div class="row">
<div class="col-md-12">
<div class="pull-left">
<p> <b id="noOfVisitors">@ViewData["visitors"]</b> <span id="visitorsText"> @ViewData["visitors_txt"] </span> </p>
</div>
</div>
</div>
</div>
Now our page will look like:
Adding realtime updates to our views counter with Pusher Channels
While a user views our page we’d like them to know when more people visit the page by increasing the number of views without requiring a refresh. We will be using Pusher for this.
To start with, lets head over to the Pusher dashboard and create a Channels app. You can register for free if you haven’t got an account. Fill out the create app form with the information requested.
To make our app realtime, we’ll make each visit trigger an event via Channels on the server-side (i.e. backend) and have Channels listen and react to that event on the client-side (i.e. view using JavaScript).
Triggering event on the server-side
In our HomeController.cs
, on every new visit using Pusher we’ll trigger a newVisit
event on a channel we’ll call general
which will broadcast the current number of visits.
To do this, we’ll install Pusher Channels via NuGet - *a packer manager for ASP.NET *- by:
- Right clicking the
*Packages*
folder in our solution - Selecting
Add Packages
and; - Searching and selecting
Pusher Server
Next, we’ll initialize Pusher in our Controller using and trigger our newVisit
event.
//HomeController.cs
...
using PusherServer;
public ActionResult Index()
{
ViewBag.Title = "Views Dot Net | A pusher - .Net Tutorial";
var visitors = 0;
if (System.IO.File.Exists("visitors.txt")) {
string noOfVisitors = System.IO.File.ReadAllText("visitors.txt");
visitors = Int32.Parse(noOfVisitors);
}
++visitors;
var visit_text = (visitors == 1) ? " view" : " views";
System.IO.File.WriteAllText("visitors.txt", visitors.ToString());
var options = new PusherOptions();
options.Cluster = "PUSHER_APP_CLUSTER";
var pusher = new Pusher(
"PUSHER_APP_ID",
"PUSHER_APP_KEY",
"PUSHER_APP_SECRET", options);
pusher.TriggerAsync(
"general",
"newVisit",
new { visits = visitors.ToString(), message = visit_text });
ViewData["visitors"] = visitors;
ViewData["visitors_txt"] = visit_text;
return View();
}
💡 After Installing the
PusherServer
package we use it in our controller by addingusing PusherServer
at the top of our class definition.
After initializing Pusher using our PUSHER_APP_ID, PUSHER_APP_KEY, **PUSHER_APP_SECRET and PUSHER_APP_CLUSTER (be sure to replace these with the actual values from your dashboard), we will broadcast an object consisting of the number of visitors and the visitors supporting text with our pusher instance on the newVisit
event via the general
channel.
Listening for the event on our client-side
To react to our newVisit
event and its corresponding data we’ll be using JavaScript and JQuery for DOM manipulation to display the event data.
//_Layout.cshtml
...
<script src="https://js.pusher.com/4.0/pusher.min.js"></script>
<script>
// Enable pusher logging - don't include this in production
Pusher.logToConsole = true;
var pusher = new Pusher('PUSHER_APP_KEY', {
cluster:'PUSHER_APP_CLUSTER'
});
var channel = pusher.subscribe('general');
channel.bind('newVisit', function(data) {
var visits = data.visits;
var message = data.message;
$('#noOfVisitors').text( visits );
$('#visitorsText').text( message );
});
</script>
</body>
</html>
In the above code, we:
- Add the pusher library to our view via a CDN,
- Initialize Pusher passing in our PUSHER_APP_KEY,
- Subscribe to the
general
channel - Bind the channel to the
newVisit
event also attaching a callback function to the binding.
In our callback function we retrieve the visits and message data, then using jQuery pass it into our markup.
Now we run our application by clicking the play button in the top left corner of our IDE and here’s a glimpse of our resulting webpage.
Conclusion
In this tutorial, we’ve covered building a single web page with ASP.NET MVC in C# and how to implement realtime functionality in our web page using Pusher in both C# and JavaScript. There’s a lot more functionality we can achieve using ASP.NET and Pusher Channels together, feel free to extend the functionality of your web page.
6 September 2017
by Neo Ighodaro