Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

ASP.Net MVC (2 & 3) - Tracking number of downloads

0.00/5 (No votes)
9 Jan 2012 1  
This tip explains how downloads could be tracked for any file in your website or another website


At times, you would wish to see the number of downloads your app (or any file) gets. The following tip discusses how this could be achieved. The intention is, if the user enters the url (for ex.) http://localhost:12345/downloads/CalendarControlSrc.zip, track the download and then return the file that the user requested. This is how you do them in ASP.Net MVC 3 (should also work in MVC 2).



The first step would be to access the database layer to save the count. I am not discussing this as its out of scope for this tip. As we intend to serve a file instead of a view, we just need to return a FileResult that takes in 3 parameters (other overloads are also available). The parameters expected are:



  • The url as received from Url.Content [Url.Content expects a virtual directory]
  • The application type of the file to be served. In this case it's a zip file and so the applicationType is "application/x-compressed"

C#
public ActionResult DownloadLink1()
{
    // access the database layer and increment the counter to
    // indicate that SampleApp was downloaded
    string url = Url.Content("~/Content/downloads/CalendarControlSrc.zip");
    return File(url, "application/x-compressed");
}


You may also wish to track the number of downloads you app (or some file) gets, when its hosted on another site. In that case, you cannot just use Url.Content as it expects a virtual path. So you will have to use the WebClient class to first download this file and then return it. In this case we use another overload of FileResult, as we are downloading the file and then presenting it to the user. This overload takes in a 3rd parameter which is the file name that the client sees while the download link is clicked (the client is free to change the name, of course). This overload of FileResult takes in a byte stream as the first parameter instead of a path returned by Url.Content. The first step just like the previous method would be to access the database layer to save the count.


C#
public ActionResult DownloadLink2()
{
    // access the database layer and increment the counter to
    // indicate that SampleApp was downloaded

    byte[] file = null;
    using (var client = new WebClient())
    {
        file = client.DownloadData("http://www.codeproject.com/KB/webforms/Calendar/CalendarControlSource.zip");
    }
    return File(file, "application/x-compressed", "CalendarControlSource.zip");
}


Now, I will give an example as to how these action methods could be used. Lets assume these 2 action methods are in a controller called DownloadsController. We need to generate routes so that they could be added to various views. If you observe, unlike normal routes which doesn't have an extension in the url (in mvc), these url's need to have an extension so that the url indicates that it is indeed pointing to the path of the file about to be downloaded. So instead of just using Html.ActionLink we need to use Html.RouteLink, which generates url's depending on the format given in Global.asax.cs file. To achieve this, add the 2 routes to the Global.asax.cs file's RegisterRoutes method (text in bold).



C#
public static void RegisterRoutes(RouteCollection routes)
{
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

    routes.MapRoute("DownloadRt1", "downloads/CalendarControlSrc.zip",
        new { controller = "Downloads", action = "DownloadLink1" });

    routes.MapRoute("DownloadRt2", "downloads/CalendarControlSource.zip",
        new { controller = "Downloads", action = "DownloadLink2" });

    routes.MapRoute(
        "Default", // Route name
        "{controller}/{action}/{id}", // URL with parameters
        new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
    );
}



Finally, given below is a cshtml file that utilizes these 2 links



C#
@{
    ViewBag.Title = "Index";
}

<h2>Index</h2>

@Html.RouteLink("download link 1", "DownloadRt1")
<br />
@Html.RouteLink("download link 2", "DownloadRt2")



The above Html.Routelink would generate the following links (assuming base url is http://localhost:12345) - http://localhost:12345/downloads/CalendarControlSrc.zip and http://localhost:12345/downloads/CalendarControlSource.zip. Html.RouteLink is a helper method that generates links using the route name (From Global.asax.cs passed in as the 2nd parameter. Clicking on these links would would call the database layer to log this download. Hope this tip was hepful!

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here