Click here to Skip to main content
15,885,278 members
Articles / Web Development / ASP.NET
Tip/Trick

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

Rate me:
Please Sign up or sign in to vote.
2.50/5 (2 votes)
9 Jan 2012CPOL3 min read 21K   7   2
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, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
United States United States
Just another passionate software developer!

Some of the contributions to the open source world - a blog engine written in MVC 4 - sBlog.Net. Check it out here. For the codeproject article regarding sBlog.Net click here!

(Figuring out this section!)

Comments and Discussions

 
GeneralReason for my vote of 1 This implementation only seems to ma... Pin
Shane Church17-Jan-12 4:41
professionalShane Church17-Jan-12 4:41 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.