Skip navigation

Build Your Own Photo Gallery: Part III

Display Public and Private Albums

CodeTalk

LANGUAGES: C#

ASP.NET VERSIONS: 2.0

 

Build Your Own Photo Gallery: Part III

Display Public and Private Albums

 

By Bipin Joshi

 

A photo gallery is the perfect place to share your snapshots. This three-part series demonstrates how you can build a photo gallery complete with categories, thumbnails, and security using ASP.NET 2.0 and SQL Server 2005.

 

In Part I of this series we developed database tables, a data access class, and a PhotoHelper utility class. We also developed two master pages, AdminMasterPage.master and MasterPage.master. In Part II we developed administrative pages for managing albums and photos. In this last part we ll develop pages that display a list of albums and allow users to see photos. We ll also implement the logic for public/private albums, as well as demonstrate how the PhotoHelper utility class we developed in Part I can be put to use to generate thumbnails and retrieve photos.

 

Displaying a List of Albums

Now that we ve completed the administrative pages, let s move on to pages that display the albums and photos.

 

Proceed by adding in the Web site a new Web form named Default.aspx. Make sure to set its master page to MasterPage.aspx. Drag and drop a SQL Data Source control on the Web form and configure it to select all the records from the Albums table (see Figure 1).

 


Figure 1: Configuring SQL Data Source to select albums.

 

Now drag and drop a DataList and set its Data Source to SqlDataSource1. Set the DataKeyField property of the DataList to AlbumID. Also, make sure to set the RepeatColumns property of DataList to 2 (so that the available albums will be displayed in two columns) and the RepeatDirection property to Horizontal. Design the DataList as shown in Figure 2.

 

 DataKeyField="AlbumID" DataSourceID="SqlDataSource1"

 OnItemDataBound="DataList1_ItemDataBound" RepeatColumns="2"

 RepeatDirection="Horizontal" Width="100%">

Font-Bold="True" Font-Size="Larger"

NavigateUrl='<%# Eval("AlbumID",

 "~/displayalbum.aspx?albumid={0}") %>'

Text='<%# Eval("Name") %>'

Font-Names="Verdana">


 Text='<%# Eval("Description") %>' Font-Names="Verdana"

 Font-Size="12px">


 Text="Added :" Font-Names="Verdana">

 Text='<%# Eval("DateCreated", "{0:g}") %>'>

Figure 2: Displaying a list of albums.

 

Here, we display the album name, description, and date of creation, along with the thumbnail image of the most recently added photo. The name of the album is displayed as a hyperlink. Point this hyperlink to DisplayAlbum.aspx and also pass albumid as a query string parameter. Add the code shown in Figure 3 in the ItemDataBound event handler of the DataList.

 

protected void DataList1_ItemDataBound(object sender,

 DataListItemEventArgs e)

{

Image img = (Image)e.Item.FindControl("Image1");

if (img != null)

img.ImageUrl = "~/getphoto.aspx?imgtype=thumbnail&albumid=" + DataList1.DataKeys[e.Item.ItemIndex].ToString();

}

Figure 3: ItemDataBound event handler.

 

We point the NavigateUrl property of the Image control to GetPhoto.aspx, passing two query string parameters, imgtype and albumid. The imgtype parameter indicates whether we want to retrieve a thumbnail or full image; an albumid parameter indicates the ID of the album. As mentioned previously, GetPhoto.aspx is responsible for fetching thumbnails and photos from the database and emitting them on the response stream. Figure 4 shows Default.aspx in run mode.

 


Figure 4: Default.aspx in run mode.

 

Displaying a List of Photos from an Album

Once the albums are displayed, the user can click on the desired album to view the photos within it. The list of photos in an album is displayed in a Web form named DisplayAlbum.aspx. This Web form receives the albumid as a query string parameter and displays thumbnails of all the photos from that album.

 

Start by adding in the Web site a new Web form named DisplayAlbum.aspx. Drag and drop a SQL Data Source control and configure it to select all the records from the Photos table matching the albumid query string parameter. To set the WHERE condition to the query, click the WHERE button of the Configure Data Source Wizard (again, see Figure 1) to open a dialog box, as shown in Figure 5.

 


Figure 5: Adding a WHERE clause in the SQL Data Source control.

 

Select AlbumID in the Column dropdownlist, = in the Operator dropdownlist, and QueryString in the Source dropdownlist. Specify QueryString field as albumid and click the Add button. This configures the SQL Data Source control.

 

Now drag and drop a DataList control on the Web form and set its Data Source to SqlDataSource1. Set the RepeatColumns property to 2 and the RepeatDirection property to Horizontal. Set the DataKeyField property to PhotoID. Next, design the DataList as shown in Figure 6.

 

 DataKeyField="PhotoID" DataSourceID="SqlDataSource1"

 OnItemDataBound="DataList1_ItemDataBound"

 RepeatColumns="2" RepeatDirection="Horizontal"

 Width="100%">

 Font-Bold="True" Font-Size="Larger" NavigateUrl=

 '<%# Eval("PhotoID", "~/displayphoto.aspx?photoid={0}") %>'

 Text='<%# Eval("Name") %>'

Font-Names="Verdana">


Text='<%# Eval("Description") %>'

 Font-Names="Verdana" Font-Size="12px">


 Font-Italic="False" Font-Size="10px" Text="Added :"

 Font-Names="Verdana">

 Font-Italic="False" Font-Size="10px"

 Text='<%# Eval("DateCreated", "{0:g}")

 %>' Font-Names="Verdana">

Figure 6: Markup of DataList displaying photo thumbnails.

 

Here we display the name, description, and date of addition of the photos, along with the thumbnail image. The name of the photo is displayed as a hyperlink. The hyperlink points to DisplayPhoto.aspx and passes the photo ID as a query string parameter. As before, we need to get the thumbnail images from GetPhoto.aspx. Next, add an event handler for the ItemDataBound event of the DataList, as shown in Figure 7.

 

protected void DataList1_ItemDataBound(object sender,

 DataListItemEventArgs e)

{

Image img = (Image)e.Item.FindControl("Image1");

if (img != null)

img.ImageUrl = "~/getphoto.aspx?imgtype=thumbnail&photoid="

 + DataList1.DataKeys[e.Item.ItemIndex].ToString();

}

Figure 7: ItemDataBound event handler.

 

Note that this time we pass PhotoID as a query string parameter to GetPhoto.aspx. Now add a HyperLink at the top of the page and set its Text property to Back to album list. Point the hyperlink to Default.aspx by setting its NavigateUrl property to ~/Default.aspx. Finally, add the code shown in Figure 8 in the Page_Load event handler.

 

protected void Page_Load(object sender, EventArgs e)

{

int albumid = int.Parse(Request.QueryString["albumid"]);

SqlParameter[] p = new SqlParameter[1];

p[0] = new SqlParameter("@albumid", albumid);

bool ispublic=bool.Parse(SqlHelper.ExecuteScalar("select

 ispublic from albums where albumid=@albumid",p).ToString());

if (!ispublic)

{

if (!User.Identity.IsAuthenticated)

{

Response.Redirect("~/login.aspx");

}

}

}

Figure 8: Page_Load event handler of DisplayAlbum.aspx.

 

Here we parse the query string parameter albumid and store it in an integer variable. We then fire a query to check whether the album is public. We do this by retrieving the IsPublic column for that album. If the album is marked as private, we further check whether the current user is authenticated by using the User.Identity.IsAuthenticated property. If the user is not authenticated, we redirect him to the login page. Figure 9 shows a sample run of DisplayAlbum.aspx.

 


Figure 9: Sample run of DisplayAlbum.aspx.

 

Displaying a Photo

When the user clicks on a photo title, we navigate to DisplayPhoto.aspx, along with a photo ID in the query string. We then display the complete photo image of the selected photo.

 

Start by adding a new Web form named DisplayPhoto.aspx. Drag and drop a SQL Data Source control and configure it to select the required photo from the Photos table. Be sure to add the WHERE condition, as shown in Figure 10.

 


Figure 10: Selecting a photo by adding a WHERE condition.

 

We select the record whose PhotoID column matches the photoid query string parameter. Drag and drop a FormView control on the Web form and set its Data Source to SqlDataSource1. Also, set the DataKeyNames property to PhotoID. The complete markup of FormView is shown in Figure 11.

 

 DataKeyNames="PhotoID" DataSourceID="SqlDataSource1"

 OnDataBound="FormView1_DataBound"

 OnItemCreated="FormView1_ItemCreated" Width="100%">

Font-Bold="True" Text='<%# Eval("Name")

 %>' Font-Names="Verdana"

 Font-Size="12px">

 Text='<%# Eval("Description") %>'

 Font-Names="Verdana"

 Font-Size="12px">

Font-Names="Verdana" Font-Size="12px">

Text='<%# Eval("DateCreated", "{0:g}") %>'

Font-Names="Verdana" Font-Size="12px">

Figure 11: Markup of FormView.

 

Here we have Label controls bound to the Name, Description, and DateCreated columns, respectively. To display the image we handle the ItemCreated event of the FormView, as shown in Figure 12.

 

protected void FormView1_ItemCreated(object sender,

 EventArgs e)

{

Image img = (Image)FormView1.FindControl("Image1");

if (img != null)

img.ImageUrl = "~/getphoto.aspx?imgtype=full&photoid="

 + FormView1.DataKey[0];

}

Figure 12: ItemCreated event handler of FormView.

 

As usual, we point the ImageUrl property of the Image control to GetPhoto.aspx. There is one difference, however. We pass the imgtype query string parameter as full, thus indicating that we want to display the full-size image and not the thumbnail. Drag and drop a HyperLink control on the Web form and set its Text property to Back to the album. Finally, add the Page_Load event handler shown in Figure 13.

 

protected void Page_Load(object sender, EventArgs e)

{

if (!IsPostBack)

{

SqlParameter[] p = new SqlParameter[1];

p[0] = new SqlParameter("@photoid",

 Request.QueryString["photoid"]);

int albumid=(int)SqlHelper.ExecuteScalar("select albumid

 from photos where photoid=@photoid",p);

SqlParameter[] p1 = new SqlParameter[1];

p1[0] = new SqlParameter("@albumid", albumid);

bool ispublic = bool.Parse(SqlHelper.ExecuteScalar("select

 ispublic from albums where albumid=@albumid",

 p1).ToString());

if (!ispublic)

{

if (!User.Identity.IsAuthenticated)

{

Response.Redirect("~/login.aspx");

}

}

HyperLink1.NavigateUrl = "~/displayalbum.aspx?albumid="

 + albumid.ToString();

}

}

Figure 13: Page_Load of DisplayPhoto.aspx.

 

Recollect that we added some code in DisplayAlbum.aspx that checks whether the album being accessed is private or public and redirects the user to the login page if needed. A similar check is also needed in DisplayPhoto.aspx because there is always a possibility that the user directly navigates to the photo URL. So, we put the same check in the Page_Load event of DisplayPhoto.aspx. We also set the NavigateUrl property of the Back to the album HyperLink to DisplayAlbum.aspx, passing the required albumid query string parameter. Figure 14 shows how DisplayPhoto.aspx looks in the browser.

 


Figure 14: DisplayPhoto.aspx in run mode.

 

Displaying Images in DataList and FormView

Until now we displayed thumbnails and images in our application and we always pointed the ImageUrl property of Image control to the GetPhoto.aspx page. Now we ll develop the GetPhoto.aspx page. Add to the Web site a new Web form named GetPhoto.aspx and write in its Page_Load event handler the code shown in Figure 15.

 

protected void Page_Load(object sender, EventArgs e)

{

Image photo = null;

if (Request.QueryString["imgtype"] == "thumbnail")

{

if (Request.QueryString["photoid"] != null)

{

int photoid = int.Parse(Request.QueryString["photoid"]);

photo = PhotoHelper.GetThumbnail(photoid);

}

if (Request.QueryString["albumid"] != null)

{

int albumid= int.Parse(Request.QueryString["albumid"]);

photo = PhotoHelper.GetThumbnailForAlbum(albumid);

}

}

else

{

int photoid = int.Parse(Request.QueryString["photoid"]);

photo = PhotoHelper.GetPhoto(photoid);

}

photo.Save(Response.OutputStream, ImageFormat.Gif);

}

Figure 15: Page_Load event handler of GetPhoto.aspx.

 

We use two types of images, thumbnails and full images. The type of image is passed via the imgtype query string parameter. The outermost if condition checks the imgtype parameter. If the image type requested is a thumbnail, we further check if the thumbnail of a specific photo is needed or the thumbnail for an album is needed. We determine this by checking the photoid and albumid query string parameters. The presence of the photoid parameter in the query string indicates that we want to display a thumbnail for a specific photo. Similarly, the presence of the albumid parameter indicates that we want a thumbnail for an album. If the thumbnail of a specific photo is required, we call the GetThumbnail method of the PhotoHelper class (see Figures 10-13 in Part I). On the other hand, if we need to display the thumbnail for an album, we call the GetThumbnailForAlbum method of the PhotoHelper class. If the image type is not a thumbnail, we call the GetPhoto method of the PhotoHelper class and retrieve the full-size photo. The return value of GetThumbnail, GetThumbnailForAlbum, and GetPhoto is an instance of the Image class. The Image class has a method named Save that accepts the stream to which the image is to be saved, as well as the image format (BMP, GIF, JPEG, etc.). We call the Save method of the Image class by passing the Response.OutputStream and image format as ImageFormat.Gif (ImageFormat is a class defined in the System.Drawing.Imaging namespace). This way the outputted image is displayed in the Image control.

 

Security

Some of the albums might be marked as private. These albums, along with the pages from the Admin folder, are to be protected from unauthorized access. We use Forms-based authentication, along with role-based security, to protect these pages. Open the web.config file and add the markup shown in Figure 16.

 

Figure 16: Enabling Forms-based security.

 

We set the mode attribute of the tag to Forms. Because public albums can be accessed by anyone, we set the users attribute of the tag to * .

 

We need to protect Web forms in the Admin folder from anonymous users. To enable this behavior, add after the end of section but before the end of the root node the markup shown in Figure 17.

 

   

     

       

     

   

 

Figure 17: Protecting the Admin folder.

 

We use a tag to apply settings to the Admin folder. We deny access to anonymous users by setting the user s attribute of the tag to ? . This will ensure that only authenticated users can access the pages from the Admin folder.

 

Not all the authenticated users are administrators. We must identify a user that is acting as an administrator. We do this by implementing role-based security. Select ASP.NET Configuration from the WebSite menu of VS.NET 2005. This will open the Web Site Administration Tool. Using the tool, add a role named ADMIN (see Figure 18).

 


Figure 18: Adding roles to your Web site.

 

Note that in the absence of any specific membership and roles provider, ASP.NET will maintain all the membership and roles details in a SQL Server 2005 database named ASPNETDB.mdf. This database automatically gets created in the App_Data folder of your Web site. Recollect that in the Page_Load of AdminMasterPage.master we have put a check to ensure that only the users belonging to the ADMIN role can access the administrative Web pages.

 

Now, add in the Web site a Web form named Login.aspx. Drag and drop on the Web form a Login and CreateUserWizard control. Figure 19 shows a sample run of this Web form.

 


Figure 19: Sample run of Login.aspx.

 

Register as a new user and through the Web Site Administration Tool associate the newly registered User ID with the ADMIN role.

 

That s it! Our photo album is ready to share photos with family members and friends.

 

Conclusion

Storing and retrieving images in a SQL Server database is quiet easy in .NET. However, ASP.NET 2.0 data bound controls don t have a built-in way to display Image data types. With some tweaks you can overcome this limitation. Applications like a photo gallery require dealing with thumbnails of images. Traditionally, developers maintained two separate images full size and thumbnail making it difficult to manage the application. Using GDI+ classes you can emit thumbnails on the fly, thus making life easier for developers.

 

The sample code for this series is available for download.

 

Bipin Joshi is the founder and owner of BinaryIntellect Consulting (http://www.binaryintellect.com), where he conducts professional training programs on .NET technologies. He is the author of Developer s Guide to ASP.NET 2.0 (http://www.binaryintellect.com/books) and co-author of three WROX books on .NET 1.x. He writes regularly for http://www.DotNetBips.com, a community Web site he founded in the early days of .NET. He is a Microsoft MVP, MCAD, MCT, and member of ASPInsiders. He jots down his thoughts about .NET, life, and Yoga at http://www.bipinjoshi.com. He also conducts workshops on Yoga and Meditation, where he helps IT professionals develop a positive personality. You can contact him at mailto:[email protected].

 

Enhance the App Even More

Here are some suggestions for further enhancing the photo gallery application:

  • You can use Microsoft Data Access Application Block (MSDAAB) or BinaryIntellect DatabaseHelper open source component as a data access layer.
  • You can build in the ability to detect image types (GIF/JPEG).
  • You can extend the security system to include moderated albums. Moderated albums can be seen only by people you explicitly authorize and not by all authenticated users.
  • You can add a Tell a friend feature.
  • You can also add an Invite people feature.

 

 

 

Hide comments

Comments

  • Allowed HTML tags: <em> <strong> <blockquote> <br> <p>

Plain text

  • No HTML tags allowed.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Lines and paragraphs break automatically.
Publish