Simple download protection for files and document using ASP.NET / C#

Posted in .NET 2.0 | Authentication | Security at Monday, 24 December 2007 14:36 GMT Standard Time
Really really simple. Feel free to write your own custom authentication method to fit your project context.

This is download.aspx:

<%@ Page Language="C#" AutoEventWireup="true"  CodeFile="download.aspx.cs" Inherits="download" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title>Download Page</title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
    
    </div>
    </form>
</body>
</html>

and this is the code behind that file:
using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;

public partial class download : System.Web.UI.Page 
{

    /// 
    /// Show error to user and close response object.
    /// 
    /// 
    private void WriteError(string error) {
        Response.Write(error);
        Response.End();
    }

    /// 
    /// Check authentication ticket
    /// 
    /// 
    private bool Authenticated() {
        //whatever is a session ticket, membership provider base, container in a coded URL querystring parameters, etc..
        return true;    
    }

    private string GetRepositoryFolder() {
        System.Configuration.AppSettingsReader r = new AppSettingsReader();
        return r.GetValue("RepositoryFolder", typeof(string)).ToString();                
    }


    protected void Page_Load(object sender, EventArgs e)
    {
        if (!Authenticated()){
            WriteError("You are not allowed to download this file");
            return;
        }
        else if (Request.QueryString["id"] == null)
        {
            WriteError("Missing parameter : id");
            return;
        }       
        
        string filePath = System.IO.Path.Combine(GetRepositoryFolder(),Request.QueryString["id"]);
        System.IO.FileInfo file = new System.IO.FileInfo(filePath);
        if (!file.Exists)
        {
            WriteError("File doesn't exists");
            return;
        }
        else {
            Response.Clear();
            Response.AddHeader("Content-Disposition", "attachment; filename=" + file.Name);
            Response.AddHeader("Content-Length", file.Length.ToString());
            Response.ContentType = "application/octet-stream";
            Response.WriteFile(file.FullName);
            Response.End();
        }        
    }
}
If successfully authenticated, you will be able to directly download the file:


If not, you will get an error message:

You are not allowed to download this file

AddThis Social Bookmark Button

Querying Youtube API using C#

Posted in .NET 2.0 | Google API | YouTube at Thursday, 20 December 2007 22:40 GMT Standard Time

This example shows how to use Google Data API to query and obtain videos from YouTube. There is also a downloadable zip file with the example in ASP.NET / C#.

  1. First of all, you need to download the Google Data APIs Client Libraries.
  2. Secondly, use the following namespaces:
    using Google.GData.Client;
    using Google.GData.Extensions;
    
  3. Use the service by querying by tag, or by search (you can also query related items, etc..):

    
        //by tag
        //feel free to change number of items, by there is a limit of 50, I believe. 
        //If you want to retreive more, you have to do a loop (retrieve 1-50, then 51 to 100, etc)
        protected void btoGo_Click(object sender, EventArgs e)
        {
            string url = "http://gdata.youtube.com/feeds/videos/-/" + this.txtTag.Text;
            AtomFeed myFeed = GetFeed(url, 1, 20);
            DisplayFeed(myFeed);        
        }
    
        //by search
        //feel free to change number of items, by there is a limit of 50, I believe. 
        //If you want to retreive more, you have to do a loop (retrieve 1-50, then 51 to 100, etc)
        protected void btoSearch_Click(object sender, EventArgs e)
        {
            string url = "http://gdata.youtube.com/feeds/videos?q=" + this.txtSearch.Text;
            AtomFeed myFeed = GetFeed(url, 1, 15);
            DisplayFeed(myFeed);
        }
    
    
  4. Use the following methods, or similars to get and display the Feed:

    /// 
        /// Create and returns and Google.GData.Client.AtomFee from url with the specific start and number of items
        /// 
        /// 
        /// 
        /// 
        /// 
        private static AtomFeed GetFeed(string url, int start, int number)
        {
            System.Diagnostics.Trace.Write("Conectando youtube at " + url);
            FeedQuery query = new FeedQuery("");
            Service service = new Service("youtube", "exampleCo");
            query.Uri = new Uri(url);
            query.StartIndex = start;
            query.NumberToRetrieve = number;
    
            AtomFeed myFeed = service.Query(query);
            return myFeed;
        }
    
        /// 
        /// Renders feed in example aspx page
        /// 
        /// 
        private void DisplayFeed(AtomFeed myFeed)
        {
            System.Text.StringBuilder sb = new System.Text.StringBuilder();
            foreach (AtomEntry entry in myFeed.Entries)
            {
                #region render each
                sb.Append("
    Title: "); sb.Append(entry.Title.Text); sb.Append("
    Categories: "); foreach (AtomCategory cat in entry.Categories) { sb.Append(cat.Term); sb.Append(","); } sb.Append(RenderVideoEmbedded(getIDSimple(entry.Id.AbsoluteUri))); sb.Append("
    Published on: "); sb.Append(entry.Published); #endregion } this.lblResults.Text = sb.ToString(); } private string RenderVideoEmbedded(string idSimple) { return string.Format("
    ", idSimple); }
Related resources:


Download example web site project in C#:
youtubeAPIExample.zip (65,91 KB)

AddThis Social Bookmark Button

Inheriting from System.Exception or System.ApplicationException?

Posted in .NET quirks at Monday, 17 December 2007 18:02 GMT Standard Time
Yes, there is a bit of confusion about this (also read this post).

I understand that the right way to create your application specific exceptions classes is to inherit from Exception class:
public class MyCustomEx : System.Exception{
   //class implementation
}
And if in any case you have to throw a general application exception that has not specific type, throw a System.ApplicationException:
throw new System.ApplicationException("Error retrieving data. The web service may be down");

AddThis Social Bookmark Button

Using a RAM drive to compile Visual Studio .NET projects

Posted in .NET 2.0 | Performance | Productivity | Visual Studio 2005 | RAM disk at Saturday, 15 December 2007 10:18 GMT Standard Time
(updated 22 dec 07)

After reading some blog posts like this I decide to test on my computers how important is hard disk speed in order to increase your productivity when compiling Visual Studio solutions with more than a few project.

I also wanted to see the gain if I placed my solution (more than 25 projects) in a RAM drive disk instead of the hard disk (be sure you backup frecuently if you do that, or get one of this things to avoid data lost).

In order to create a RAM drive, I download the trial version of Virtual Hard Drive Pro
 from FarStone.

There are the results:

1. Environment hardware information

My desktop:
  1. CPU: AMD Sempron, 1800 MHz
  2. RAM: 2 x (1 Gb Kingston)
  3. Hard disks (2):
    1. System: ATA-100 40 Gb Barracuda 7200 rpm. Average seek: 8.5 ms. Buffer size: 2Mb. Average read speed: 40 Mb/second (*).
    2. Data and code: SATA 200 Gb Barracuda 7200 rpm. Average seek: 8.5 ms. Buffer size: 8 Mb. Average read speed: 50 Mb/second (*).
  4. RAM drive speed (read): 900 Mb/sec
My laptop (Toshiba Satellite Pro M70):
  1. CPU: Intel Pentium Celeron 1.73 Ghz
  2. RAM: 2 x (512 Mb Toshiba)
  3. Hard disk (1) : Toshiba 5400 rpm. Average read speed: 30 Mb/second (*)
  4. RAM drive speed (read): 1500 Mb/sec
* (Hard disk speed tests have been done with HD_Speed from www.steelbytes.com)

2. The Microsoft Visual Studio solution

A Microsoft Visual Studio .NET 2005 solution with 26 projects (Windows Forms and Windows library projects mainly), in C#.

3. Results

Compilation:

Desktop machine:

a) Compilation on hard disk (no RAM Drive installed yet): 72 seconds*
b) Compilation on a 500 MB RAM Drive : 71 seconds*

Laptop machine:

a) Compilation on hard disk (no RAM Drive installed yet): 65 seconds*
b) Compilation on a 400 MB RAM Drive : 32 seconds*

*(average of three compilations)

4. Conclusions:

Seems like my desktop doesn't have much processor power, and the bottleneck is mainly on the CPU, since there is not much different results on readig from a 50 Mb/seconds hard disk or from a 900 MB/second one (the RAM Drive)

My laptop, instead has a slower disk drive but more processor power, so there is a lot of difference between compiling from hard disk and RAM drive. (it took half the time on the RAM disk - also RAM disk read speed is higher than in the desktop)

I still will do more tests with some other combinations of CPU and hard disk..

Feel free to do the above tests yourself and share the results.

Updated:
  • 22 dic 07: Added test with laptop. Desktop tests done again.

AddThis Social Bookmark Button