When building ASP.NET pages, you write the vast majority of your dation code in the user interface layer instead of your business logic layer where your vali-dation code properly belongs
Trang 1from the ObjectDataSource control and provides default values for several
ObjectDataSource control properties
For example, you could swap the ObjectDataSource control in Listing 20.33 with the
follow-ing EntityDataSource control:
<custom:EntityDataSource
id=”srcMovies”
TypeName=”Movie”
EnablePaging=”true”
SortParameterName=”orderBy”
Runat=”Server” />
Why use the EntityDataSource control? Less typing I don’t want to program all day; I
want to see a movie
Performing Validation with the EntityBase Class
One complaint I’ve always had about ASP.NET Framework is that validation happens at
the wrong place When building ASP.NET pages, you write the vast majority of your
dation code in the user interface layer instead of your business logic layer where your
vali-dation code properly belongs
Performing validation in your user interface layer is bad for two main reasons First, it
means that if you switch user interfaces for your application, you must rewrite all your
validation logic For example, you might want to create a cool Silverlight interface for
your application In that case, you have to write all your validation logic again from
scratch Validation logic should be user interface-independent
Also, placing your validation logic in your user interface layer means that you have to
rewrite the exact same validation logic on each page that you use an entity This is an
extraordinary time waster I want to write my validation logic for an entity once and use
the same logic everywhere
The EntityBase class includes a Validate() method that you can use to incorporate
validation logic into your entities (and thus, your business logic layer) Listing 20.34
illustrates how you can write the Movie class so that it validates the Title, Director, and
DateReleased properties
LISTING 20.34 ShowEntityBase\App_Code\Movie.cs
using System;
public partial class Movie : EntityBase<Movie>
{
Trang 2protected override void Validate()
{
// Title is required
if (!ValidationUtility.SatisfiesRequired(Title))
ValidationErrors.Add(“Title”, “Required”);
// Director is required
if (!ValidationUtility.SatisfiesRequired(Director))
ValidationErrors.Add(“Director”, “Required”);
// DateReleased is required
if (DateReleased == DateTime.MinValue)
ValidationErrors.Add(“DateReleased”, “Required”);
// DateReleased can’t be more than 10 years ago
if ((DateTime.Now.Year - DateReleased.Year) > 10)
ValidationErrors.AddIfNotAlready(“DateReleased”, “Movie too old”);
}
}
The Validate() method validates the properties of the Movie entity The method takes
advantage of the ValidationUtility class The ValidationUtility class contains a set of
methods to make it easier to perform standard types of validation:
SatisfiesRequired()—Enables you to check whether an expression has a value
SatisfiesType()—Enables you to validate against a regular expression defined in
the Web.config file
SatisfiesExpression()—Enables you to validate against a regular expression
IsInRole()—Enables you to check whether the current user is in a particular role
IsUserName()—Enables you to check whether the current user has a particular
username
ShowValidationErrors()—Displays validation errors on a page
The ASP.NET page in Listing 20.35 demonstrates how you take advantage of entity
valida-tion when inserting new movie records into the database (see Figure 20.3)
Trang 3LISTING 20.35 ShowEntityBase\InsertMovie.aspx
<%@ Page Language=”C#” Trace=”true” %>
<%@ Register TagPrefix=”custom” Namespace=”Superexpert.Controls” %>
<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN”
“http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”>
<script runat=”server”>
protected void frmMovie_ItemInserted
(
object sender,
FormViewInsertedEventArgs e
)
{
if (e.Exception != null)
{
e.ExceptionHandled = true;
e.KeepInInsertMode = true;
ValidationUtility.ShowValidationErrors(this, e.Exception);
}
}
</script>
FIGURE 20.3 Performing entity validation
Trang 4<html xmlns=”http://www.w3.org/1999/xhtml”>
<head id=”Head1” runat=”server”>
<title>Insert Movie</title>
</head>
<body>
<form id=”form1” runat=”server”>
<div>
<asp:FormView
id=”frmMovie”
DataSourceID=”srcMovies”
DefaultMode=”Insert”
OnItemInserted=”frmMovie_ItemInserted”
Runat=”Server”>
<InsertItemTemplate>
<asp:Label
id=”lblTitle”
Text=”Title:”
AssociatedControlID=”txtTitle”
Runat=”server” />
<br />
<asp:TextBox
id=”txtTitle”
Text=’<%# Bind(“Title”) %>’
Runat=”server” />
<custom:EntityCallOutValidator
id=”valTitle”
PropertyName=”Title”
Runat=”Server” />
<br /><br />
<asp:Label
id=”lblCategory”
Text=”Category:”
AssociatedControlID=”ddlCategory”
Runat=”server” />
<br />
<asp:DropDownList
id=”ddlCategory”
DataSourceId=”srcMovieCategories”
SelectedValue=’<%# Bind(“CategoryId”) %>’
DataTextField=”Name”
DataValueField=”Id”
Runat=”server” />
<asp:ObjectDataSource
id=”srcMovieCategories”
Trang 5TypeName=”MovieCategory”
SelectMethod=”Select”
Runat=”Server” />
<br /><br / >
<asp:Label
id=”lblDirector”
Text=”Director:”
AssociatedControlID=”txtDirector”
Runat=”server” />
<br />
<asp:TextBox
id=”txtDirector”
Text=’<%# Bind(“Director”) %>’
Runat=”server” />
<custom:EntityCallOutValidator
id=”valDirector”
PropertyName=”Director”
Runat=”Server” />
<br /><br />
<asp:Label
id=”lblDescription”
Text=”Description:”
AssociatedControlID=”txtDescription”
Runat=”server” />
<br />
<asp:TextBox
id=”txtDescription”
Text=’<%# Bind(“Description”) %>’
TextMode=”MultiLine”
Columns=”60”
Rows=”3”
Runat=”server” />
<br /><br />
<asp:Label
id=”lblDateReleased”
Text=”Date Released:”
AssociatedControlID=”txtDateReleased”
Runat=”server” />
<br />
<asp:TextBox
id=”txtDateReleased”
Trang 6Text=’<%# Bind(“DateReleased”) %>’
Runat=”server” />
<custom:EntityCallOutValidator
id=”valDateReleased”
PropertyName=”DateReleased”
ControlToValidate=”txtDateReleased”
TypeName=”date”
Runat=”Server” />
<br /><br />
<asp:Button
id=”btnInsert”
Text=”Insert”
CommandName=”Insert”
Runat=”server” />
</InsertItemTemplate>
</asp:FormView>
<hr />
<asp:GridView
id=”grdMovies”
DataSourceID=”srcMovies”
Runat=”server” />
<custom:EntityDataSource
id=”srcMovies”
TypeName=”Movie”
Runat=”server” />
</div>
</form>
</body>
</html>
You should notice several things about the page in Listing 20.35 First, the page includes a
method for handling the FormView control’s ItemInserted event This handler checks for
an exception If Movie.Validate() creates one or more validation errors, the Movie entity
throws a ValidationException when inserting or updating automatically
If there is an exception, the exception is passed to the
ValidationUtility.ShowValidationErrors() method The ShowValidationErrors()
method finds the EntityCallOutValidator that corresponds to each validation error and
displays the correct error message
Trang 7The Validate() method executes only if a Movie entity can be created If someone enters
the wrong type of value into a field, the ObjectDataSource can’t even create the entity
and the Validate() method never executes The EntityCallOutValidator associated with
the DateReleased property includes ControlToValidate and TypeName properties This
validation control checks whether the value entered into the DateReleased TextBox is a
valid date even before the Movie entity is created
Summary
We covered a lot of material over the course of this chapter In the first part, we discussed
all the features of C# and VB.NET used to support LINQ, such as anonymous types,
exten-sion methods, and lambda expresexten-sions
Next, we discussed LINQ to SQL entities You learned how to build entities that represent
your database objects both by hand and by using the LINQ to SQL Designer We also
briefly examined the LinqDataSource control
In the following part, we discussed how you can perform basic database operations with
LINQ to SQL For example, you learned how to select records, page through records, and
cache records You also learned how to insert, update, and delete database records with
LINQ to SQL
In the final part of this chapter, you learned how to build a custom LINQ to SQL base
class You learned how to use this class to support selecting, inserting, deleting, and
updat-ing entities without writupdat-ing any code You also learned how to add validation logic to
your entities
Trang 8Data Access with WCF
Data Services
Overview of WCF Data Services Using Data Services with a Service Reference
Using Data Services with a Data Context
Summary
Throughout this section of the book, we covered a wide
variety of ways to get data to and from your web forms In
a standard n-tier model, the web application would talk to
a middle tier containing business logic, which would in
turn talk to a data tier responsible for communicating with
the database
Although this is a perfectly adequate model, to handle the
scalability and performance demands of modern distributed
applications, we need something a bit more flexible In
large organizations we might have dozens of services
exposed by multiple departments and multiple web
applica-tions that need to consume those services In this case, we
can’t just add a reference to the Business Logic Layer (BLL)
and start invoking methods
This chapter shows you how to use WCF Data Services to
facilitate high-performance, scalable, distributed
applica-tions by exposing entity models as RESTful web services
that can be reused by many applications on many
plat-forms We provide an overview of the WCF Data Services
technology and provide samples of some of the ways your
ASP.NET application can consume these services
Overview of WCF Data Services
When you see data access samples, most of them illustrate
making a direct database connection from the web server
(even if it’s from a data tier) to the database Although this
is fine for illustrative purposes, it’s not that practical In
many production environments, firewalls and other
secu-rity systems prevent direct database connections of any
Trang 9kind As previously mentioned, in many service-oriented, distributed systems, client code
must go through a service to read or write any data
In the past, developers had to manually create their own service-based facades in front of
the database, generally creating headaches and extra work WCF Data Services aims to
solve some of these problems A WCF Data Service is a standardized service that exposes
underlying relational data as a RESTful Web Service This means that there’s no WSDL, no
ASMX, just a convention for building URL-based queries and using the AtomPub or JSON
protocols for sending data over the wire
It is beyond the scope of this book to go into too much detail on how to build WCF Data
Services or create the underlying Entity Models exposed by WCF Data Services For more
information on these services, read the MSDN documentation at
http://msdn.microsoft.com/en-us/data/bb931106.aspx
The following two sections show you how to allow your ASP.NET application to
commu-nicate with a WCF Data Service, either by using a Service Reference or by using the
client-side DataServiceContext class directly
Using Data Services with a Service Reference
If you’ve used Visual Studio for any length of time, you’re probably familiar with the
ability to add service references to existing projects These either discover services in the
current solution, or you can enter the URL of a WCF service and the service reference
creates a client-side proxy for you Up until now, this has worked only for regular web
services
With Visual Studio 2010 and WCF Data Services, you can add a Service Reference to a
WCF Data Service This Service Reference can create a special client proxy for you, one that
exposes all the entities for the service and handles all the change tracking and other heavy
lifting that, as a service consumer, you just don’t want to have to deal with manually
Figure 21.1 shows the screen you see when attempting to add a service reference to a WCF
Data Service Each of the entities exposed by the data service appear as properties on the
client proxy generated
To illustrate how we might consume a WCF Data Service from an ASP.NET application,
let’s use an example that is a little bit more fun than the typical “Hello World” sample
Let’s say that you work for a fabulously successful video game company and your most
popular game, Zombie Killa, has an incredible multiplayer mode You’ve been asked to
make the kill list and scores available on the web The team that keeps that information
won’t let you access its database directly for many (very good) reasons Instead, it set up a
WCF Data Service that exposes some of the key entities that you need to create your high
scores website
Trang 10ptg FIGURE 21.1 Adding a service reference to a WCF Data Service
The first thing to do is add a service reference to its service, which you can see in Figure
21.1 This creates a client-side proxy that enables your code to treat the entities like
regular LINQ data sources Your LINQ queries convert into the WCF Data Services URL
syntax, and the data coming back from the service converts into instances of the classes
generated when you added the service reference
Now that you have your service reference, you’re ready to access the data service For this
sample, we’ve been asked to create a My Kills page that shows all the zombies a particular
player has killed and the weapons she used
We created a MyKills.aspx page and then added the code from Listing 21.1 to the
Page_Load() method In addition to enabling us to write LINQ queries against specific
entities, we can also invoke custom methods made available on the service The game
team didn’t want us to try to create the My Kills filter on our own because it might
change over time, so it provided a method on the service called “GetMyKills” that we can
execute The amazing thing is that the result of this custom method execution is still
queryable, enabling us to further filter, page, and sort the results
LISTING 21.1 Page_Load for MyKills.aspx.cs
protected void Page_Load(object sender, EventArgs e)
{
ZombieKillaService.ZombieKillaContainer svc =
new ZombieKillaService.ZombieKillaContainer(
new Uri(“http://localhost:5000/ZombieKilla.svc”));
var q = from Kill kill in svc.CreateQuery<Kill>(“GetMyKills”)