Search This Blog

Monday, September 20, 2010

Keep track download in ASP.NET

Situation:
I have a software in my web server and let visitor download for free, i wish to keep track of total download and visitor location. 

Feasibility:
For the location keep tracking, i use GeoIP (GeoLiteCity.dat) http://www.maxmind.com/app/ip-location 

Solution:

Database:
I have create a table called downloadlog with field below. I plan to have different type of product in future, so i add ProductFamilyID field. If you don't have that, you can ignore it.















Now, i need a stored procedure called psp_DownloadLog_Add that insert data into table above. The code should be as simple as possible



CREATE PROCEDURE [dbo].[psp_DownloadLog_Add]
(
@p_IP NVARCHAR(50),
@p_Country NVARCHAR(255),
@p_CountryCode VARCHAR(50),
@p_City NVARCHAR(255),
@p_ReferrerURL        NVARCHAR(512),
@p_ProductFamilyID INT
)
AS
BEGIN
SET NOCOUNT ON;

INSERT INTO tblDownloadLog
(
IP,
Country,
CountryCode,
City,
ProductFamilyID,
ReferrerURL,
DownloadDate
)
VALUES
(
@p_IP,
@p_Country,
@p_CountryCode,
@p_City,
@p_ProductFamilyID,
@p_ReferrerURL,
GETDATE()
)

SET NOCOUNT OFF;

END

ASP.NET

To make the system more structural and manageable, I have create 2 classes to handle the download log. DownloadLogInfo class mainly is use the deal with the information that need to log into database. DownloadLog class is mainly the class who do the communication with the database. Please check the code below.

DownloadLogInfo class



 public sealed class DownloadLogInfo
    {
         public DownloadLogInfo() { }
        
         int _downloadID = 0;
         string _ip = "";
         string _country = "";
         string _countryCode = "";
         string _city = "";
         int _productFamilyID = 0;
         string _referrerURL = "";
         DateTime _downloadDate = DateTime.Now;


         public int DownloadID { get { return _downloadID; } set { _downloadID = value; } }
         public string IP { get { return _ip; } set { _ip = value; } }
         public string Country { get { return _country; } set { _country = value; } }
         public string CountryCode { get { return _countryCode; } set { _countryCode = value; } }
         public string City { get { return _city; } set { _city = value; } }
         public int ProductFamilyID { get { return _productFamilyID; } set { _productFamilyID = value; } }
         public string ReferrerURL { get { return _referrerURL; } set { _referrerURL = value; } }
         public DateTime DownloadDate { get { return _downloadDate; } set { _downloadDate = value; } }

         public DownloadLogInfo(int pDownloadID, string pIP, string pCountry, string pCountryCode, string pCity, int pProductFamilyID, string pReferrerURL, DateTime pDownloadDate)
         {
             _downloadID = pDownloadID;
             _ip = pIP;
             _country = pCountry;
             _countryCode = pCountryCode;
             _city = pCity;
             _productFamilyID = pProductFamilyID;
             _referrerURL = pReferrerURL;
             _downloadDate = pDownloadDate;

         }


    }

DownloadLog Class

    public sealed class DownloadLog
    {
        public void Add(DownloadLogInfo pInfo, string pConnectionString)
        {
            SpParamInfo[] myParamInfo = new SpParamInfo[6];
            myParamInfo[0] = new SpParamInfo("@p_IP", SqlDbType.NVarChar, pInfo.IP);
            myParamInfo[1] = new SpParamInfo("@p_Country", SqlDbType.NVarChar, pInfo.Country);
            myParamInfo[2] = new SpParamInfo("@p_CountryCode", SqlDbType.NVarChar, pInfo.CountryCode);
            myParamInfo[3] = new SpParamInfo("@p_City", SqlDbType.NVarChar, pInfo.City);
            myParamInfo[4] = new SpParamInfo("@p_ProductFamilyID", SqlDbType.Int, pInfo.ProductFamilyID);
            myParamInfo[5] = new SpParamInfo("@p_ReferrerURL", SqlDbType.NVarChar, pInfo.ReferrerURL);

            DbAdapter myDbAdapter = new DbAdapter(pConnectionString);
            myDbAdapter.ExecuteNonQuery("psp_DownloadLog_Add", myParamInfo);

            myDbAdapter.Dispose();

        }

    }

Now, I have create a page, call download.aspx. This page will actually get information from the visitor and insert into database. After that it will force a file to be downloaded. Before that, i already GeoLiteCity.dat file and put into my App_Data folder.


Code behind for download.aspx


protected void Page_Load(object sender, EventArgs e)
    {
        string VisitorReferrer;

        // Full path to GeoLiteCity.dat file
        string FullDBPath = Server.MapPath("~/App_Data/GeoLiteCity.dat");
        // Visitor's IP address
        string VisitorIP; 
            
        VisitorIP  = Request.ServerVariables["REMOTE_ADDR"];
      
        if (Request.UrlReferrer != null)
        {
            VisitorReferrer = Request.UrlReferrer.ToString();
        }
        else
        {
            VisitorReferrer = "";
        }

        // Create objects needed for geo targeting
        Geotargeting.LookupService ls = new Geotargeting.LookupService(FullDBPath, Geotargeting.LookupService.GEOIP_STANDARD);
        Geotargeting.Location visitorLocation = ls.getLocation(VisitorIP);
        
        DownloadLog myDownloadLog = new DownloadLog();
        DownloadLogInfo myDownloadLogInfo = new DownloadLogInfo();


        if (visitorLocation != null) // get the geoip information using visitor IP address
        {
            myDownloadLogInfo.Country = visitorLocation.countryName;
            myDownloadLogInfo.CountryCode = visitorLocation.countryCode;
            myDownloadLogInfo.City = "unknown";
            if (visitorLocation.city != null)
            {
                myDownloadLogInfo.City = visitorLocation.city;
            }
            
            myDownloadLogInfo.IP = VisitorIP;
            myDownloadLogInfo.ProductFamilyID = 1;
            myDownloadLogInfo.ReferrerURL = VisitorReferrer;
        }
        else
        {
            string country = "unknown";
            string countryCode = "unknown";
            string city = "unknown";
            myDownloadLogInfo.Country = country;
            myDownloadLogInfo.CountryCode = countryCode;
            myDownloadLogInfo.City = city;
            myDownloadLogInfo.IP = VisitorIP;
            myDownloadLogInfo.ProductFamilyID = 1;
            myDownloadLogInfo.ReferrerURL = VisitorReferrer;
        }

       
       // WebConfig.Connection is the connection the database and insert data into database
       myDownloadLog.Add(myDownloadLogInfo, WebConfig.Connection);
        
       Response.ContentType = "application/zip";
       Response.AddHeader("content-disposition", "attachment; filename=softwaresetup.zip");

       FileStream sourceFile = new FileStream(@"C:\inetpub\dotnetfish\software\softwaresetup.zip", FileMode.Open);
        
       long FileSize;
       FileSize = sourceFile.Length;
       byte[] getContent = new byte[(int)FileSize];
       sourceFile.Read(getContent, 0, (int)sourceFile.Length);
       sourceFile.Close();

       Response.BinaryWrite(getContent);
    }
Hope this help.

No comments: