CodeTalk
LANGUAGES: C#
ASP.NET VERSIONS: 2.0
Build Your Own Photo Gallery: Part I
Getting Started
By Bipin Joshi
You probably preserve many moments of your life in photos. And you probably want to share those moments with your friends and relatives. A photo gallery is the perfect place to share your snapshots with others. This three-part series will demonstrate how you can build a photo gallery complete with categories, thumbnails, and security using ASP.NET 2.0 and SQL Server 2005. In this first part we ll start with database design and a few utility classes.
Functional Requirements
Let s first summarize our expectations for the photo gallery application we are going to build:
- The administrator should be able to create albums in the system.
- The administrator should be able to mark the albums as public or private.
- The administrator should be able to upload photos to the albums.
- The photos should be stored in a SQL Server database and not as physical files.
- The administrator should be able to specify attributes for the photos, such as title and description.
- The photo thumbnails should be generated automatically as per the specified dimensions without any need to upload small images.
- The full photo is to be displayed when a user clicks on the thumbnail.
ASP.NET Feature Illustration
We will use ASP.NET 2.0 and SQL Server 2005 Express Edition to develop the photo gallery. The application will illustrate:
- How to store and retrieve images in a SQL Server database.
- How to display images in data bound controls such as DataList and FormView.
- How to create thumbnail images on the fly.
- How to work with a file upload control to upload files on the server.
- How to implement security using Forms authentication, Membership, Roles, and login controls.
Creating the Web Application
To begin, create a new ASP.NET Web site using Visual Studio .NET or Visual Web Developer. Figure 1 shows the New Web Site dialog box of Visual Studio .NET.
Figure 1: Creating a new Web site in
VS.NET.
All the administrative pages are stored in a folder named Admin; other pages are stored directly under the virtual root. Create a folder named Admin inside the application folder.
Database Schema
All the data, including photos and album definitions, will be stored in a SQL Server 2005 database. To add a new SQL Server database in your Web site, right click on the App_Data folder and select Add New Item to open the dialog box shown in Figure 2.
Figure 2: The Add New Item dialog
box.
Name the database PhotoDb.mdf. Once the database is created we can create tables in it. Figure 3 lists all the tables and their columns that we need. Figure 4 shows the database diagram of these two tables.
Table Name |
Columns |
Description |
Albums |
AlbumID (int, Identity) Name (varchar) Description (varchar) IsPublic (byte) DateCreated (DateTime)
|
This table stores the photo album definitions. |
Photos |
PhotoID (int, Identity) AlbumID (int) Name (varchar) Description (varchar) Image (Image) ThumbnailHeight (int) ThumbnailWidth (int) DateCreated (DateTime) |
This table stores photos and related information. |
Figure 3: Create these tables and columns in PhotoDb.mdf.
Figure 4: Database diagram of the
Albums and Photos tables.
Handling Data Access
To perform our database operations we use the SQL Data Source control. Data source controls act as a bridge between your database and the user interface. They help reduce the amount of code you write for data access. The SQL Data Source control also allows you to develop two-tier applications. Though most of the data access is taken care via the SQL Data Source control, at times we need to execute queries on our own. For that purpose, we ll create a class named SqlHelper that encapsulates such common tasks as opening a connection, closing a connection, and executing the queries.
To create the SqlHelper class, right click on your App_Code folder and select Add New Item. Then select Class from the Add New Item dialog box and name it SqlHelper. Figure 5 lists the main methods of the SqlHelper class.
Method |
Description |
public static int ExecuteNonQuery(string query) |
Allows you to execute action queries without any parameters. |
public static int ExecuteNonQuery(string query, SqlParameter[] p) |
Allows you to execute action queries with parameters. |
public static SqlDataReader ExecuteReader(string sql) |
Allows you to execute SELECT queries without any parameters and get returned results in a SqlDataReader. |
public static SqlDataReader ExecuteReader(string sql, SqlParameter[] p) |
Allows you to execute SELECT queries with parameters and get returned results in a SqlDataReader. |
public static object ExecuteScalar(string sql) |
Allows you to execute queries without any parameters that return a single value. |
public static object ExecuteScalar(string sql, SqlParameter[] p) |
Allows you to execute queries with parameters that return a single value. |
public static DataSet ExecuteDataSet(string sql) |
Allows you to execute SELECT queries without any parameters and get returned results in a DataSet. |
public static DataSet ExecuteDataSet(string sql, SqlParameter[] p) |
Allows you to execute SELECT queries with parameters and get returned results in a DataSet. |
Figure 5: Methods of the SqlHelper class.
As you can see, all the methods of SqlHelper are static so that you can call them without creating an instance of SqlHelper. Listing One shows the complete source code of the SqlHelper class.
We store the database connection string in the web.config file. Figure 6 shows the relevant markup of web.config.
providerName="System.Data.SqlClient"/> Figure 6: The database
connection string in the web.config file. As you can see, we use the In the static constructor of the SqlHelper class, we pick
up the above connection string. In each of the public methods, we essentially
create a new instance of the SqlConnection and SqlCommand objects. We then
configure the command object by setting its properties, such as CommandText and
Connection. If our query has any parameters, we also populate the Parameters
collection of the command object using a private method (FillParameters). We
then call the ExecuteNonQuery, ExecuteScalar, or ExecuteReader methods of the
command object. Create the Web forms and master pages, as shown in Figure 7. Web Form Name Folder Description AdminMasterPage.master Admin This is the master page for administrative Web forms. AlbumManager.aspx Admin Manages albums; i.e., add, edit, and delete album
definitions. PhotoManager.aspx Admin Manages photos. Allows you to upload photos and
categorize them in albums. MasterPage.master Root Acts as a master page for the album and photo pages. Default.aspx Root Acts as the home page of the photo gallery and displays a
list of all albums in the system. DisplayAlbum.aspx Root Displays thumbnails of all the images from an album,
along with their names and descriptions. DisplayPhoto.aspx Root Displays a selected photo, along with its name and
description. GetPhoto.aspx Root Gets a photo or its thumbnail from the SQL Server
database. Login.aspx Root Users are required to log in to access private albums.
This form acts as a log-in page for private albums and administrative tasks. Figure 7: List of Web
forms used in the application. Any photo gallery application needs to frequently deal
with images and their thumbnails. We ll create a utility class named
PhotoHelper that allows us to retrieve photos and thumbnails from the database
and display them in Web forms. To create this class, right click on the
App_Code folder and choose Add New Item. Name the class PhotoHelper. Figure 8
lists the methods of this class. Method Description public static Image GetThumbnail(int photoid) This method accepts a photo ID and returns its thumbnail
image as an Image. public static Image GetThumbnailForAlbum(int albumid) This method accepts an album ID and returns the
thumbnail of the latest photo from that album as an Image. public static Image GetPhoto(int photoid) This method accepts a photo ID and returns the whole
photo image in the form of an Image. Figure 8: Methods
of the PhotoHelper class. Note that you need to import System.Drawing,
System.Drawing.Imaging, and System.IO before you proceed with the coding of
this class: using System.Drawing; using System.Drawing.Imaging; using System.IO; Let s examine all the methods of PhotoHelper; Figure 9
lists the complete source code for the GetThumbnail utility method. public static Image GetThumbnail(int photoid) { string sql = "SELECT IMAGE,THUMBNAILHEIGHT,THUMBNAILWIDTH FROM PHOTOS WHERE
PHOTOID=@id"; SqlParameter[] p = new SqlParameter[1]; p[0] = new SqlParameter("@id", photoid); SqlDataReader reader = SqlHelper.ExecuteReader(sql, p); byte[] imagedata = null; int height = 0, width = 0; while (reader.Read()) { imagedata = (byte[])reader.GetValue(0); height = reader.GetInt32(1); width = reader.GetInt32(2); } reader.Close(); MemoryStream ms = new MemoryStream(imagedata); Image bigImage = Image.FromStream(ms); Image smallImage = bigImage.GetThumbnailImage(width, height, null,
IntPtr.Zero); return smallImage; } Figure 9: The GetThumbnail
method. The GetThumbnail method accepts the photo ID whose
thumbnail is to be created. Then it fetches the actual image and its thumbnail
height and width from the database using the ExecuteReader method of the SqlHelper
class. The image data is read into a byte array called imagedata. This image is
further converted into a MemoryStream. This is necessary because later we need
to create an Image from this stream. The Image class has a static method named
FromStream. This method accepts a stream and constructs an image out of it. The
return type of the FromStream method is another class named Image. The Image
class further has a method named GetThumbnailImage that creates a thumbnail of
the image. The parameters to the GetThumbnailImage method are: We finally return the thumbnail Image instance back to the
caller. The second method, GetThumbnailForAlbum, is shown in Figure 10. public static Image GetThumbnailForAlbum(int albumid) { SqlParameter[] p = new SqlParameter[1]; p[0] = new SqlParameter("@albumid",albumid); int photoid = int.Parse(SqlHelper.ExecuteScalar("SELECT TOP 1 PHOTOID FROM PHOTOS
WHERE ALBUMID=@albumid ORDER BY DATECREATED DESC",
p).ToString()); return GetThumbnail(photoid); } Figure 10: The GetThumbnailForAlbum
method. Albums by themselves do not have a photo. However, it
would be nice to have a thumbnail for the album cover. That is precisely what the
GetThumbnailForAlbum method does. It simply fetches the latest photo added to
the album and returns a thumbnail for it in the form of an Image. Finally, Figure 11 lists the source code for the GetPhoto
method. The code in Figure 11 is similar to Figure 9 but does not create a
thumbnail. The GetPhoto method accepts the ID of the photo to be retrieved and
returns the complete image retrieved from the database. public static Image GetPhoto(int photoid) { string sql = "SELECT IMAGE FROM PHOTOS WHERE
PHOTOID=@id"; SqlParameter[] p = new SqlParameter[1]; p[0] = new SqlParameter("@id", photoid); SqlDataReader reader = SqlHelper.ExecuteReader(sql, p); byte[] imagedata = null; while (reader.Read()) { imagedata = (byte[])reader.GetValue(0); } reader.Close(); MemoryStream ms = new MemoryStream(imagedata); Image bigImage = Image.FromStream(ms); return bigImage; } Figure 11: The GetPhoto
method. We need two master pages. One, AdminMasterPage.master, for
administrative pages, and the other, MasterPage.master, for the remaining
pages. Figure 12 shows the general layout of AdminMasterPage.master. To create this master page, add a new Master Page in the Admin
folder using the Add New Item dialog box (again, see Figure 1); name it
AdminMasterPage.master. Figure 13 shows the markup of this master page. <%@ Master Language="C#"
AutoEventWireup="true" CodeFile= "AdminMasterPage.master.cs"
Inherits="AdminMasterPage" %> Web Forms and Master Pages
Creating the PhotoHelper Utility Class
Creating Master Pages
Figure 12: Layout of
AdminMasterPage.master.