|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Announcements
Chapters
Services
Feature Zones
|
IntroductionIt is sometimes useful to display the number of visits a page on a Web site has experienced using a counter that's displayed as part of the page's content. While adding a counter to a page written in ASP or ASP.NET is relatively straight-forward, adding a counter to a plain HTML page (no scripting of any kind) is a little different. This article describes a counter I created (see the following figure) using ASP.NET. The ASP.NET code generates an image using the
Overview of JScript .NETJScript .NET is one of the programming languages available on the .NET Framework and is Microsoft's version of ECMAScript - the language that's forms the basis of JavaScript. JScript .NET is very similar to C# and C++ in many ways, so if you know either language you'll immediately feel at home with JScript .NET. JScript .NET is an object oriented language that supports classes, inheritance, polymorphism, and all other popular OO features. You can also use JScript .NET to create Windows Forms-based applications (applications that have a GUI), Windows Services, console applications, Web Services, and ASP.NET pages and applications. Using the CounterThe following listing demonstrates how easily it is to use the counter with plain HTML: <img src="EWCounter.aspx?item=CodeProjectArticle"> The HTML <a href="http://www.designs2solutions.com" target="_blank"> <img src="EWCounter.aspx?item=CodeProjectArticle" border="0"> </a> Managing the Counter's DataThe counter keeps track of the value of a counter using simple text files that it accesses using the var itm :String = Request.QueryString("item");
// ... elsewhere on the page ...
createCounter(itm);
// etc...
function createCounter(nameOfItem:String)
{
var sw : StreamWriter;
var filePath:String = Server.MapPath("data\\") + nameOfItem + ".txt";
if(!File.Exists(filePath)) {
sw=File.CreateText(filePath);
sw.WriteLine("99");
sw.Close();
}
}
The initial value of the counter is 99, to make it look like the first visitor to a page is the hundredth visitor (gotta be optimistic). To create a new counter, specify a new, unique value for the The code that retrieves and optionally updates the counter's value is straightforward. The code does not perform any random access in the file and simply reads the value using a function getCounterValue(nameOfItem : String, readOnly : Boolean) : String
{
var fileIn:StreamReader =
File.OpenText(Server.MapPath("data\\" + nameOfItem + ".txt"),
FileMode.Open);
var current : String = new String("");
current = fileIn.ReadLine().ToString();
fileIn.Close();
if(readOnly)
return current;
var curInt : int = Convert.ToInt32(current);
curInt++;
var fs : FileStream =
new FileStream(Server.MapPath("data\\" + nameOfItem + ".txt"),
FileMode.Open,FileAccess.Write);
var sw : StreamWriter;
sw = new StreamWriter(fs);
sw.WriteLine(Convert.ToString(curInt));
sw.Close();
fs.Close();
return Convert.ToString(curInt);
}
The code reads the current value of the counter using the Rendering the CounterThe counter wouldn't be all that interesting if it's displayed as a simple text string, so the code uses the The first thing the code does is create a function drawCounter(nameOfItem : String, readOnly : Boolean)
{
// some code omitted for brevity...
var height : int = 20;
var width : int = 100;
var bmp : Bitmap= new Bitmap(width, height);
var g:Graphics = Graphics.FromImage(bmp);
// Create a DarkBlue background
g.FillRectangle(new SolidBrush(Color.DarkBlue), 0, 0, width, height);
// LightGreen for the small box on the left...
g.FillRectangle(new SolidBrush(Color.LightGreen), 0, 0, 26, 20);
The preceding listing establishes the two objects it needs to work with and creates the dark blue box that the counter's value appears in, and the light green box on the left side of the counter that hosts the counter's logo. The counter's logo is made up of three characters: "D2S". You can add text to a bitmap using the var maroonBrush:SolidBrush= new SolidBrush(Color.Maroon);
var blackBrush:SolidBrush= new SolidBrush(Color.Black);
var counterByFont:Font = new Font("Verdana", 7, FontStyle.Bold);
g.DrawString("D", counterByFont,blackBrush ,0,5);
g.DrawString("2", counterByFont,maroonBrush ,8,2);
g.DrawString("S", counterByFont,blackBrush ,16,5);
The logo's text was easy to add to the bitmap because its content does not change. The counter's value does change, so you need to pay a little more attention to how you position it within the enclosing rectangle. As in the preceding listing, the code uses the var counterFont:Font = new Font("Verdana", 8, FontStyle.Bold);
var whiteBrush:SolidBrush= new SolidBrush(Color.White);
When you position something on a bitmap, you place it by defining its location in terms of the top, left pixel of the object you want to draw. Since the counter's length can vary (as the value of the counter increases), the code measures the length of the counter's value as it appears in the enclosing box and positions it so that all of the numbers are visible, as shown in the following listing: var counterText : SizeF;
counterText = g.MeasureString(counterValue,counterFont);
g.DrawString(counterValue, counterFont, whiteBrush ,
(bmp.Width)-((counterText.Width)+5),3);
There's a lot going on in that short listing: it begins by measuring the counter's value based on the font it will be rendered in using the With the counter ready to be presented, the last thing the code does is deliver it to the client in the form of a JPG image using the following line: bmp.Save(Response.OutputStream, ImageFormat.Jpeg);
Limiting Counter UpdatesThe code you have seen so far isn't very selective when it comes to updating the counter: when a user refreshes a page, the counter gets updated. While this is okay in most cases, in some cases you want to ensure that you don't have users sitting around refreshing the page every few seconds to 'dope' the value of the counter (cause it to misstate the number of visitors by artificially inflating the value). One solution to this problem is to use a cookie that expires after a set period of time. If the cookie hasn't expired, the counter's value does not get updated but it still gets displayed. Working with cookies in ASP.NET is relatively straight-forward as long as you're aware of the fact that an expired cookie is equivalent to a var cookie:HttpCookie;
cookie = Request.Cookies("LastVisit");
var readOnly:Boolean = (cookie!=null);
drawCounter(itm,readOnly);
if(!readOnly) {
cookie = new HttpCookie("LastVisit",DateTime.Now.AddSeconds(120));
cookie.Expires = DateTime.Now.AddSeconds(60);
Response.AppendCookie(cookie);
}
The code queries for a cookie called "LastVisit" - if the cookie does not exist or has expired it is SummaryThis article described how to create a fast page hit counter that's easy to use with plain HTML. The code uses ASP.NET and the JScript .NET programming language and includes features like a logo, automatically creating new counters, and preventing users from artificially inflating the value of the counter. Installing and Using the Sample CodeUse the following steps to install the sample:
You should see a page that contains a short message and the counter image.
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||