Completing a Simple Storefront with LINQ

In the last article, we created the storefront's home page, which displayed the three latest products. To do this, we used LINQ in the code-behind file, manually databinding a ListView with the results. We also started to create the Product.aspx page, which displays more detailed information about a given product. In this article, we'll finish the storefront by completing the Product.aspx page and creating the Browse.aspx page, which will allow the user to browse products by category.

Contributed by
Rating: 4 stars4 stars4 stars4 stars4 stars / 6
May 13, 2008
Rate this Article:
MEH MEH++


SEARCH ASP FREE
TOOLS YOU CAN USE

advertisement

In the first article of this series, we laid out the plans for a very simple storefront for the Adventure Works Cycles sample database that would demonstrate the use of LINQ in ASP.NET Websites. We created a master page for the entire site and put together a stylesheet for the site. We also examined the relevant tables in the database, and we created a page that would display a product's image, given the product's ProductID.

Creating the Product View Page

With the database setup, we can now begin creating the product view page, Product.aspx. This page should accept a ProductID in the query string and then display information about that product, including the product's description, which we set up our Website to handle in the last article.

Additionally, it would be wise to make sure that the ProductID is set in the query string, and that the given ProductID matches an entry in the database. This is similar to what we did with ProductPicture.aspx, except now we can display an error message rather than just have the page output nothing. This can be handled through a MultiView control. Inside the MultiView, one View can be a simple error message, alerting the user that the ProductID is invalid. The other View, then, can display the chosen product's information.

Markup


Here's how the markup for this works:


<%@ Page Language="C#" MasterPageFile="~/MasterPage.master"
 AutoEventWireup="true" 
CodeFile="Product.aspx.cs" Inherits="Product" Title="View Product" %>


<asp:Content ID="Content1" ContentPlaceHolderID="content" 
Runat="Server">


<asp:MultiView ID="ProductMultiView" runat="server">


<asp:View ID="InvalidProductView" runat="server">

Invalid product! Please go back and try again.

</asp:View>


<asp:View ID="ValidProductView" runat="server">

<div class="itemBoxLarge">

 <asp:Image ID="ProductImage" CssClass="productImage" 
runat="server" />

 <strong><asp:Label ID="NameLabel" runat="server" /></strong>

 <br />

 Category: <asp:Label ID="CategoryLabel" runat="server" /><br />

 List Price: <asp:Label ID="PriceLabel" runat="server" /><br />

 Color: <asp:Label ID="ColorLabel" runat="server" /><br />

 <p><asp:Label ID="DescriptionLabel" runat="server" /></p>

</div>

</asp:View>


</asp:MultiView>


</asp:Content>


As you can see above, we've used an Image control to display the product's image, and we've used Label controls to display textual information about the product. We display the name of the product, the category that the product is under, the list price of the product, the color of the product, and a description of the product. However, feel free to add more fields.

Now we need to write the code to populate the page with data. First, we need to check whether the ProductID is set in the query string. If it's not, we need to set the active View to InvalidProductView and stop. If it is, we need to query the database. Then, we need to check to see if the query returns anything. If it doesn't return anything, then the ProductID is invalid. If it does return something, then we need to set the active View to ValidProductView and then set the Image control's ImageUrl property and the Label controls' Text properties.

Here's how it's all done. Place the following code in the Page_Load method:


ProductMultiView.SetActiveView(InvalidProductView);

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

{

 AdventureWorksDataContext db = new AdventureWorksDataContext();

 var product = (from p in db.Products

 where p.ProductID == int.Parse(Request.QueryString["id"])

 select new

{

ProductID = p.ProductID,

Name = p.Name,

Category = p.ProductCategory.Name,

ListPrice = p.ListPrice,

Color = p.Color,

Description =
p.ProductModel.ProductModelProductDescription.ProductDescription.
Description

}).FirstOrDefault();

 if (product != null)

{

ProductMultiView.SetActiveView(ValidProductView);

 Page.Title = "View Product: " + product.Name;

 ProductImage.ImageUrl = "ProductPicture.aspx?id=" + product.ProductID.ToString();

NameLabel.Text = product.Name;

CategoryLabel.Text = product.Category;

 PriceLabel.Text = String.Format("{0:C}", product.ListPrice);

ColorLabel.Text = product.Color;

DescriptionLabel.Text = product.Description;

}

}


Notice how we set ProductMultiView's active View to InvalidProductView to start. Then, if and only if the ProductID is valid, we switch to ValidProductView. Also notice how we change the title of the page to include the product's name, and how we create an anonymous type to store product information.

The Product.aspx page is now complete. Running it with no query string should generate an error, but clicking on an entry in the list of latest products in Default.aspx should return information about that product.

Building the Product Browse Page

It's finally time to build the product browse page. Add a page called Browse.aspx. As before, be sure to select MasterPage.master as the master page.

The plan is to create two ListBox controls and a ListView control. The first ListBox control will contain the top-level categories. When the user selects a top-level category (for example, Bikes), the second ListBox control will become populated with the appropriate subcategory (for example, Mountain Bikes). Then, when the user selects a subcategory, the ListView will become populated with products in that category.

We'll start with the the top-level category ListBox, but we need a way to populate it. We could work in the code-behind file as we did before, but there is an easier solution here: LinqDataSource. We can drop it right onto the page and set the appropriate properties declaratively. To get the top-level categories, we simply need to get all the categories that have a null ParentProductCategoryID, which makes sense, since they are themselves parent categories. Querying with a LinqDataSource isn't hard at all. Place this into the Browse.aspx page (inside of the Content control, of course):


<asp:LinqDataSource ID="CategorySource" 
ContextTypeName="AdventureWorksDataContext"

 TableName="ProductCategories" Where="ParentProductCategoryID = null" runat="server">

</asp:LinqDataSource>


As you can see, it's not hard at all to use LinqDataSource. We simply specify the name of the data context, the name of the table, and the condition of the Where clause. Hooking this up to a ListBox control isn't difficult either:


<asp:ListBox ID="CategoryList" DataSourceID="CategorySource" 
DataTextField="Name"

 DataValueField="ProductCategoryID" AutoPostBack="true" 
runat="server">

</asp:ListBox>


Note how the control automatically posts back.

Now we need to create a second LinqDataSource and a second ListBox. The process is much the same as before, with one important difference: we need to get the value of CategoryList and work it into our query. We need to retrieve all of the ProductCategory entries whose ParentProductCategoryIDs match the value of CategoryList. LinqDataSource actually provides a neat way to do this: WhereParameters. We can automatically generate a Where clause based on, among other things, the value of a control. Here's how it's done:


<asp:LinqDataSource ID="SubcategorySource" 
ContextTypeName="AdventureWorksDataContext"

 TableName="ProductCategories" AutoGenerateWhereClause="true" 
runat="server">

 <WhereParameters>

 <asp:ControlParameter ControlID="CategoryList" 
Name="ParentProductCategoryID"

 DefaultValue="-1" Type="Int32" />

 </WhereParameters>

</asp:LinqDataSource>


Notice how we have DefaultValue set to -1. This way, if nothing is selected in CategoryList, nothing will be in the second ListBox. Also, take note of how AutoGenerateWhereClause is set to true. This is necessary! Otherwise, all WhereParameters will be ignored.

Now we need to wire SubcategorySource. This works the same way as before:


<asp:ListBox ID="SubcategoryList" 
DataSourceID="SubcategorySource"

 DataTextField="Name" DataValueField="ProductCategoryID"

 AutoPostBack="true" runat="server">

</asp:ListBox>


Try the page out now. Selecting a top-level category should populate the second ListBox with the appropriate subcategories.

Building the Product Browse Page, Continued

To finish everything, we just need to create a ListView control that lists the products in the selected category. This ListView will need to have its own LinqDataSource, which is created much the same way as the last one. Again, we need to automatically generate the Where clause based on the value of a control-this time, SubcategoryList:


<asp:LinqDataSource ID="ProductSource" 
ContextTypeName="AdventureWorksDataContext"

 TableName="Products" AutoGenerateWhereClause="true" 
runat="server">

 <WhereParameters>

 <asp:ControlParameter ControlID="SubcategoryList" 
Name="ProductCategoryID"

 DefaultValue="-1" Type="Int32" />

 </WhereParameters>

</asp:LinqDataSource>


Now we just need to create the ListView. This is created in the same way that we created the ListView on the main page:


<asp:ListView ID="ProductList" DataSourceID="ProductSource" 
runat="server">

 <LayoutTemplate>

 <asp:PlaceHolder ID="itemPlaceholder" runat="server" />

 </LayoutTemplate>

 <ItemTemplate>

 <div class="itemBoxSmall">

 <img src="ProductPicture.aspx?id=<%#Eval("ProductID") %>"

 class="productImage" alt=<%#Eval("Name") %> />

 <strong><%#Eval("Name") %></strong>

 <br />

 Product Number: <%#Eval("ProductNumber") %><br />

 List Price: <%#Eval("ListPrice", "{0:C}") %>

 </div>

 </ItemTemplate>

</asp:ListView>


Go ahead and try the page. Select a top-level category and then a subcategory. The subcategory's products should then appear. However, you'll probably notice something right away, especially if you pick a large category: the data isn't paged. Thankfully, this is quite easy to fix. We simply need to add a DataPager control, which, given a control, a page size, and a method of formatting, will automatically page the data:


<asp:DataPager ID="ProductPager" PagedControlID="ProductList" 
PageSize="10" 
runat="server">

 <Fields>

 <asp:NumericPagerField />

 </Fields>

</asp:DataPager>


That's it!

Conclusion

If you've followed this walk through from start to finish, you should be comfortable using LINQ in ASP.Net Websites. We've created a basic storefront that takes advantage of the capabilities provided by LINQ using various methods. Of course, the Website we've created is very primitive, and LINQ has a lot more to offer.

From here, try to expand the storefront on your own. For example, here, we browse individual products. However, it may be more logical to browse by models. Then, when a user selects a model, he could be confronted with DropDownList controls asking for the desired color and size. You could even rework the Website to use the full Adventure Works Cycles database, rather than the light version, or you could add administrative features. Go ahead and try.

blog comments powered by Disqus
.NET ARTICLES

- .Net 4.5 Brings Changes
- Understanding Events in VB.NET
- Objects, Properties, Events and Methods in V...
- Install Visual Web Developer Express 2010
- Microsoft Gadgeteer an Open Source Alternati...
- Best DotNetNuke Modules
- Facebook Image Viewer in Visual Basic
- Murach`s ADO.NET 4 Database Programming with...
- 5 Must Have Visual Studio 2010 Extensions
- Dynamic Web Applications with ASP.NET Mono u...
- PDFSharp: HTML to PDF in ASP.NET 3.5 using V...
- Using the PDFSharp Library in ASP.NET 3.5 wi...
- Sending Email in ASP.NET 3.5 using VB.NET wi...
- ASP.NET 3.5 Role Based Security and User Aut...
- Creating ASP.NET Login Web Pages and Basic C...

ASP Web Hosting ASP.Net Web Hosting Windows Web Hosting
 
 
 

ASP Free Forums 
 RSS  Tutorials RSS
 RSS  Forums RSS
 RSS  All Feeds
Site Map 
Request Media Kit
Write For Us Get Paid 
Weekly Newsletter
 
Developer Updates  
Free Website Content 
Privacy Policy 
Support 


© 2003-2012 by Developer Shed. All rights reserved. DS Cluster 2 - Follow our Sitemap
Most Popular Topics
All ASP.Net Tutorials