Visitor Tracker in ASP.NET

Visitor trackers aren’t new, and even novice HTML coders can place a free tracker in their webpage, but there comes a point when
you outgrow what’s available free, and you really need to get hold of the raw data behind your tracker.
 
Recording data for every visitor to the site may be out of the question, as you end up filling your database with too much archival data. Generally a tracker will keep detailed information about the last day’s traffic, then aggregated information for archival material. For example, it might be of interest to view which websites the last 20 visitors came from, but just a count of how many people came to the site last march might be sufficient.
 
I therefore created two tables in my database, RecentVisitors and AggregatedVisitors. With a trigger set up between the two, to automatically populate the AggregatedVisitors table based on new inserts into the RecentVisitors table, thus:
 
CREATE TRIGGER trigger_RecentVisitors
ON RecentVisitors
FOR INSERT
AS
BEGIN
 — note this will track hits not unique visitors.
 declare @websiteID int
 select top 1 @websiteID = websiteid from inserted  
 declare @VisitorsToday int
 select @VisitorsToday = count(*) from RecentVisitors  
 where dateDiff(day,Date,getdate())=0
 and websiteId=@websiteID
  
 delete from AggregatedVisitors where
 websiteID = @websiteID
 and
 Datediff(day,date,getDate())=0
 insert into AggregatedVisitors (Number,websiteID)
 values (@VisitorsToday,@websiteID)
 
 delete from recentVisitors where dateDiff(day,Date,getdate())>1
 
END
 
 
I then, put together some javascript to load a hidden image, which would execute an insert into RecentVisitors
 
<img name="Tracker" style="display:none">
 <script language="javascript">
 var WebsiteID = 1;
 var Tracker = window.document.images["Tracker"];
 Tracker.src = "default.aspx?WebsiteId=" + WebsiteID + "&Referrer=" + escape(document.referrer);
 </script>
 
To return a 1px x 1px image from asp.net is really easy, and combined with an insert into the database, I came up with:
 

if (Session["FirstTime"]==null)
{
   string strReferrer = Request.QueryString["Referrer"].ToString();
  
int intWebsiteID = Convert.ToInt32(Request.QueryString["WebsiteID"]);
  
string strSQL = "insert into RecentVisitors (IP,Referrer,websiteId) values (";
   strSQL += "’" + Request.ServerVariables["REMOTE_ADDR"] + "’,";
   strSQL += "’" + strReferrer.Replace("’","”") + "’,";
   strSQL += intWebsiteID + ")";
  
base.ExecuteNonQuery(strSQL);
   Session["FirstTime"]=
false;
}
Bitmap bmpCanvas =
new Bitmap(1,1);
Response.ContentType = "image/gif";
bmpCanvas.Save(Response.OutputStream,ImageFormat.Gif);

ExcecuteNonQuery is a function I wrote to run a statement against the database, and is outside the scope of this blog.

Then, to view this data in a meaningful way, I created a page with two dataGrids, dgRecentVisitors and dgAggregatedVisitors, which used the following SQL to display their results:

select top 20 rv.id,referrer,date from recentvisitors rv
join websites w on w.id = rv.websiteid
where charindex(w.websiteaddress,rv.referrer)=0
order by date desc

and

select * from aggregatedVisitors order by date desc.

and, that suffices for a tracker for my purposes, and I have access to the raw data, should I need to run queries to work out sales conversion rates etc. The only downfall is that it does not correctly measure visitors rather than hits, but that’s work for another day.

Njoy.

 

 

 
 
 
 
 
Categories: Uncategorized

Reconnecting ADSL programatically

I had an issue that my ADSL connection kept disconnecting every few hours, which meant that I manually had to go and open
the local web interface to my ADSL modem (Binatone), and press connect.
 
I figured out how to do this from code, by making a GET request to the following URL, my ADSL was reconnected.
 

http://192.168.1.2/doc/loginout.htm?

WINDWEB_URL = %2Fdoc%2Floginout.htm&

simple_ppp_username = xxxx&

simple_ppp_pwd = xxxx&

wanAdapterSelection = 0&

wan_encapsulation = 0&

wan_VPI = 0&

wan_VCI = 38&

PPP_connection_number = 1&

New_PPP_Action = 0

 

Categories: Uncategorized

VPN option greyed out in Windows XP

When setting up a VPN connection on Windows XP Pro, I found the VPN option greyed out.
 
Searching on the net, people said that the Remote Access Connection Manager service wasn’t running, however when you try to start this, you get an Access Denied error, and a "cannot allocate buffers" errror in the event log.
 
This is actually due to a registry corruption,
To fix it, go to HKL:MSystemCurrentControlSetRasmanPPPEAP then delete subkeys EXCEPT 13 & 4. Then reboot the pc.
 
Categories: Uncategorized

Parser Error Message: Access is denied

This is one of those horrible asp.net error messages, when for no reason, you update some code with new code and you get an access is denied error.(*)
 
There are some sensible suggestions listed on msdn as to why this happens, and how it’s all down to indexer service – although, when you already have this service disabled, you’d wonder what’s up?
 
Basically, I went through these steps
Kill the asp_wp process
stop w3svc service
delete the bin folder
restart w3svc service, and go to offending page
stop the w3svc service
replace the bin folder with old files
restart the w3svc service.
 
It makes little sense why this works, but it worked for me.
 
 
(*) the specifics of the error (if you do view|Source) are
[FileLoadException]: Access is denied: ‘erc’.
   at System.Reflection.Assembly.nLoad(AssemblyName fileName, String codeBase, Boolean isStringized, Evidence assemblySecurity, Boolean throwOnFileNotFound, Assembly locationHint, StackCrawlMark& stackMark)
   at System.Reflection.Assembly.InternalLoad(AssemblyName assemblyRef, Boolean stringized, Evidence assemblySecurity, StackCrawlMark& stackMark)
   at System.Reflection.Assembly.InternalLoad(String assemblyString, Evidence assemblySecurity, StackCrawlMark& stackMark)
   at System.Reflection.Assembly.Load(String assemblyString)
   at System.Web.UI.CompilationConfiguration.LoadAssemblies(Hashtable original)
[ConfigurationException]: Access is denied: ‘erc’. (c:winntmicrosoft.netframeworkv1.1.4322Configmachine.config line 258)
   at System.Web.UI.CompilationConfiguration.LoadAssemblies(Hashtable original)
   at System.Web.UI.TemplateParser.AppendConfigAssemblies()
   at System.Web.UI.TemplateParser.PrepareParse()
   at System.Web.UI.TemplateParser.Parse()
   at System.Web.UI.TemplateParser.GetParserCacheItemThroughCompilation()
   at System.Web.UI.TemplateParser.GetParserCacheItemInternal(Boolean fCreateIfNotFound)
   at System.Web.UI.TemplateParser.GetParserCacheItemWithNewConfigPath()
   at System.Web.UI.TemplateParser.GetParserCacheItem()
   at System.Web.UI.ApplicationFileParser.GetCompiledApplicationType(String inputFile, HttpContext context, ApplicationFileParser& parser)
   at System.Web.HttpApplicationFactory.CompileApplication(HttpContext context)
   at System.Web.HttpApplicationFactory.Init(HttpContext context)
   at System.Web.HttpApplicationFactory.GetApplicationInstance(HttpContext context)
   at System.Web.HttpRuntime.ProcessRequestInternal(HttpWorkerRequest wr)
Categories: Uncategorized

Using DBCC to create fair performance tests on stored procedures

When tweaking stored procedures, to make them run faster, we often compare them against a benchmark,
say SP_A vs SP_B.
 
However, if SP_A has been used actively, as part of a running system (i.e. website). it will be optimized by SQL server and will be placed in the procedural cache. This then results in Biased tests between SP_A and SP_B.
 
Therefore I would recommend using
DBCC FREEPROCCACHE
and
DBCC DROPCLEANBUFFERS
 
before timing the execution of SP_A against SP_B. Although, the affect of clearing the cache will cause them both to run slower, it will highlight performance gains of one against the other fairly.
 
 
 
Categories: Uncategorized

Full text catalog not populating on SQL server 2005

I had a problem with a full text catalog stopping at a particular point, and not populating further,
 
To diagnose, problems like this, open C:Program FilesMicrosoft SQL ServerMSSQL.1MSSQLLOG
 
where I saw, Could not allocate space for object ‘sys.fulltext_index_map_1813581499’.’i2′ in database ‘CFGlobal’ because the ‘PRIMARY’ filegroup is full. Create disk space by deleting unneeded files, dropping objects in the filegroup, adding additional files to the filegroup, or setting autogrowth on for existing files in the filegroup.
Therefore I just increased the space allocated to the primary filegroup, and it kicked off again.
 
Categories: Uncategorized

IFrames and the back button

If you have an Iframe on a page, and you press the back button, then oftentimes, only the Iframe goes back in it’s history, not the containing page.
 
There are a few workarounds for this, this is just a proposal, if it helps…
 
firstly, if you have a pre-loader on the iframe, such as…
 
graph.contentWindow.document.write(‘Please wait…’);
graph.src = ‘someurl’
 
when you can poll the Iframe for a change in the "Please wait message". (Note, that the url that you are redirecting to must be on the same domain as the parent page, or else you get a security exception)
 
// 951 – back button fix. 
 var wasGraphLoaded = false;
 setTimeout(‘checkGraph()’,500);
 function checkGraph()
 {
  if (imgGraph.document.body.innerHTML.indexOf("…")==-1)
  {
   // Graph must be loaded…
   wasGraphLoaded = true;  
   
  }
  else
  {
   // Graph isn’t loaded.
   if (wasGraphLoaded)
   {
    // The back button bust have been pressed
    window.history.go(-1);
   }
  }
  setTimeout(‘checkGraph()’,500);
 }
Categories: Uncategorized

Redistributing a VB6 application the “Free way”

After finding out that my WISE installer had passed it’s 30 day limit, and my Installshield CD scratched beyond repair, I looked on the web for a free way to redistribute a VB6 application.
 
My first attempt, was Advanced Installer 4, which looked promising. However, it also, is a 30 day trial, if you want go beyond the absolute basics. For instance, my app required the Soap Toolkit,(a COM object), so that was beyond the basic version. Also, it couldn’t properly self-register the COM DLL’s in the Advanced mode either. – Waste of time.
 
I then came accross a Microsoft tool, Visual Studio Installer, which looked well. With a bit of fiddling, I got it to create an MSI. However, an MSI may not work first time on pre-XP machines, since the Windows Installer is not guaranteed to be on the machine, So I looked for a generic MSI to EXE converter
 
The best I found was this: http://www.tmgdevelopment.co.uk/setuputility.htm Which you place in the same folder as the MSI.
 
I zipped them both together, and placed them on the website.
 
 
Categories: Uncategorized

Workaround for Bitmap ColorDepth in C#

I am almost cerain this is a bug in the .NET bitmap Codec, that you cannot change the color Depth… It always saves in its native format for Bitmap.
 
However, if you convert the image to a TIFF first, then it works.
 

Image imgTIFF = Image.FromStream(s);

ImageCodecInfo ici = GetEncoderInfo("TIFF");

EncoderParameter ep = new EncoderParameter(Encoder.ColorDepth,24L);

EncoderParameters eps =

new EncoderParameters(1);

eps.Param[0]= ep;

imgTIFF.Save(@"c:test.tiff",ici,eps);

Image imgBMP = Image.FromFile(@"c:test.tiff");

imgBMP.Save(@"c:test.bmp");

 
 
 
 
(for reference:)

private

ImageCodecInfo GetEncoderInfo(string mimeType)

{

ImageCodecInfo[] encs = ImageCodecInfo.GetImageEncoders();

for (int ix = 0; ix <= encs.Length; ix++)

{

if ( encs[ix].CodecName.IndexOf(mimeType) != -1)

{

return encs[ix];

}

}

return null;

}

Categories: Uncategorized

Converting a Bitmap to a pixel array

I was looking for some high performance code to convert a bitmap into a 2D byte array, this is what I came up with.
 
first I have a class called pixel.
public class pixel

{

  public byte red;

  public byte green;

  public byte blue;

}

 

then I read it using some Unsafe code thus:

public pixel[,] BitmapToArray(Bitmap b)

{

pixel[,] bmpData=new pixel[b.Width,b.Height];

// GDI+ still lies to us – the return format is BGR, NOT RGB.

BitmapData bmData = b.LockBits(new Rectangle(0, 0, b.Width, b.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);

int stride = bmData.Stride;

System.IntPtr Scan0 = bmData.Scan0;

unsafe

{

byte * p = (byte *)(void *)Scan0;

int nOffset = stride – b.Width*3;

int nWidth = b.Width * 3;

for(int y=0;y<b.Height;++y)

{

for(int x=0; x < nWidth; ++x )

{

switch(x%3)

{

case 0:

bmpData[x/3,y] =

new pixel();

bmpData[x/3,y].blue = (

byte)(p[0]);

break;

case 1:

bmpData[x/3,y].green = (

byte)(p[0]);

break;

case 2:

bmpData[x/3,y].red = (byte)(p[0]);

break;

}

++p;

}

p += nOffset;

}

}

b.UnlockBits(bmData);

return bmpData;

}

 

 

Categories: Uncategorized