Вы находитесь на странице: 1из 49

Reviewed: DXperience & ADO.NET 3.

5 Cookbook

www.aspnetPRO.com

October 2008
Volume 7 Number 10 Solutions for Building Enterprise Web Applications
��������������������������������
����������������������������
�������������������������������
����������������������������������������������������������������������������������������
����������������������������������������

���������������������������������
�����������������������������������������������������������������������������
�������������������������������� ���������������������������������������������������
����������� ���������

�������������� �������������
���������������������������������������������������������������������������������������������
��������������������

�����������������������������
�����������������������������������������������������������������������������������
����������������������������������������

������������������������������
��������������������������������������������������������������������������������������
������� ���������������� �����������������������������������������������������������������
����������������

������������������������

����� ����������������������������� ������������������ ������������


������������������������� ��������������������

���������������������������������������������������������������������
�������������������������������������������������������������������������������������������������������������������������������
����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� ���� �������������������������������������������������������������������������������������������������������������������������������������������������������������������������
In This Issue
October 2008 | Volume 7 Number 10

Columns
�������������������������������������������

14 CoreCoder: Authentication and AJAX


�����������������

���������������
Upgrading your software doesn’t always entail a learning curve: Getting
��������������������������������������������������
credentials and sharing tokens in AJAX is much the same as in classic
������������������

ASP.NET, as Dino Esposito explains.

19 ControlFreak: Process Payments Promptly


Many Web development tasks are much easier to implement than they used to
be. But one that remains relatively laborious is payment processing. Steve C. Orr
provides two free ASP.NET Web controls to easily add e-commerce capabilities to
your Web site.

26 Exploring WCF Web Services: Workflow Services


Michele Leroux Bustamante introduces Workflow Services, then explores
how to expose workflows as WCF services, and how to consume WCF services
from workflows using features introduced with .NET Framework 3.5.

Cover Design by Diana Nishimura


48 BackDraft: Spreading the Word
Microsoft’s dynamic new cross-platform Web development and video stream-
ing technology, Silverlight, stands to play an important role in the future of Web
development. That is, if it catches on. Jonathan Goodyear explains.

Cover Stor y
Feature
8 Custom Criteria
One of the most time-consuming
tasks involved in building any 36 Convention Over Configuration: Part II
Emad Ibrahim wraps up his two-part series on how to create applications
application is the customization using ASP.NET MVC, jQuery, and AJAX.
of the different criteria pages
for the reports. In this article,
Carl Ganz, Jr. illustrates how to Reviews
centralize your reporting criteria
interface into one page and 44 CloserLook: DXperience Universal
DXperience includes components for developing Windows and ASP.NET appli-
cations. Focusing on the components designed for ASP.NET, Anand Naraya-
dynamically create report criteria
pages at run time using defini- naswamy reviews the first build of the 2008 series.
tions stored in a table.

46 BookReport: ADO.NET 3.5 Cookbook


Solving one problem in the middle of a project can often be worth the price of
a book. Find out if Dennis Hayes thinks this is one of those books.

Departments
6 Crossword Puzzle
by Ravi Nangunoori

47 Advertising Index
asp.netPRO Online
Here’s just some of the content that’s available only online at www.aspnetpro.com.
• “Dynamic Data with the Entity Framework in Medium Trust.” Don Kiely provides
workarounds for using Dynamic Data with the Entity Framework in medium trust.
• “Creating XBAP Poppers.” Alvin Bruney shows us how to create XBAP Poppers.
• You’ll also find additional book and product reviews, product announcements, and
more — and only available at www.aspnetpro.com.

2 October 2008 | www.aspnetPRO.com


ASP.NET Crossword Puzzle
§ By Ravi Nangunoori
22. You must use these files to support multiple
1
languages in a Web application.
23. The Document Object Model used for code
2 3 generation in .NET.

4 5 DOWN
6 1. The keyword used in C# to call a member of
7
the current instance of a class.

8 9 10 3. This event ends when an end user leaves an


ASP.NET-based Web application or closes the
11 12
browser.
13 14
4. This page directive must be added to the top
of an .aspx page to cache the pages in a Web
15 16 application.
6. This utility is used to create UI, properties,
17 18 19 and events for creating custom controls.
9. A text message is displayed to an end user
20
if a control’s validation fails by setting this
property of the Validation control.
21
10. HttpHandlers are classes that implement this
22
interface.
23
12. This Namespace System.Web._____ must be
used to send messages from an application.
14. This provider is required to generate compil-
able code and keep this code in sync with a
source file.
Please see page 47 for answers to this puzzle. Copyright © www.dotnetvideos.net, www.visualsoftinc.com 16. These classes receive output from Debug and
Trace classes.

ACROSS 19. A property of the TextBox server control that


determines whether the text entered in it can
2. One must assign this property of an .aspx 14. These lines of code or conditions will always be displayed as a single line or multiline, or
page to change its Master Page at run time. cause an application to break in the debugger. as a password format.
5. To display a pop-up message box on the client 15. To avoid a first hit delay of a public site built
side in a Web application, one must set to True using ASP.NET, developers employ this process.
this property of the ValidationSummary control.
17. To uncover Web application-wide problems,
7. A current selection from a List server control one must set this flag to True in the web.config
can be received using this property. file before viewing the trace.axd page in the
browser.
8. One must use this control on a Web form to Ravi Nangunoori is a Principal at
group controls. 18. This represents a disconnected representa- www.visualsoftinc.com and specializes in
tion of data held in memory.
11. A cleaner and more stringent version of developing Web applications using .NET
HTML. 20. This Page___ event occurs as the last event technologies. He also runs a multimedia
in the life of the Page object. content site (www.dotnetvideos.net)
13. The URL property of this class must be set
after instantiating an object of this class in 21. This window allows one to monitor the values serving the Microsoft developer community
order to set the URL of a Web service at of all the variables of a procedure when a around the world. He can be reached at
run time. program is executing in Debug mode. ravi443@gmail.com.

EDITOR-IN-CHIEF SYSTEMS ADMINISTRATOR P R I N T E D BY S C H U M A N N DISTRIBUTION BY CURTIS


David Riggs .................................................driggs@informant.com Bob Silva PRINTERS, INC. CIRCULATION COMPANY
CONTRIBUTING EDITORS INFORMANT COMMUNICATIONS GROUP MANAGEMENT 701 South Main Street 730 River Road
Jonathan Goodyear and Mike Riley PUBLISHER Fall River, WI 53932 New Milford, NJ 07646
TECHNICAL EDITORS Mitchell Koulouris ................................ mkoulouris@informant.com Phone: 920.484.3348 Phone: 201.634.7400
Ken McNamee and Anand Narayanaswamy CHIEF FINANCIAL OFFICER Fax: 201.634.7497
CONTRIBUTING WRITERS Nancy Nomellini
Michele Leroux Bustamante, Dino Esposito, Carl Ganz, Jr., ADMINISTRATIVE ASSISTANT
Dennis Hayes, Emad Ibrahim, Ravi Nangunoori, and Steve C. Orr Rachel Morgan
ART DIRECTOR Customer Support....................... customerservice@informant.com 5105 Florin-Perkins Road
Diana Nishimura .................................. dnishimura@informant.com Phone .....................................................................916.379.0609 Sacramento, CA 95826-4817
NATIONAL SALES MANAGER Fax .........................................................................916.379.0610 Phone: 916.379.0609
Cathy Sanassarian ...................................... cathys@informant.com Fax: 916.379.0610
www.informant.com

6 October 2008 | www.aspnetPRO.com


C o v e r S t o r y
LANGUAGES: C# | VB.NET
§ By Carl Ganz, Jr.

Custom Criteria
Customize Data-driven Report Criteria Pages

O
ne of the most time-consuming tasks involved in
building any application is the customization of Column Name Data Type Description

the different criteria pages for the reports. This ReportID Int ID of report to which these criteria
article illustrates how to centralize your reporting criteria controls belong.

interface into one page and dynamically create report cri- ControlName Varchar Name of the control object using ‘txt’,
‘lst’, etc. prefix.
teria pages at run time using definitions stored in a table.
ParameterName Varchar Name of the report parameter to which
the entered value is assigned.
The controls typically required for criteria pages are
Label Varchar Text used to described the control on
text/numeric input boxes, date controls, checkboxes, list-
the Web page.
boxes, and comboboxes. Radio buttons are not necessary
because comboboxes can handle the same choices and Type Tinyint Enumerated value indicating the type of
are much easier to work with when using data-driven control: ComboBox, ListBox, etc.
programming techniques. DataSource Varchar Connection string for data-populated
controls.
As a general rule, date criteria should be set up in a
StoredProc Varchar Name of the stored procedure, the value
“from/to” layout specified by the user as a range. If a user column, and the description column
only needs one day’s worth of information, the “from/to” that populated the control separated by
dates can be set to the same date. If the particular param- semi-colons.
eter truly requires only a single date, then certainly offer DefaultValue Varchar Default value of the control.
the user only one date box. Your validation code should
preclude the user from entering a “from” date that is later Left Int Left position on the Web page.
than the “to” date (and any other such logical inconsis-
Top Int Top position on the Web page.
tencies). Optionally, the “to” date can be defaulted to the
system date as user needs require. Because there’s nor- Width Int Width position on the Web page.
mally very little free-form data you would pass to a report
engine, most of the error checking can occur before the Height Int Height position on the Web page.
user selections are submitted to the reporting tool.
Figure 1: Set the definitions for your criteria controls in a table.
Checkboxes handle Boolean values; textboxes can allow
the user to restrict the output based on free-form text the report could return “Smoot”, “Smith”, “Smythe”, etc.
— a last name, for example. Often you may wish to treat Depending on the flavor of SQL you are using, this can be
all entries in the textbox as partial search criteria. For accomplished by using the LIKE keyword and appending
example, if in filtering by last name the user enters “Sm”, a percent sign to the end of the search value:

8 October 2008 | www.aspnetPRO.com


ASP.NET ASP WINDOWS FORMS
®
.NET ACTIVEX

N Se nd 3 n X fiel
centralize

EW cti 2 M d
Co

64 fice S W
O te
m

bi O o

VE n br it v sup omp
f M
pl

t a pe rd
e

o b L c
RS eak ersi po ati
IO s ons rt bilit
N
:
your word processing

y
���������� ��� 2 CREATE
print-ready
����������������
PDF documents

�������� �����������������
ê STORE
documents on a
server

7 EDIT

�������������� documents in a
�������������������������
browser

�������
TX Text Control ®
.NET Server 14.0
��� ������

SERVER-SIDE
��������������������������
• Create, modify and convert DOCX, DOC, RTF and HTML documents on a
central server
• Load and save MS Word documents including all merge fields
• Merge templates and create print-ready, password encrypted PDF documents
CLIENT-SIDE
• Edit documents directly in Microsoft Internet Explorer®
• Integrate a fully featured word processing interface, including headers and
footers, text frames, images, decimal tabs, section breaks and many more

© 2008 The Imaging Source Europe GmbH. All rights reserved. TX Text Control is a registered trademark of The Imaging Source Europe GmbH in the United States and/or other countries. All other names of actual companies and
products mentioned herein may be trademarks of their respective owners. Microsoft, Windows and Internet Explorer are either registered trademarks or trademarks of Microsoft Corporation in the United States and/or other countries.

Download a fully functional trial version at


www.textcontrol.com TX Text Control Sales: 877-462-4772 (toll free)
TX Text Control Europe Sales: +49 (0) 421 3359 0
CoverStory | Custom Criteria

SELECT * Suppose you want to display a


FROM Employees listbox to the user that will allow
WHERE LastName LIKE 'Sm%'
them to select none, one, or multi-
ple items. You can accomplish this
Listboxes provide the most flexible criteria control. Use of a with the following line of code:
listbox implies that the user may select more than one option.
Each listbox should have a button underneath it that allows ShowListBox(szControlName,
the user to clear the choices made. This way if a user wishes to szParameterName,
szLabel,
run a report for both the Human Resources and Manufacturing szDataSource,
departments, it is rather easy to do so. In those cases where szStoredProc, Figure 2: Filter departments.
the user is permitted to select only one out of a set of options, szDefaultValue,
iLeft,
use a combobox. In both cases, each control has two columns. iTop,
The first is invisible to the user and contains the unique ID of iWidth,
the table that contains the filter options. The second column iHeight);

contains the text description the user would recognize.


This code will display the Web page shown in Figure 2.
CheckBoxList controls, specifically, are usually best for
making multiple selections on an individual control. The goal is to retrieve the user selections client side only
Though you can certainly accomplish the same thing because you can always pass the values to the server via
with a ListBox control, my experience has been that the hidden controls. Because of the increasing popularity of
user can easily forget to press the Ctrl key when making asynchronous JavaScript (AJAX), more and more develop-
multiple selections and may end up deselecting every- ers are avoiding full-page postbacks for tasks such as report
thing selected so far. This is not a problem with Check- generation. By retrieving the user selections client side and
BoxList controls. ListBox controls are more appropriate invoking an on-demand reporting Web service asynchro-
in cases where you need mutually exclusive lists. For nously, you can display the report output with minimal
example, when you want two adjacent ListBox controls server traffic. This approach also simplifies the UI code
so that when the user double-clicks on the first listbox, because we don’t need to maintain state between postbacks.
the choice is moved to the second, and vice versa. The
reason a CheckBoxList control is not being used here is abstract class ControlManager
{
because the id values assigned to it through the ListItem private string szName;
object do not persist client side, and therefore cannot private Label oLabelControl;
be retrieved through JavaScript. Microsoft Knowledge
public string Name
Base article Q309338 (support.microsoft.com/kb/309338) {
explains this problem in greater detail. CheckBoxList con- get { return szName; }
set { szName = value; }
trols work very well when building a WinForms interface. }

Dynamic Criteria Controls public Label LabelControl


{
The data-driven techniques for each of the criteria controls are get { return oLabelControl; }
very similar to one another. Therefore, we’ll examine the code set { oLabelControl = value; }
}
for creating ListBox controls. ListBoxes are the most complex of
}
the controls and, therefore, illustrate every feature.

class ListBoxManager : ControlManager


You can set the definitions for your criteria controls in a {
table. The table structure in Figure 1 shows the data needed private System.Web.UI.WebControls.ListBox oListBoxControl;
to display a criteria screen. Each report will have as many private Button oButtonControl;

rows in the table as it has parameters. public System.Web.UI.WebControls.ListBox ListBoxControl


{
This isn’t a complete list of attributes for the various get { return oListBoxControl; }
set { oListBoxControl = value; }
controls. You also could add a Required column that tells }
the engine to generate the necessary JavaScript to force
public Button ButtonControl
the user to make a selection. Likewise, you could have
{
a JavaScript column that contains a block of JavaScript get { return oButtonControl; }
code that handles validation. You also could have a set { oButtonControl = value; }
}
RegEx column that contains the regular expression that }
formats input; for example, a valid e-mail address or a
masked edit. Figure 3: ControlManager and ListBoxManager classes.

10 October 2008 | www.aspnetPRO.com


���������������
������������������������������

��������������������������������������������������������������������������������������������������
����������������������������������������������������������������������������������������������������
����������������

�������������������������������������������
�������������������������������������� ��������������������������������������������
�������������������������� ���������������������������������������
������������������������������������ ����������������
����������������������������� � ������������������������������������������
������ ���������������������������

���������������� ������
������
��� ��������������������������������������������������
������
���������������������������������
��������������������������������
����������������������������������
�������������������������������
�������������
������������������������������������������
�����������������������������������
������������
����������������������������������������
����������������������������
������������������������������
�����������������
��������������������

��������������������������������������
�������������������������������������
��������������������������������������
���������������������������������
�������������������������������������

������������������������������������������������������������
��������������������������������������������������������������������
CoverStory | Custom Criteria

private void ShowListBox(string szControlName, private System.Web.UI.WebControls.ListBox


string szParameterName, AddDynamicListBox(string szControlName,
string szLabel, string szDataSource,
string szDataSource, string szStoredProc,
string szStoredProc, int iLeft,
string szDefaultValue, int iTop,
int iLeft, int iWidth,
int iTop, int iHeight)
int iWidth, {
int iHeight) System.Web.UI.WebControls.ListBox oListBox;
{
ListBoxManager oListBoxManager; oListBox = new System.Web.UI.WebControls.ListBox();

oListBoxManager = new ListBoxManager();


LoadListBox(oListBox, szDataSource, szStoredProc);

oListBoxManager.Name = szControlName;
oListBox.ID = szControlName;
oListBox.Style["position"] = "absolute";
oListBoxManager.LabelControl =
oListBox.Style["left"] = iLeft.ToString() + "px";
AddDynamicLabel(szControlName, iLeft, iTop, szLabel);
oListBox.Style["top"] = iTop.ToString() + "px";
oListBox.Style["height"] = iHeight.ToString() + "px";
oListBoxManager.ListBoxControl =
oListBox.Style["width"] = iWidth.ToString() + "px";
AddDynamicListBox(szControlName, szDataSource,
oListBox.BorderStyle = BorderStyle.Solid;
szStoredProc, iLeft, iTop + 20, iWidth, iHeight);
oListBox.SelectionMode = ListSelectionMode.Multiple;
oListBoxManager.ButtonControl =
AddDynamicListBoxButton(szControlName, iLeft, Panel1.Controls.Add(oListBox);
iTop + iHeight + 20, iWidth, 23, szLabel);
return oListBox;
} }

Figure 4: The ShowListBox method. Figure 6: The AddDynamicListBox method.

private Label AddDynamicLabel(string szControlName, private Button AddDynamicListBoxButton(string szControlName,


int iLeft, int iLeft,
int iTop, int iTop,
string szCaption) int iWidth,
{ int iHeight,
Label oLabel; string szCaption)
{
oLabel = new Label(); Button oButton;

oLabel.Style["position"] = "absolute"; oButton = new Button();


oLabel.Style["left"] = iLeft.ToString() + "px";
oLabel.Style["top"] = iTop.ToString() + "px"; oButton.Style["position"] = "absolute";
oLabel.Text = szCaption; oButton.Style["left"] = iLeft.ToString() + "px";
oButton.Style["top"] = iTop.ToString() + "px";
Panel1.Controls.Add(oLabel); oButton.Style["width"] = iWidth.ToString() + "px";
oButton.Text = "Clear Selected " + szCaption;
return oLabel;
} oButton.Attributes.Add("onclick",
"return DeselectAll('" + szControlName + "')");
Figure 5: The AddDynamicLabel method.
Panel1.Controls.Add(oButton);
The ShowListBox method invokes additional methods that
return oButton;
display the Label, ListBox, and Button objects that make }
up the set of controls. These controls are managed in the
classes shown in Figure 3. Figure 7: The AddDynamicListBoxButton method.

Because every control has a name, and almost all have an The AddDynamicLabel method instantiates a Label object
associated Label control, these properties are encapsulated and assigns its location via the Style method (see Figure 5).
in the ControlManager base class from which the individual The new control is then added to the Controls collection of
control’s classes, like ListBoxManager and TextBoxManager, the owner Panel object, which displays it to the user.
inherit. To display the control, you must pass the control
name to the ShowListBox method (see Figure 4), along with Likewise, the ListBox control itself is displayed in a similar
the data source information, the dimensions of the listbox, fashion, as illustrated in the AddDynamicListBox method
and the caption. ShowListBox instantiates an object of type shown in Figure 6. The SelectionMode property is always set
ListBoxManager, which receives the instantiated objects of to multiple selections; otherwise, a combobox would suffice.
the Label, ListBox, and Button types. The szStoredProc parameter contains a semi-colon-delimited

12 October 2008 | www.aspnetPRO.com


function DeselectAll(szListBox) Notes
{
var oListBox = document.getElementById(szListBox); When running the sample application, please adjust the
database path on line 638 as needed. In addition, please
for (i=0; i < oListBox.options.length; i++) adjust the database path in the DataSource column of the
oListBox.options[i].selected = false;
ReportParameters table in the MDB file.
return false; Also, add the Access database inside the C:\Articles\Data-
} DrivenCriteriaScreens directory. You should create a direc-
tory if it doesn’t exist.
Figure 8: The DeselectAll method.

function ParseIt(szListBox, bQuotes, bCheckedOnly)


which it is associated. The generic JavaScript function
{
var oListBox = document.getElementById(szListBox); that clears the selected options in the ListBox is shown
var szResult = new String(''); in Figure 8. The Button’s onclick event is wired to this
var szQuotes = '';
JavaScript function using the Attributes.Add method.
var szValue = '';

if (bQuotes) Extracting the User Selections


szQuotes = "'";
After the user has completed entering their report criteria,
for (i=0; i < oListBox.options.length; i++) the Get Data button can generically retrieve the information
{ one control at a time. In the code shown here, the selected
szValue = oListBox.options[i].value;
departments are retrieved and displayed in an alert box:
if (bCheckedOnly)
{ function GetData()
if (oListBox.options[i].selected) {
szResult += szQuotes + szValue + szQuotes + ","; var szDepartments = "Departments: " +
else ParseIt("ListBox6", false, true) + "\n";
szResult += szQuotes + szValue + szQuotes + ","; alert(szDepartments)
return false;
if (szResult.length > 0) }
szResult = szResult.substring(0, szResult.length - 1);

return szResult;
The JavaScript ParseIt function shown in Figure 9 iterates
}
the ListBox and extracts the data.
Figure 9: The JavaScript ParseIt function.
The other controls are handled in a fashion similar to the
ListBox. Ultimately, the data definitions will produce the
screen shown in Figure 10.

Using these techniques can dramatically reduce the effort


required to produce and maintain report criteria screens.
By storing the definitions in a database table, you can
easily add new criteria for a report, or provide support for
a brand new report, without releasing another version of
the application. </>
Figure 10: Dynamically generated criteria screen.

Source code accompanying this article is available for down-


list of the stored procedure name, the value id, and the dis- load to asp.netPRO subscribers at www.aspnetPRO.com.
played description. The LoadListBox method will parse this
string into its three components. Using the connection string
supplied by szDataSource, it will connect to the database, Carl Ganz, Jr. is president of Seton Software Development, Inc.,
execute the stored procedure, and load the appropriate data a provider of software design and development services located in
columns into the ListBox control. Raritan, New Jersey. He has an MBA in Finance from Seton Hall
University and is the author of three books on software development,
The Button control is also created and displayed in a similar as well as dozens of articles on Visual Basic, C#, and Microsoft
fashion as the Label and ListBox controls, as shown in Figure 7. .NET technology. He is the president and founder of the New Jersey
Visual Basic User Group and has been a featured speaker at software
The Button control triggers JavaScript code that, when development conferences in both the US and Germany. Contact Carl
clicked, must clear the selections in the ListBox with at seton.software@verizon.net.

asp.netPRO | October 2008 13


C o r e C o d er
LANGUAGES: C# § ASP.NET VERSIONS: 3.5
§ By Dino Esposito

Authentication and AJAX


Getting Credentials and Sharing Tokens in AJAX Is
Much the Same as in Classic ASP.NET

B
ecause of the statelessness of the HTTP protocol, Authentication is a key feature in ASP.NET. It ensures
Web applications have a lot to gain from server- that only recognized users are granted access to a given
resource — be it a page, a folder, or a simple image.
side services that make up for the extreme Authentication is implemented through an HTTP module
simplicity of the protocol. On the other hand, the HTTP that intercepts any request to a protected resource and
protocol was designed for an idea of the Web quite differ- directs the user to a log-in page first. Are authentication
and other services compatible with ASP.NET AJAX?
ent from the one we have today. Such a simple protocol
was just fine for sharing HTML-based and hyperlinked How Authentication Works in ASP.NET
documents; it is less than ideal when we actually use In the configuration file in classic ASP.NET, you declare
which resources in which folder are off-limits for the anony-
HTML as an application delivery format and claim for mous user. At that point, the runtime pipeline automatically
security, state maintenance, and caching. At the end of redirects the anonymous user to a log-in page, where the
the day, though, HTTP is still there — and it forms the user is prompted for credentials. Next, if the user is success-
fully authenticated, an authentication token is generated as
foundation of ASP.NET and AJAX. a cookie and appended to the response. Finally, the user is
redirected to the originally requested page and passes any
To empower Web applications, virtually all server-side run- further check because of the attached token. Forms authenti-
time environments build an abstraction layer and provide cation is the ASP.NET built-in infrastructure that implements
additional services to applications, such as session state, the log-in pattern. Forms authentication requires an addi-
caching, user profiling, and, especially, authentication and tional log-in page and two HTTP redirect commands. Is it
role management. possible to save one redirect and authenticate the user from
within an HTML page through an AJAX call?
In ASP.NET, the vast majority of these application services
are incorporated in the runtime pipeline and use the HTTP An AJAX Infrastructure for Authentication
module infrastructure. Services intercept pipeline events For ASP.NET AJAX clients, the infrastructure for authentica-
and kick in when appropriate. The page developer isn’t tion consists of two key components: a client-side JavaScript
involved in the services activity and passively deals with class and a system-provided HTTP handler. The same model
the results of the activity itself. What does it mean? For is in place for other system services, such as role manage-
example, if a profiling service is in place, the page devel- ment and user profiles.
oper will find profile information for the current user ready
to use. The same goes for the role management service. The JavaScript class supplies one method to send any user’s
But what about authentication, instead? credentials to a server-side endpoint. The HTTP handler

14 October 2008 | www.aspnetPRO.com


[ScriptService]
Method Description class AuthenticationService
{
login Verifies credentials and issues an authentication ticket if // Methods
public AuthenticationService();
the credentials are good.
[WebMethod]
logout Clears the authentication ticket. public bool IsLoggedIn();
[WebMethod]
public bool Login(string userName, string password,
Figure 1: Methods of the Sys.Services.AuthenticationService object. bool createPersistentCookie);
[WebMethod]
public void Logout();
Property Description }

isLoggedIn Boolean read-only property; indicates whether the Let’s focus on the login method. The first two arguments
current user is logged in. set the credentials of the user. When you authenticate a
path Gets and sets the URL to reach the authentication user through Forms authentication, a cookie is created
Web service. and attached to the response. This cookie is referred to
as the authentication cookie and its name defaults to
timeout Gets and sets the timeout for the user authentication
process.
.ASPXAUTH. The final Boolean argument indicates wheth-
er a persistent cookie is required. If so, authenticated
Figure 2: Properties of the Sys.Services.AuthenticationService object. credentials will be in a persistent cookie saved across
browser sessions.
internally invokes a system-provided scriptable Web service.
As a result, you receive a Boolean answer that indicates What about the expiration of the authentication cookie?
whether the user has been authenticated or not. The Web The cookie is simply given the expiration that you specify
service uses the server-side ASP.NET authentication and in the configuration file. So to set the timeout that is
membership API to validate the user information. When you appropriate for your site, you simply set the timeout
use a JavaScript proxy to command a remote authentication attribute in the <authentication> section of the applica-
service, you check your users more quickly because you tion’s web.config file to the desired number of minutes.
can incorporate a log-in form into any pages in the site that You should note that the authentication service sets the
users visit regularly. The authentication essentially consists cookie using the SetAuthCookie method on the Forms-
of a request, and doesn’t force a redirect to a specialized Authentication class. This means that most settings
log-in page. defined in the <authentication> section of the configura-
tion file are taken into proper account while creating the
From JavaScript, you invoke a proxy class implemented as a authentication ticket.
singleton. The original JavaScript class is instantiated in the
Microsoft AJAX client library and is exposed as an object (as The Role of Membership Providers
named here): Where would you specify the logic to check credentials? The
AJAX authentication service takes advantage of the currently
var proxy = Sys.Services.AuthenticationService; registered ASP.NET membership provider. The default mem-

The methods offered by the authentication


JavaScript proxy class for ASP.NET AJAX are public class CustomMembershipProvider : MembershipProvider
{
listed in Figure 1. Figure 2, instead, details the public CustomMembershipProvider()
properties defined on the object. The underlying {
JavaScript class is a regular JavaScript proxy class }

nearly identical to any other JavaScript proxy public override bool ValidateUser(string username, string password)
class that the ScriptManager control generates for {
referenced Web and WCF services. The only dif- return AuthenticateUser(username, password);
}
ference is that such proxy classes for authentica-
tion, role management, and profile services are private bool AuthenticateUser(string username, string password)
natively part of the Microsoft client library and {
// Your authentication logic here
downloaded as part of the MicrosoftAjax.js file. }

The back-end of the authentication service is // Override all other abstract methods in MembershipProvider
:
implemented in the AuthenticationWebService }
class, marked as sealed and internal. The class
features a script service, as illustrated here: Figure 3: Skeleton for a custom membership provider.

asp.netPRO | October 2008 15


CoreCoder | Authentication and AJAX

bership provider checks username and


public abstract class MembershipProvider : ProviderBase
password against the content of the
{
users table in the aspnetdb.mdf file. public abstract bool ChangePassword(
However, both the database schema string username, string oldPassword, string newPassword);
public abstract bool ChangePasswordQuestionAndAnswer(
and the logic applied are a detail you
string username, string password, string newPasswordQuestion,
can change at will. string newPasswordAnswer);
public abstract MembershipUser CreateUser(
string username, string password, string email, string passwordQuestion,
If you want to apply an application-
string passwordAnswer, bool isApproved, object providerUserKey,
specific piece of logic or reuse an out MembershipCreateStatus status);
existing database of users, all you have public abstract bool DeleteUser(
string username, bool deleteAllRelatedData);
to do is create a custom membership
public abstract MembershipUserCollection FindUsersByEmail(
provider. Starting with ASP.NET 2.0, string emailToMatch, int pageIndex, int pageSize, out int totalRecords);
forms authentication is built atop a public abstract MembershipUserCollection FindUsersByName(
string usernameToMatch, int pageIndex, int pageSize, out int totalRecords);
provider-based, extensible model that
public abstract MembershipUserCollection GetAllUsers(
lets you easily change the underlying int pageIndex, int pageSize, out int totalRecords);
machinery, such as validation code public abstract int GetNumberOfUsersOnline(
);
and users management, while leaving
public abstract string GetPassword(
the front-end API intact. Based on this string username, string answer);
model, you can easily adapt your exist- public abstract MembershipUser GetUser(
object providerUserKey, bool userIsOnline);
ing code to connect to the authentica-
public abstract MembershipUser GetUser(
tion machinery of ASP.NET, also from string username, bool userIsOnline);
an AJAX client. public abstract string GetUserNameByEmail(
string email);
public abstract string ResetPassword(
A custom membership provider takes string username, string answer);
the form as shown in Figure 3. It is public abstract bool UnlockUser(
string userName);
essentially a class that inherits from
public abstract void UpdateUser(
MembershipProvider and overrides MembershipUser user);
a few members. The key member to public abstract bool ValidateUser(
string username, string password);
override is ValidateUser. This method
takes a username and password and // Properties
returns a Boolean answer. It’s within public abstract string ApplicationName { get; set; }
public abstract bool EnablePasswordReset { get; }
this member that you should place
public abstract bool EnablePasswordRetrieval { get; }
your custom logic for managing a public abstract int MaxInvalidPasswordAttempts { get; }
user’s credentials. public abstract int MinRequiredNonAlphanumericCharacters { get; }
public abstract int MinRequiredPasswordLength { get; }
public abstract int PasswordAttemptWindow { get; }
Note also that MembershipProvider is an public abstract MembershipPasswordFormat PasswordFormat { get; }
abstract class with a long list of mem- public abstract string PasswordStrengthRegularExpression { get; }
public abstract bool RequiresQuestionAndAnswer { get; }
bers to override in any derived class.
public abstract bool RequiresUniqueEmail { get; }
The complete list is shown in Figure 4. }

You are not required to give an effec- Figure 4: Definition of the MembershipProvider class.
tive implementation to each member,
but at the very minimum you should day, this class is a relatively thin wrapper around
throw an exception, as shown here: MembershipProvider that overrides ValidateUser and
throws for any other method. You might seriously consider
public override bool ChangePassword(string username, deriving your custom provider class from this instead of
string oldPassword, string newPassword) MembershipProvider.
{
throw new NotSupportedException();
} Finally, to register the new membership provider, tweak the
web.config file as shown here:
For ASP.NET AJAX, though, there’s a quicker way out you
might want to consider. In the System.Web.ClientServices.- <membership defaultProvider="MyMembershipProvider">
Providers namespace you’ll find the ClientFormsAuthenti- <providers>
cationMembershipProvider class. This class is essentially <add name="MyMembershipProvider"
type="YourNamespace.CustomMembershipProvider" />
an implementation of MembershipProvider that ASP.NET </providers>
AJAX uses to perform default validation. At the end of the </membership>

16 October 2008 | www.aspnetPRO.com


��������������
����� ��������������
���������������������
������������� �� ����������������������������

�����������������������������������������������������������������������
�������������������������������������������������������������������������������������������
���������������������������������������������������������������������������

������������������������������ ���������������������������������������������������������������������������
� ���� � ����������������������������������
� ���� � �����������������������������
� ��������������������� � �����������������������
� ��������������� � ����������
� ��������������������� � ������������������
� ���������������������� � �����������������������������������
� ����������������������� � �����������
� ��������������������������������� � ���������������
� ����������
� ������������������������������������
����������������
����� ������ ����� �
� ���������������������
� ��������������������
������� ����� ����� � ���������������� � ������������������
� ������������ � ��������������
���������� ����������� ��������������� � �������� � ��������������������������������
���������������� �������������� �������������� � ������������������������� �����
��������������� ������������ � ���� � ���������������������������
��������� ��������������������������������� � �������������������������������������
�������� ������������ �
�������������������������������
� ��������� �
��������� ��������������� � �������������������������������� � ��������������������������������
��������� � ������� � ����
� ���������������������������� � ���

���������������
���������������������� � ������������ � ������������
CoreCoder | Authentication and AJAX

Add the preceding code to the web.config file under the button to your client user interface and bind it to the fol-
<system.web> node and you’re done. lowing JavaScript code:

Performing Authentication function Logout1_Click()


Using ASP.NET AJAX authentication requires a bunch of {
Sys.Services.AuthenticationService.logout(
HTML input tags to collect username, password, and the onLogoutCompleted);
optional checkbox for a persistent cookie. You also need a return false;
JavaScript button bound to the following code: }

<script type="text/javascript"> The function originates a redirect and a full page reload.
var username = $get("Login1_UserName"); The final response doesn’t include any more than the
var password = $get("Login1_Password");
authentication cookie.
function Login1_Click()
{ Brief Notes on AJAX Authentication
Sys.Services.AuthenticationService.login(
username.value, password.value, false, ASP.NET AJAX authentication needs to be explicitly
null, null, onLoginCompleted); enabled through a setting in the configuration file:
return false;
}
: <system.web.extensions>
</script> <scripting>
<webServices>
<authenticationService enabled="true" />
The authentication occurs asynchronously; when all is </webServices>
done, the callback (in this case, onLoginCompleted) is </scripting>
</system.web.extensions>
invoked to give you a chance to update the user interface.

What about the log-out process? To give users a chance In ASP.NET, forms authentication always sends credentials
to log out directly from the client, you must add another as clear text. This is nothing new, but a reminder is still
useful. For a number of security-related reasons, it is rec-
ommended that log-in forms be placed in pages you reach
through HTTPS. Clear text is not related to AJAX, but
using AJAX for authentication certainly makes it easier for
developers to place log-in forms everywhere.

Another point to keep in mind is that the AJAX authentica-


tion service doesn’t work with applications that use a cook-
ieless authentication scheme.

Conclusion
Forms authentication is the mechanism in ASP.NET applica-
tions that allows you to show a log-in page in front of users
when they attempt to access a protected resource. In classic

100s of FREE ASP.NET, forms authentication is based on a couple of HTTP


redirects. In an ASP.NET AJAX scenario, you can use some
JavaScript code to make at least the log-in process happen in a

ASP.NET Videos smoother way. </>

Dino Esposito is an architect at IDesign and specializes mainly


in ASP.NET, AJAX, and RIA solutions. Dino is the author of
Programming ASP.NET 3.5 Core Reference (Microsoft Press, 2008).
He also wrote Introducing ASP.NET AJAX, also for Microsoft Press.
Late-breaking news is available at weblogs.asp.net/despos.

18 October 2008 | www.aspnetPRO.com


C o n t r o l Fre ak
LANGUAGES: VB.NET | C# § ASP.NET VERSIONS: 2.0+
§ By Steve C. Orr

Process Payments Promptly


Use Free PayPal-compatible Web Controls to Add E-Commerce
Capabilities to Your Web Site

O
ver the years, many Web development tasks have Present Purchases
become easier to implement. For example, HTML The BuyNow control has a nearly identical design and
a similar one-button user interface. It is intended to be
is generated with drag and drop simplicity, basic associated with a specific product or service so users may
state management is now virtually automatic, and user purchase it. Like the donation control, the user’s initial
profile data management is nearly as simple as getting and button click leads them through PayPal’s intuitive pay-
ment processing system. When the transaction is com-
setting variables. plete, PayPal provides multiple options for transferring the
flow back to your Web site and allowing your Web site to
One thing that remains relatively laborious, however, is verify the completed payment.
payment processing. In an attempt to quench the thirst
for simpler e-commerce capabilities, I’ve assembled two The default user interface of the Buy Figure 2: The Buy
ASP.NET Web controls that will empower any user to Now button is shown in Figure 2. An Now button allows
donate money or buy a basic product or service from alternative button image may be speci- a user to purchase
a particular product
your Web site. fied by adjusting the ImageUrl property.
or service.

In the following paragraphs I’ll show you how easy it is to Common Properties
use these controls from an ASP.NET application. Following The two controls present slightly different user interfaces
that, I’ll show you how the controls were designed so you to the user, but they share the same set of public proper-
can extend them or learn how to make similar Web controls. ties. Some of the properties are likely more relevant for the
Buy Now button than the Donate button, but all the prop-
Accept Donations erties can be useful for both controls in certain situations.
The Donate control allows users to give money in a simple
and intuitive way. When the user clicks it at run time, they are If you’re familiar with the standard ASP.NET ImageButton
led through PayPal’s payment system that accepts credit card control, you’ll find most of the properties to be familiar
payments and other common payment options. End users do because both controls ultimately inherit from it. Here I’ll
not necessarily need to be PayPal members, but Web sites will cover the unique properties the controls offer (see Figure 3).
need a basic account with PayPal in order to accept such pay-
ments. Setting up a PayPal account is free, although they typi- Perhaps the most important property is the BusinessEmail
cally take a small specified amount from each transaction as string. This must be set to the e-mail address associated
their fee. When the transaction is complete, users are option- with your registered PayPal account. If this property is
ally redirected automatically back into not set correctly, you will not receive payments that were
the specified flow of your Web site. intended for you.

The default user interface of the Donate Figure 1: The Donate The Price property is also of notable functionality. For
control provides a
button is shown in Figure 1. An alter- simple and familiar way
the Buy Now button you’ll almost certainly want to set
native button image may be specified for users to contribute this property to the amount of the associated product or
by adjusting the ImageUrl property. to your cause. service. For the Donate button, you might choose to leave

asp.netPRO | October 2008 19


ControlFreak | Process Payments Promptly

The ItemName property should be filled with the name of the


Value
Property Description product or service with which the Buy Now button is associ-
Type
ated. PayPal presents this name to the user so they can rest
SuccessReturnUrl String The public URL to which PayPal assured they are purchasing the correct item. This property is
should return the user upon clearly optional for the Donate button, although you might (in
successful payment.
some cases) choose to associate a donation with a particular
FailReturnUrl String The public URL to which PayPal item of some sort. If the ItemName property value is omit-
should return the user upon ted, PayPal typically allows the user to enter a free-form item
aborted payment.
name with which their payment is associated.
NotifyUrl String The URL to which PayPal posts
information about the transaction Similarly, the ItemNumber property can be filled with any
via Instant Payment Notification. custom identifier that you may have associated with the
Must be URL-encoded.
specified product or service. This passthrough variable is
BusinessEmail String The registered e-mail address of never shown to the user, but is saved along with the trans-
your PayPal account. action to help identify what was purchased. Taking this con-
CustomData String Passthrough variable never presented cept one step further, the Invoice and CustomData properties
to the customer. May be useful for also can be filled with personalized passthrough identifiers
associating custom state or identifier of some sort to help identify particular purchases.
data with the transaction.

Invoice String Passthrough variable you can use to The Boolean RequireNote property can be set to true to
identify your invoice number for this force users to include a note along with their payment. The
purchase. default value of this property is false.
ItemName String Description of item. If omitted,
customers can enter an item name You can avoid having to manually collect shipping address
at time of purchase. information for purchases that must be physically shipped to
ItemNumber String Passthrough variable for you to track
a user simply by setting the Boolean RequireShippingAddress
purchases or donations, passed property to true. This will prompt PayPal to collect the ship-
back to you at payment completion. ping address information, thus simplifying your own input
requirements.
CurrencyCode String Defines the currency of the payment.
Default is USD.
Transaction Complete
Price Single The required payment amount. If you want the user to return to the flow of your Web site
(Leave blank to allow the user to
after they’ve completed their interaction with PayPal, you
choose the payment amount.)
must set the SuccessReturnUrl and FailReturnUrl properties.
PostReturn Boolean Return method GET or POST: the The SuccessReturnUrl property should be set to the absolute
FORM METHOD used to send data
public Web address of the page intended to accept the user
to the URL specified by the return
variable after payment completion. back into your site. If the user cancels out of the PayPal trans-
Default: false. action, the FailReturnUrl page accepts the redirection instead.

RequireShippingAddress Boolean Prompts customer for a shipping


All these transaction variables will be posted to the
address. Default: false.
above specified ReturnUrl if the Boolean PostReturn
RequireNote Boolean Prompts customer to include a note property is set to true. This allows the page to potentially
with payment. Default: false. contain custom logic to recognize the incoming transaction
data and respond intelligently to the success or failure of
Figure 3: These are the unique public properties of the Donate and that transaction. For example, a custom function could be
BuyNow controls. called to order the shipment of the product associated with a
successful transaction. The relevant form variables are docu-
this property value unspecified. In either case, if the prop- mented on PayPal’s Web site at https://www.paypal.com/
erty is left blank, PayPal will prompt the user to specify IntegrationCenter/ic_std-variable-ref-buy-now.html.
their desired payment amount.
However, instead of blindly trusting any data claiming to be
The CurrencyCode property is only relevant when the price from PayPal that is posted to this page, you might want to
property has been set. The default currency code is USD, take a more secure approach by verifying the data with one
which specifies that the Price property contains a United of PayPal’s other payment notification services. These services
States Dollar amount. Any other standard currency code can also can be useful if you choose to leave the PostReturn prop-
be specified for this property value. erty at its default value of false.

20 October 2008 | www.aspnetPRO.com


ControlFreak | Process Payments Promptly

'(requires reference to System.Design) Imports System.ComponentModel


<Editor(GetType(System.Web.UI.Design.UrlEditor), _ Imports System.Web.UI
GetType(System.Drawing.Design.UITypeEditor)), _
Bindable(True), Category("Behavior"), _ <DefaultProperty("Price"), _
DefaultValue(""), Localizable(True)> _ ToolboxData("<{0}:Donate runat=server></{0}:Donate>")> _
Property SuccessReturnUrl() As String Public Class Donate
Get Inherits aspaypal_base
Dim s As String = CStr(ViewState("SuccessReturnUrl"))
If s Is Nothing Then Protected Overrides Sub OnInit(ByVal e As System.EventArgs)
Return String.Empty MyBase.OnInit(e)
Else
Return s Dim u As String
End If u = "http://www.paypal.com/en_US/i/btn/btn_donate_LG.gif"
End Get Me.ImageUrl = u

Set(ByVal Value As String) Me.cmd = "_donations"


ViewState("SuccessReturnUrl") = Value End Sub
End Set
End Property End Class

Figure 4: This is an example of one of the properties from the Figure 6: This is the complete code for the Donate class found in
aspaypal_base class. the file Donate.vb.

Imports System.ComponentModel
Imports System.Web.UI

<DefaultProperty("Price"), _
ToolboxData("<{0}:BuyNow runat=server></{0}:BuyNow>")> _
Public Class BuyNow
Inherits aspaypal_base

Protected Overrides Sub OnInit(ByVal e As System.EventArgs)


MyBase.OnInit(e)

Dim u As String
u = "http://www.paypal.com/en_US/i/btn/btn_buynow_LG.gif"
Me.ImageUrl = u

Me.cmd = "_xclick"
Figure 5: Visual Studio’s Select URL dialog box. End Sub

End Class

For example, their Instant Payment Notification System


Figure 7: This is the complete code for the BuyNow class found in
(IPN) can post a special message to your server when a the file BuyNow.vb.
transaction has been successfully completed. The Notify-
Url property of the controls can be used to specify the full The SuccessReturnUrl property listed in Figure 4 is a little
public Web address of the page that accepts such messages. more interesting than most of the other properties because it
This and other types of automated and manual PayPal verifi- is decorated with the Editor attribute. This design-time feature
cation systems are documented at https://www.paypal.com/ tells Visual Studio to show the ellipsis (...) button in the prop-
IntegrationCenter/ic_button-encryption.html. erties window for this property. When clicked, the standard
Visual Studio Select URL dialog box appears (see Figure 5).
How It Works
Because the Donate and Buy Now buttons have such a similar Listing One lists the aspaypal_base class’ internal CreateHidden-
design, it makes sense to have them inherit from the same Fields subroutine, which is called from the Render method.
base class. This technique maximizes code reuse and reduces The actual Donate and BuyNow controls (listed in Figures 6
maintenance. The custom abstract base class from which both and 7, respectively) contain very little code, because most of
controls are inherited is named aspaypal_base. It, in turn, the functionality is implemented via inheritance.
inherits from the standard ASP.NET ImageButton Web control.
As you can see by the code listings in Figures 6 and 7,
The aspaypal_base class primarily collects the previously the controls differ only by a couple properties that have
noted properties and renders them into the page as hidden distinctive default values set in their initialize events. The
form fields that are recognized by PayPal. It then posts these underlying ImageButton’s ImageUrl property is assigned
values into PayPal’s payment processing system. This requires a standard button image from PayPal’s site. Additionally,
a few hundred lines of fairly boilerplate code, examples of the custom cmd property is set to a value that reflects the
which are listed in Figure 4 and Listing One (on page 23). button’s type to PayPal’s Web site.

22 October 2008 | www.aspnetPRO.com


Conclusion
Payment processing no longer needs to be an ominous If Me.Price > 0 Then
development chore. By dropping one of these free controls h = New HiddenField()
h.ID = "amount"
on a Web page, basic e-commerce functionality can be h.Value = Me.Price
enabled simply by setting a property or two. You’ve seen h.RenderControl(writer)
how easy it is to use these controls, examined their proper- End If

ties, and explored much of the source code. If Me.CurrencyCode.Trim.Length > 0 Then
h = New HiddenField()
I encourage you to download the complete source code, h.ID = "currency_code"
h.Value = Me.CurrencyCode
available in both VB.NET and C#, to more thoroughly h.RenderControl(writer)
explore their inner workings. With this knowledge you can End If
extend these controls with custom functionality, or create
If Me.CustomData.Trim.Length > 0 Then
entirely new controls of similar design. </> h = New HiddenField()
h.ID = "custom"
C# and VB.NET source code accompanying this article h.Value = Me.CustomData
h.RenderControl(writer)
is available for download to asp.netPRO subscribers at End If
www.aspnetPRO.com/download.
If Me.NotifyUrl.Trim.Length > 0 Then
h = New HiddenField()
h.ID = "notify_url"
Steve C. Orr is an ASPInsider, MCSD, Certified ScrumMaster, h.Value = Me.NotifyUrl
Microsoft MVP in ASP.NET, and author of Beginning ASP.NET 2.0 h.RenderControl(writer)
End If
AJAX by Wrox. He’s been developing software solutions for leading
companies in the Seattle area for more than a decade. When he’s not If Me.FailReturnUrl.Trim.Length > 0 Then
busy designing software systems or writing about them, he often can h = New HiddenField()
h.ID = "cancel_return"
be found loitering at local user groups and habitually lurking in the h.Value = Me.FailReturnUrl
ASP.NET newsgroup. Find out more about him at SteveOrr.net or h.RenderControl(writer)
e-mail him at Steve@SteveOrr.net. End If

If Me.SuccessReturnUrl.Trim.Length > 0 Then


h = New HiddenField()
h.ID = "return"
Begin Listing One — The aspaypal_base h.Value = Me.SuccessReturnUrl
class’ hidden field rendering h.RenderControl(writer)

Protected Sub CreateHiddenFields(ByVal _


If Me.PostReturn Then
writer As System.Web.UI.HtmlTextWriter)
h = New HiddenField()
'Create common hidden fields...
h.ID = "rm"
h.Value = "2"
Dim h As HiddenField
h.RenderControl(writer)
End If
h = New HiddenField()
End If
h.ID = "business"
h.Value = Me.BusinessEmail
If Me.RequireShippingAddress = False Then
h.RenderControl(writer)
h = New HiddenField()
h.ID = "no_shipping"
If Me.Invoice.Trim.Length > 0 Then
h.Value = "1"
h = New HiddenField()
h.RenderControl(writer)
h.ID = "invoice"
End If
h.Value = Me.Invoice
h.RenderControl(writer)
If Me.RequireNote = False Then
End If
h = New HiddenField()
h.ID = "no_note"
If Me.ItemName.Trim.Length > 0 Then
h.Value = "1"
h = New HiddenField()
h.RenderControl(writer)
h.ID = "item_name"
End If
h.Value = Me.ItemName
h.RenderControl(writer)
h = New HiddenField
End If
h.ID = "cmd"
h.Value = Me.cmd
If Me.ItemNumber.Trim.Length > 0 Then
h.RenderControl(writer)
h = New HiddenField()
End Sub
h.ID = "item_number"
h.Value = Me.ItemNumber End Listing One
h.RenderControl(writer)
End If

asp.netPRO | October 2008 23


Exploring WCF Web Services
LANGUAGES: C# § TECHNOLOGIES: .NET 3.5 | WCF
§ By Michele Leroux Bustamante

Workflow Services
Exploring .NET Framework 3.5 Features for Better
Workflow and WCF Integration

T
his monthly column explores how to expose work- tier to automate the flow of messaging between users,
flows as WCF services, and how to consume WCF applications, and services. For client applications to reach
a workflow, it is helpful to expose it as a WCF service —
services from workflows using features introduced either behind the firewall or on the Internet. In a service-
with .NET Framework 3.5. If you have questions about oriented system, business functionality is typically exposed
migrating your existing ASMX or WSE Web services to through services (for this discussion I’ll assume services
are implemented in WCF) — which means that a workflow
WCF, or questions regarding WCF as it relates to Web ser- is likely to coordinate access to that functionality by calling
vices, please send them to underthehood@aspnetpro.com! those services.

Workflow Services were introduced with the release of .NET Simply put, Workflow Services make it easy to expose a
Framework 3.5 to facilitate better communication between workflow as a WCF service so that client applications can
WCF and Windows Workflow Foundation (Workflow or reach it, and make it easy for workflows to call out to WCF
WF). Before this release it was cumbersome at best to start services to coordinate access to business logic in a service-
a workflow from a WCF service operation, or to call a WCF oriented system. The value Workflow Services bring to the
service operation from an executing workflow. The term table is in the removal of overhead to set up communica-
“Workflow Services” describes a workflow that is exposed tion between WCF and Workflow to accomplish these two
as a WCF service and can more easily make calls to other scenarios. Under the assumption you are employing work-
WCF services, thanks to a few new Workflow activities: flow in the middle-tier, Workflow Services become a staple
ReceiveActivity and SendActivity. Visual Studio templates item in your application.
simplify the process of creating a new Workflow Service by
generating sample sequential or state machine workflows Workflow Service Features and
along with related code and configuration. Templates
Creating a Workflow Service involves leveraging several
In this article I’ll explain how Workflow Services can be .NET Framework 3.5 features, including:
used to expose workflows as WCF services, and to consume § ReceiveActivity: A new Workflow activity that imple-
other WCF services — and why you would want to leverage ments a WCF service operation.
these features. I assume you have some basic understanding § SendActivity: A new Workflow activity for calling WCF
of Workflow technology, so I won’t be introducing you to services from an executing workflow instance.
Workflow concepts. § Context-aware bindings: New WCF bindings specifically
for Workflow, which handle workflow instance manage-
Why Workflow Services? ment between clients and Workflow Services.
Workflow is useful for describing and executing long- § WorkflowServiceHost: A new ServiceHost type that
running and complex business processes. Typically, we see facilitates communication between WCF services and the
Workflow technology implemented as part of the middle- Workflow Runtime.

26 October 2008 | www.aspnetPRO.com


Figure 1: Workflow Service templates.
Figure 3: State machine Workflow Service template results.

For a Workflow developer less familiar with WCF, it might


seem daunting to figure out how to create a service con- Note: Visit msdn.microsoft.com/en-us/library/bb552363.aspx
tract, select bindings and configure endpoints, configure and msdn.microsoft.com/en-us/library/bb552364.aspx for more
the ReceiveActivity and SendActivity accordingly, and information about the test tools.
initialize the correct ServiceHost type. Fortunately, there
are two Visual Studio templates to simplify this process: For sequential workflows, the ReceiveActivity is the first
Sequential Workflow Service Library and State Machine activity in the workflow (as shown in Figure 2). For state
Workflow Service Library (see Figure 1). These templates machine workflows, the ReceiveActivity is the first activ-
are only shown if you select .NET Framework 3.5 from the ity contained within an event-driven activity (as shown in
Add New Project list. Figure 3). Both sample workflows created by the template
support clients calling a WCF service operation to initialize
Each template creates a new class library project with a the workflow, because the ReceiveActivity is configured to
sample workflow (sequential or state machine) that has been support workflow initialization.
configured as a Workflow Service as follows:
§ Each workflow starts with a ReceiveActivity (shown in It is still possible to create Workflow Services without the help
Figures 2 and 3). of a Workflow Service template. You can add new sequential or
§ The ReceiveActivity is associated with a service opera- state machine workflows to a class library project and manu-
tion from a sample WCF service contract. When clients ally add the ReceiveActivity, create the WCF service contract
call the operation via proxy, that particular Receive- using dialogs provided, and add the required WCF configura-
Activity is executed. tion settings for the Workflow Service endpoint.
§ The class library includes an app.config file with a
sample <system.serviceModel> configuration for the ReceiveActivity
Workflow Service. The most common use for Workflow Services is to expose a
§ The binding used for the Workflow Service endpoint workflow as a WCF service. The main benefit to the devel-
is WSHttpContextBinding, one of the context-aware oper is that they no longer have to manually initialize the
bindings. Workflow Runtime or workflow instance from a WCF service
operation. Instead, the Workflow Service directly exposes a
Essentially, the template generates a project with the neces- WCF service operation via ReceiveActivity. This activity rep-
sary assembly references, a sample Workflow Service, and resents the implementation of a WCF service operation.
the required configuration and set up so you can execute it.
To test the service, the class library is set up to use the two Consider the Workflow Service shown in Figure 4. This Work-
WCF test tools released flow Service exposes three ReceiveActivity instances imple-
with .NET Framework menting three WCF service operations: ReceiveOperation1,
3.5, WCF Service Host ReceiveOperation2, and ReceiveOperation3. ReceiveOpera-
(WcfSvcHost.exe) tion1 kicks off the workflow; ReceiveOperation2 and Receive-
and WCF Test Client Operation3 can be called only after the workflow has started.
(WcfTestClient.exe). Once a client calls one of the latter two operations, the work-
However, in this article flow is completed.
I’ll explain how to
create your own host Figure 2: Sequential Workflow Each ReceiveActivity has a number of properties that should
and client. Service template results. be initialized:

asp.netPRO | October 2008 27


Exploring WCF Web Services | Workflow Services

����������������
������ ������������������������������������������������������������������

�����������������

������� ����� �������� �������������


����������������������������������������
����������������������������������
����������������������������������������
���������������������������
�������������������������������
��������������������������������������
�����������
������������������������������������������
���������������������������������������
��������������������� ��������������
�������������������������������������������
�������������������������

Figure 4: A Workflow Service with multiple ReceiveActivity instances.

§ ServiceOperationInfo: Indicates the service operation implemented by


ReceiveActivity. This is set through the Choose Operation dialog box.
§ CanCreateInstance: Indicates if the operation can be called to initialize the
workflow instance. If not, the workflow must already be initialized before
ReceiveActivity can accept calls.
§ (ReturnValue): Associates the ReceiveActivity return value with a field or
��������
����������� property of the workflow. Developers can set this field or property of the
���������
����������� workflow to provide a return from the service operation.
������� § FaultMessage: Associates the ReceiveActivity fault message with a field or
������������
property of the workflow. Developers can set this value to return a fault from
����������
�����
��� the service operation. The client receives this as a FaultException.
�����������
���������� ������ § [parameters]: These are dynamically generated properties based on the param-
����� eters to the service operation used to associate the parameter with a field or
�����������
property of the workflow so that developers have access to these parameters
throughout the ReceiveActivity sequence to implement service operation logic.
��������������������
�������������� ������������
Figure 5 illustrates the property values of the first ReceiveActivity instance.
�����������������������������������
��������������������������������������� Workflow-first Services
����������������������������������������
����������� The Choose Operation dialog box shown in Figure 6 is used to set the
ServiceOperationInfo property. From this dialog box you can either import an existing
��������������������������������������
�������������������������������������� service contract (Import) and select one of its operations, or define a contract for the
������������������� Workflow Service (Add Contract) and an operation (Add Operation) for the specific
���������������������������������������� ReceiveActivity instance being configured. A subsequent ReceiveActivity instance can
���������������������������������� select the same contract and define addi-
���������������������������������������� tional operations. Workflow-first services
������������������������������������ imply that the WCF service contract does
����������������������������������� not exist until the Workflow Service is
���������������������������������������� created. While designing the workflow,
������������� one or more service contracts can be
���������������������� defined with operations associated with
���������������������������� ReceiveActivity instances. Typically,
you’ll create a single service contract (as
�������������� shown in Figure 5) for the Workflow Ser- Figure 5: ReceiveActivity properties for
����������������� vice, with as many operations as Receive- ReceiveOperation1.

28 October 2008 | www.aspnetPRO.com


������� ����
����������������� ��������
��� ��������������������

�������������������������������������������������������
���������� �����������������������

���������・�����������������������・���������������� �����・�������� ��������������


��������������� ��������������� ��������������������������

��������������������������������������������������������������������������������
Exploring WCF Web Services | Workflow Services

Workflow Service Context


Context-aware bindings facilitate passing the workflow
instance identifier in message headers between client and
service. When the first ReceiveActivity is called, the following
<Context> header is included in the response:

<Context u:Id="_4" xmlns="http://schemas.microsoft.com/


ws/2006/05/context">
<Property name="instanceId">0cb1d8a4-4484-4d19-b33e-
a3f7bdb856c6</Property>
</Context>

Because the client channel is configured to use the same


context-aware binding, the client channel is responsible
for caching this instanceId element for subsequent calls to
the Workflow Service. The same header is sent for all calls
from the same proxy instance to correlate the workflow
instance at the server.

Should the client channel be faulted, a new proxy can be gen-


erated and initialized with the same instanceId. First, save the
instanceId by retrieving its value through the context manager:
Figure 6: The Choose Operation dialog box with a workflow-first
service contract.
IContextManager ctxManager =
Activity instances. Figure 6 illustrates a service contract named m_proxy.InnerChannel.GetProperty<IContextManager>;
IDictionary<string, string> ctx = ctxManager.GetContext;
IWFService with three service operations defined for the Work- m_instanceId = ctx["instanceId"];
flow Service using the workflow-first approach.
If a new proxy is created and it is expected that the same
Note: One drawback to creating workflow-first services is lack workflow instance be used, create a new context with this
of control over service contract properties, such as the target value and assign it to the client channel:
namespace. I recommend importing a service contract created
specifically for the Workflow Service to overcome this limitation. m_proxy = new WinClient.localhost.WFServiceClient();

IContextManager ctxManager =
Workflow Service Configuration m_proxy.InnerChannel.GetProperty<IContextManager>();
Once the Workflow Service design is complete, and service IDictionary<string, string> ctx =
contracts and operations are defined and associated with new Dictionary<string, string>();
ctx.Add("instanceId", this.m_instanceId);
ReceiveActivity instances, it’s time to think about Workflow
Service configuration. Because a Workflow Service is imple- ctxManager.SetContext(ctx);
mented as a WCF service, each service contract must have
at least one service endpoint defined so clients can com- Note: If the Workflow Service is configured to use Workflow
municate with the service. This is done with classic WCF Persistence Services, the workflow instance state can be
configuration settings — with the exception that it requires reloaded from the database. This makes it possible to sur-
the use of a special context-aware binding. The following vive service channel faults and machine restarts.
example illustrates a Workflow Service endpoint for the con-
tract defined in Figure 6 — using WSHttpContextBinding: ReceiveActivity Execution
The sequence contained within a ReceiveActivity is executed
<service name="SequentialWFService.WFService"> synchronously as part of the WCF service operation. Param-
<endpoint address="http://localhost:8000/WFService" eters passed to the operation can be used by the activities
binding="wsHttpContextBinding"
contract="IWFService"> in the sequence, and before the sequence ends the activity’s
</endpoint> return value or FaultMessage should be set. Activities that
</service> follow a ReceiveActivity in the workflow are executed
asynchronously to the client (because a response will have
There are three context-aware bindings introduced with .NET already been sent back as the ReceiveActivity terminates).
Framework 3.5: BasicHttpContextBinding, WSHttpContext-
Binding, and NetTcpContextBinding. Each binding includes a For the Workflow Service defined in Figure 4, the CodeActivity
context binding element to enable communication between executes before sending a response to the client. The following
clients and a specific workflow instance. code inside the CodeActivity sets the return value:

30 October 2008 | www.aspnetPRO.com


����� ������ �������������������������
��� ��������������������

��������������������
���������� ������������������������

���������・�����������������������・���������������� �����・�������� ��������������


��������������� ��������������� ��������������������������

��������������������������������������������������������������������������������
Exploring WCF Web Services | Workflow Services

this.ReceiveOperation1Return = "ReceiveOperation1 called"; call out to WCF service operations without the hassle of
this.ReceiveOperation1Fault = null; prior techniques.

If an exception occurs and the workflow should be terminated, Using SendActivity, a Workflow Service can be config-
a fault can be thrown by initializing the FaultMessage property ured to call a particular WCF service contract by simply
through its bound field: providing the service contract metadata, indicating the
operation to call, binding parameters to workflow fields
this.ReceiveOperation1Fault = or properties, and providing a configuration for the cli-
new FaultException("ReceiveOperation1 has faulted."); ent proxy. The proxy is automatically generated based on
the information provided to the SendActivity, so it is not
Activities that follow a ReceiveActivity continue to execute necessary to write code to call the service unless you are
on the same thread as the ReceiveActivity — although a customizing the call to provide a dynamic address or spe-
response has already been sent to the client. cific security settings.

Note: Because activities placed within a ReceiveActivity are Figure 7 illustrates the same Workflow Service from Figure
executed synchronously to the client, care should be taken that 4 (modified to add a call to a WCF service operation within
this sequence is not long running in order to avoid timeouts. each ReceiveActivity). Think of this as the Workflow Ser-
Only those activities that contribute directly to the operation vice coordinating downstream service calls according to a
response need be part of the ReceiveActivity — the rest can be business process.
executed asynchronously with the remainder of the workflow.
As with ReceiveActivity, developers can configure each
SendActivity SendActivity by setting its properties. The key properties to
So far I’ve focused on Workflow Services as exposing WCF initialize are:
service endpoints to clients so they can invoke operations § ServiceOperationInfo: Indicates the service operation to
implemented by ReceiveActivity instances. Another impor- be invoked when the SendActivity instance is executed.
tant feature of a Workflow Service is the ability to easily This is set through the Choose Operation dialog box.
§ EndpointName: A child of the ChannelToken property
that specifies the WCF client configuration section to use
����������������� for proxy initialization. This can be shared by several
���������������� SendActivity instances by using the same ChannelToken.
����������������� § (ReturnValue): Associates the SendActivity return value
with a field or property of the workflow. Developers can set

Do you love the FREE PDF version of asp.netPRO, but


want access to all the code, as well?

This is the perfect


complement to the
free asp.netPRO PDF.
Now get access to all
Premium Downloads
that accompany
feature articles. A
one-year online-
only subscription
to asp.netPRO
magazine is only
US$14.99.

To order your online subscription, please contact


Customer Service at customerservice@informant.com
and include your contact information:
•Name •E-mail
•Address •Daytime telephone number

We will then provide you your Customer Number so


you can set up your online account.
Microsoft, Visual Studio, Visual Basic, MSDN, and ASP.NET are registered trademarks or
trademarks of Microsoft Corportaion in the United States and/or other countries and are
used by ICG under license from owner, asp.netPRO and Informant are trademarks or
registered trademarks of Informant Communications Group, Inc. Figure 7: A Workflow Service calling out to downstream WCF
service operations.

32 October 2008 | www.aspnetPRO.com


�����������
����������� ������������������
��� ��������������������

���������������������
���������� ���������������������������

���������・�����������������������・���������������� �����・�������� ��������������


��������������� ��������������� ��������������������������

��������������������������������������������������������������������������������
Exploring WCF Web Services | Workflow Services

this field or property of the workflow to share the return


from the service operation with the rest of the workflow.
§ [parameters]: These are dynamically generated proper-
ties based on the parameters to the service operation used
to associate the parameter with a field or property of the
workflow. This removes the need for code to initialize
parameters passed to the service operation.

Figure 8 illustrates
the property values of
the first SendActivity
instance.

To configure each
SendActivity requires
access to the service
Figure 9: Selecting a service contract to be used for SendActivity
contract and any instances.
custom data types Figure 8: SendActivity properties for
Operation1.
relied upon by that enough to reflect the workflow definition for this contract
contract. The easiest way to gain access to this is to either (because it is not statically defined).
generate a proxy, or, if you own both projects, you can share
a metadata assembly between the Workflow Service project To host Workflow Services in IIS or WAS, use the Workflow-
and the service project(s). Once this metadata is available to ServiceHostFactory in the .svc declaration (full name required):
the project you can select the service contract and operation
to associate with a SendActivity instance. After importing the <%@ ServiceHost Service="SequentialWFService.
service contract (see Figure 9) the same Choose Operation WFService" Factory="System.ServiceModel.Activation.
WorkflowServiceHostFactory" %>
dialog box from Figure 6 is presented to select the operation
for the SendActivity being configured.
Next Up: Workflow Services and Security
SendActivity instances also require access to a <client> In this article I introduced the Workflow Service, explained how
configuration section specified in the EndpointName prop- to set up ReceiveActivity and SendActivity, and explained how
erty. This configuration, which is usually created through the hosting model ties it all together. I have purposely left out
proxy generation, must be part of the host process configu- security features for Workflow Services as that topic requires an
ration file. To set the address of the service to be called by a article of its own. So, stay tuned to the next issue for the contin-
SendActivity instance, set the CustomAddress property. uation of this discussion of Workflow Services as I explain your
options for securing ReceiveActivity and SendActivity. </>
WorkflowServiceHost
WorkflowServiceHost is an extension to ServiceHost (the type Download the samples for this article from www.dasblonde.net/
responsible for initializing WCF communication channels at downloads/aspprooct08.zip.
the service). WorkflowServiceHost adds functionality to facili-
tate communication between WCF and Workflow. When a
request is received at a ReceiveActivity, the WorkflowService-
Host ensures the Workflow Runtime is initialized, initializes a Michele Leroux Bustamante is Chief Architect of IDesign Inc., Microsoft
new workflow instance if necessary (and if supported by the Regional Director for San Diego, and Microsoft MVP for Connected
ReceiveActivity), then handles activating the workflow. For Systems. At IDesign Michele provides training, mentoring, and high-
SendActivity instances, the WorkflowServiceHost constructs a end architecture consulting services focusing on Web services, scalable
client channel (or proxy) to call the specified service operation. and secure architecture design for .NET, federated security scenarios,
Web services, interoperability, and globalization architecture. She is
To host a Workflow Service, construct the WorkflowService- a member of the International .NET Speakers Association (INETA),
Host as follows: a frequent conference presenter, conference chair for SD West, and is
frequently published in several major technology journals. Michele
WorkflowServiceHost hostWFService = new also is on the board of directors for IASA (International Association
WorkflowServiceHost(typeof(SequentialWFService.WFService)); of Software Architects), and a Program Advisor to UCSD Extension.
hostWFService.Open();
Her latest book is Learning WCF (O’Reilly, 2007); visit her book blog
If the workflow-first approach was used to generate at www.thatindigogirl.com. Reach her at mlb@idesign.net, or visit
the WCF contract, the WorkflowServiceHost is smart www.idesign.net and her main blog at www.dasblonde.net.

34 October 2008 | www.aspnetPRO.com


������������ ����������
�������� ������������������
��� ��������������������

�������������������������������
���������� �����������������������

���������・�����������������������・���������������� �����・�������� ��������������


��������������� ��������������� ��������������������������

��������������������������������������������������������������������������������
a s p: F ea t u re
LANGUAGES: C# | VB.NET § ASP.NET VERSIONS: 3.5
§ By Emad Ibrahim

Convention Over
Configuration
Creating Applications Using ASP.NET MVC,
jQuery, and AJAX: Part II

A
s is the nature of working with bleeding-edge Let’s create the view by adding a new MVC View Content
“preview” technology, you are bound to bleed Page and using the Site.Master page in the Views | Shared
folder as the master. Run the project (Ctrl+F5) and navigate
once in a while. A lot has changed since Part to http://localhost:9055/listing/new (you should get a blank
I of this article was written. Preview 4 of ASP.NET MVC content page). We need to collect a title, description, and
was released and now we have to change some of our image on this page, so let’s add all the necessary controls
and a Submit button. The HTML is shown in Figure 2; the
code. The code changes are minor, but the new project form is shown in Figure 3.
template includes views and code to log in, register, and
log out. Although these pages don’t use AJAX, it would When the user clicks the Submit button, we want to
perform some basic validation on the client (JavaScript),
be easy to AJAX-enable them. For the sake of simplic- submit the request using AJAX to create the listing, then
ity, I am going to start with a new project using the new upload the image.
template (see end of article for download details).
<Authorize()> _
Public Function [New]() As ActionResult
Return View()
Let’s say we are building a classifieds Web site similar to
End Function
craigslist. The first thing we’ll do is enable the user to list
an item for sale. A listing is made up of a title, description, Figure 1: Controller action to render the new listing view.
and, optionally, an image. First, let’s create a new control-
ler named ListingController and add a “New” action. This <fieldset>
action only needs to render the view for creating a new <div class="label">Title <span class="validation"
listing (see Figure 1). id="valTitle"></span></div>
<%=Html.TextBox("txtTitle", New With {.style =
"width:300px"})%>
Notice that we don’t tell it which view to render; instead, <div class="label">Description <span class="validation"
it will automatically look for the view with the same id="valDescription"></span></div>
<%= Html.TextArea("txtDescription","",8,50) %>
name as the action (“new”). It will look for new.aspx or <div class="label">Images <span class="validation"
new.ascx in the Views | Listing folder, then it will look id="valImage"></span></div>
in the Views | Shared folder. Alternatively, you could call <form enctype="multipart/form-data" method="post"
name="formImage" id="formImage">
View(“new”). Also note the Authorize attribute; this is <input type="file" id="fileImage" name="fileImage"/>
new to Preview 4 and it’s the quickest way to authorize </form><br />
an action. By adding this attribute, only a logged-in user </fieldset>
<p><input type="button" id="btnSubmit" name="btnSubmit"
will be allowed to run it. If you are not logged in, you’ll onclick="submit();" value="Submit" /> </p>
be directed to the log-in page. All this is done automati-
cally, starting with the Preview 4 version. Figure 2: HTML for the create listing view.

36 October 2008 | www.aspnetPRO.com


Validation is pretty
function isValid()
straightforward; title
{
and description are $("span.validation").hide();
required, and if an var isvalid = true;
if (!imageIsValid()) {
image is selected, it
$("#valImage").html("Invalid image. Use jpg.").show();
should have a jpg or var isvalid = false;
jpeg extension. The }

validation method
if($("#txtTitle").val().length == 0) {
is shown in Figure 4 $("#valTitle").html("* Title is required").show();
(the image validation var isvalid = false;
Figure 3: The create new list page. }
method is shown in
Figure 5); note the use if($("#txtDescription").val().length == 0) {
of the jQuery methods: $("#valDescription").html("* Description is
required").show();
§ val to get the value of the element
var isvalid = false;
§ hide to hide the matching elements }
§ html(“some html string”) to set the html of the element return isvalid;
}
§ show to display the matching elements
Figure 4: JavaScript to validate a page.
As discussed in Part I, we are using jQuery to select and
manipulate DOM elements. We first hide all spans with line will select the element named “aDiv”, change its HTML
a validation class, then check the title, description, and content to “hello world”, then hide it slowly, then show it
image and display the appropriate error message. If every- fast. Each method basically returns an object that the follow-
thing checks out, we return true. Note the method chaining ing method acts upon to create a chain of method calls.
that makes jQuery very powerful and easy to use. Chaining
allows you to do things like $(“aDiv”).html(“hello world”).- Now that the form is valid, we need to submit it (see Figure
hide(“slow”).show(“fast”). This seemingly simple JavaScript 6). We’ll submit the form to /listing/create, so we’ll need

ORDER Your Copy Now for ONLY US$39.99*


2007 asp.netPRO Complete Works CD-ROM
• More than 700 technical articles, as well as product reviews, book
reviews, and other content appearing in asp.netPRO and asp.netNOW!
• Supporting code and sample files that you can use in your
applications immediately.
• Easily searchable CD-ROM — find what you need, when you need it.
• FREE shipping!*

Visit us online at
Co-Sponsored by: www.aspnetPRO.com/cd
or Call Toll-free in the U.S.
(800) 884-6367
Outside the U.S. dial (916) 379-0609

* Free Shipping and Handling to US and Canada! All other countries US$10.00 for shipping and handling. Applicable sales tax will be added for California residents. Payment must
be in US dollars drawn on a US bank. Your purchase may be tax deductible if used for business purposes. Please check with your tax advisor.

Microsoft and ASP.NET are registered trademarks or trademarks of Microsoft Corporation in the United States and/or other countries
and are used by ICG under license from owner. asp.netPRO and Informant are trademarks or registered trademarks of Informant
Communications Group, Inc.

asp.netPRO | October 2008 37


asp:Feature | Convention Over Configuration

call it DB. You


function imageIsValid()
can simply drag
{
var filename = $("#fileImage").val().toLowerCase(); the two tables
if (filename.length == 0) return true; created above
if ((filename.lastIndexOf(".jpg") == -1) &&
from the Server
(filename.lastIndexOf(".jpeg") == -1)) Figure 8: The LINQ to SQL class diagram.
return false; Explorer pane
return true; into the design
}
surface. The model is shown in Figure 8.
Figure 5: JavaScript to validate a file extension.
This looks similar to the database diagram — with one
minor exception: the entity names are singular. Listing and
function submit()
{ ListingImage are now classes in your project that model an
if (!isValid()) return; entity. Let’s get back to creating the Create action using the
var title = $("#txtTitle").val();
newly created model entities (see Figure 9).
var description = $("#txtDescription").val();
$("#btnSubmit").attr("disabled","disabled");
//create the listing This method creates a record in the database using the
$.ajax({
type: "POST",
model created above and then returns the Id of the record
dataType: "json", in a JSON object. There are a few things to note here. First,
url: "/listing/create", the return type is JsonResult, which returns a JSON object
data: {title : title,
description : description
to the browser. The returned JSON object is an anonymous
}, object, the Json method is part of the MVC Framework and
success: function(result) { knows how to serialize the anonymous object back to the
if (result.success){
if ($("#fileImage").val().length > 0 ) { browser. Also note that the action is decorated with the
$("#formImage").attr("action", Authorize attribute, as previously explained.
"/listing/upload/" + result.id);
$("#formImage").submit();
} else { JSON stands for JavaScript Object Notation. As defined on
window.location = "/listing/list"; www.json.org, it “... is a lightweight data-interchange format.
}
}else {
It is easy for humans to read and write.”
alert("Failed to create listing");
} Now that the record is created, the submit method shown
},
error: function(error) { in Figure 6 will submit the form containing the image to the
/listing/upload/Id. So let’s create the upload action to save
}
the file and create the database record (see Figure 10).
});
$("#btnSubmit").removeAttr("disabled");
} In a real-world application you’ll probably have a service
layer abstracting the model, but because this article is not
Figure 6: JavaScript to submit the form.
about data layer design patterns, and for the sake of simplic-
a new action in the listing controller named Create. This ity, we are directly using the SQL to Entity classes.
action will create the record in the database and then return
a JSON object, which includes the Id of the inserted record.
If the creation action works, we’ll then upload the file using
<Authorize()> _
the Id sent back to us. Public Function Create(ByVal title As String, ByVal description
As String) As JsonResult
Model Interruption Try
Dim db = New DB
Before we can write code to create the listing, let’s take a Dim listing = New Listing With { _
quick break to create the model. We need a table for the list- .Title = title, _
ing and another for the image. Although we are only adding .Description = description, _
.Username = User.Identity.Name.ToLower _
one image, it is reasonable to assume that we’ll be adding }
the ability to post multiple images in the near future; the db.Listings.InsertOnSubmit(listing)
database diagram is shown in Figure 7. db.SubmitChanges()
Return Json(New With {.success = True, .id = listing.Id})
Catch ex As Exception
We’ll now cre- Return Json(New With {.success = False, _
ate a LINQ to .message = ex.Message})
End Try
SQL model in End Function
the Models
folder and Figure 7: The database diagram. Figure 9: The controller action to create a new listing.

38 October 2008 | www.aspnetPRO.com


asp:Feature | Convention Over Configuration

<Authorize()> _ Public Class ListModel


Public Function Upload(ByVal id As Long) As ActionResult Public Items As List(Of Listing)
If (Request.Files.Count = 0) Then End Class
Return RedirectToAction("List")
End If Figure 14: A class representing a view model.
Dim db = New DB
If (db.Listings.Where(Function(l)
(l.Id = id)).Count = 1) Then
Public Function List() As ViewResult
Dim filename As String = UploadFile()
Dim model = New ListModel
Dim listingImage = New ListingImage With _
Dim db = New DB
{.ListingId = id, _
If User.Identity.IsAuthenticated Then
.Filename = filename}
model.Items = db.Listings.Where(Function(l) _
db.ListingImages.InsertOnSubmit(listingImage)
l.Username.ToLower = _
db.SubmitChanges()
User.Identity.Name.ToLower).Take(20).ToList
End If
Else
Return RedirectToAction("List")
model.Items = db.Listings.Take(20).ToList
End Function
End If
Return View(model)
Figure 10: Controller action to upload a file. End Function

Figure 15: The controller action to render the list of listings view.

$(document).ready(function() {
$("div.listingRow").hover(
function(){$(this).css("backgroundColor", "yellow");},
Figure 11: A grid displaying the listings. function(){$(this).css("backgroundColor", "");}
);
});
<% For Each item In ViewData.Model.Items%>
<div id="div<%= item.Id %>" class="listingRow">
Figure 16: The JavaScript function to initialize the page.
<span>
<%=Html.ActionLink(Of ListingController)(Function(c)
c.Edit(item.Id), "edit")%> To render a view with a strongly typed model, call
<a href="#" onclick="deleteItem('<%= item.Id %>') View(“list”, model) instead of View(“list”). If the view name
">delete</a> </span>
<%= item.Title%>
is the same as the action, you can simply call View(model).
</div> To see it how it all works together, take a look at the List
<% Next%> action in Figure 15.

Figure 12: Markup to render the listings grid.


If you haven’t fallen in love with jQuery yet, take a look
at Figure 16 to see how we change the background of the
After a successful post, we redirect the user to the /listing/ row to yellow when hovering over it (as shown in Figure
list page, which will display all the items listed by the user. 11). As mentioned in Part I, the “$” is a shorthand to
We need to repeat the same steps performed above: create the jQuery API and the $(document).ready method runs
a List action in the controller and a list.aspx view. When all as soon as the DOM is ready, but before the content is
is done, we’ll end up with the view shown in Figure 11. The displayed, so it’s the perfect place to apply styles and
List view (list.aspx) markup is shown in Figure 12. add event listeners. The code in Figure 16 adds a jQuery
hover event listener to any div with the listingRow class.
In the markup, we loop through the list of items and The hover event takes two functions as arguments: one
display links and a title for each one. One important dif- runs when the mouse is over the element and another
ference between other views we’ve created is that the when the mouse leaves. We set the CSS background color
ViewData.Model is strongly typed and has full IntelliSense, property to yellow when the mouse is over the row and
as shown in Figure 13. This is because we changed the code- clear it when the mouse leaves. How many lines of code
behind file to inherit ViewPage<ListingController.ListModel> would you have to write to accomplish the same task
instead of ViewPage. So the class definition is the public par- without jQuery?
tial class List : ViewPage
<ListingController.ListModel>. Let’s add some more jQuery magic to the grid. We want
As you can see from this code, to delete the item when the user clicks the delete link, but
the ListModel class is defined in we want to use AJAX and also fade out the row on a suc-
the ListingController class (see cessful deletion. The first thing we need to do is prompt
Figure 14). Currently, this class the user to confirm the delete action. Let’s replace the
only contains an Items property Figure 13: IntelliSense on a Html.ActionLink line with <a href=“#” onclick=
of type List<Listing>. strongly typed view model. “deleteItem(‘<%=item.Id %>’)”>delete</a> and

40 October 2008 | www.aspnetPRO.com


asp:Feature | Convention Over Configuration

function deleteItem(id) <% For Each item In ViewData.Model.Items%>


<%= Html.RenderUserControl("~/views/listing/
{ _listingDisplay.ascx", item) %>
if(!confirm("Are you sure you want to delete this listing?")) <% Next%>
return;
Figure 18: Refactored list view.
$.ajax({
type: "POST",
dataType: "json",
url: "/listing/delete/" + id, <div id="div<%= ViewData.Model.Id %>" class="listingRow">
success: function(result) { <span>
if (result.success){ <%=Html.ActionLink(Of ListingController)(Function(c)
$("#div" + id) .css("backgroundColor", "red").slideUp(1000); c.Edit(ViewData.Model.Id), "edit")%>
}else { <a href="#" onclick="deleteItem('<%=ViewData.Model.Id %>')
alert("Failed to delete listing"); ">delete</a> </span>
} <%= ViewData.Model.Title%>
}, </div>
error: function(error) {
alert("An error occurred while deleting the listing"); Figure 19: User control to display a listing.
}
});
}
Keep in mind that this user control code requires the page
reference for the JavaScript file containing the deleteItem
Figure 17: The JavaScript function to delete a listing. method — otherwise, you will get a script error. In a pro-
duction application, you would refactor your scripts into
create the deleteItem function (see Figure 17). The trick logical script files that get referenced where needed.
is in the line $(“#div” + id) .css(“backgroundColor”,
“red”).slideUp(1000); which changes to red the background Conclusion
color of the row being deleted and hides it using a slide up We’ve looked at strongly typed view pages and view user
animation. Trying different values, experiment with slide- controls using generics. We’ve seen how data is passed from
Down, fadeOut, and hide. The 1000 tells it to perform the the controller to the view. We talked to the server using
animation over a duration of 1000 milliseconds (1 second). AJAX and enhanced the usability and user experience by
adding visual cues and animation.
User Controls
One more thing we should talk about is user controls. User jQuery is a very simple, powerful, and extensible Java-
controls make your code more useable and maintainable. Script library that will get you up and running in no time.
For example, we can easily refactor the listing display into It’s difficult to cover the entire library in one article. Hope-
its own user control, which will allow us to reuse it in other fully this whets your appetite enough to give it a try. You
views such as a search results page. It is very easy to create can get more information at www.jquery.com, as well as
a user control in ASP.NET MVC. Right-click on the Views | download a ton of open source extensions that let you do
Listing folder and click Add | New Item, then select Web | a multitude of things, from creating tabs, to popup mes-
MVC | MVC View User Control and name it _ListingDisplay sages, to image effects, etc. We also looked at some of the
(it is a convention to prefix partial pages [user controls] new features of the MVC Framework introduced in the
with an underscore). Switch to the user code and change Preview 4 release. You can download the preview from
the class definition to inherit from the generic ViewUser- www.codeplex.com/aspnet. </>
Control<Models.Listing>. This means that the user control
expects the data passed to it to be of type Listing, just as Source code accompanying this article is available for down-
we did with the List view earlier. All we have to do is cut load to asp.netPRO subscribers at www.aspnetPRO.com.
and paste the markup inside the For Each loop in Figure 12
into the user control and replace any reference to “item”
with “ViewData.Model”. Remember: The ViewData.Model is
strongly typed as “Listing”. Then replace the code inside the
For Each loop in list.aspx page with one line: <%= Html.-
RenderUserControl(“~/views/listing/_listingDisplay.ascx”, Emad Ibrahim, MCSD, has been a professional developer for nine
item) %>. The RenderUserControl helper method, as the years and has worked with .NET since the first beta. He has held
name suggests, renders a user control. Note that we are titles ranging from architect to senior developer to consultant. He
passing “item” to the RenderUserControl method; “item” is quit his job with Avanade to start playing around with new stuff and
of type Listing and will be mapped to the ViewData.Model catch up with technology. Since then he created an open source twitter
of the user control — exactly what it expects. The modified clone at yonkly.com. He also is an active blogger and mostly blogs
list.aspx page is shown in Figure 18 and the _ListingDisplay about software development and technology-related stuff. His blog is
user control markup is shown in Figure 19. at www.emadibrahim.com.

42 October 2008 | www.aspnetPRO.com


C l o s er L o ok § By Anand Narayanaswamy
Rating: 
Web Site: www.devexpress.com
Price: US$1,999.99

DXperience Universal
How Suite It Is

M
any companies have released a range of nents, and allows developers to build and maintain business
products rolled into a .NET suite for applications with ease, thereby drastically reducing time to
develop solutions for end users.
Windows and Web development. These
products not only simplify programming tasks, they The ASP.NET components are bundled into various suites:
also provide components that can be used to deliver ASPxGridView, ASPxperience, ASPxScheduler, ASPxSpell,
and ASPxHTML Editor. The ASPxperience suite includes a
cutting-edge interfaces and instantly modify the look set of 20 controls. A notable feature is the inclusion of a
and feel of an entire application. DXperience Universal cloud/tag control, which I hope will be useful during the
from Developer Express (DevExpress) is one such prod- development of a knowledge base or a content manage-
ment application.
uct (www.devexpress.com/Products/NET/DXperience/
editionUniversal.xml). DXperience includes a plethora DXperience ships with a new rich text editor for ASP.NET
of components for developing highly powerful Windows 2.0, built entirely with the ASPxperience Suite with the
integration of ASPxUploadControl for embedding images.
and ASP.NET applications. I reviewed the first build of It includes the newly released AJAX-based ASPxTreeList
the 2008 series, which contains tons of feature enhance- control, which has numerous performance optimization
ments, focusing mainly on the components meant for features. It enables developers to render paged and hierar-
chical TreeLists, along with many other options (see Figure
ASP.NET applications. 1). The data loads quickly because of the powerful built-in
AJAX capabilities.
I tested the product on a machine loaded with Windows XP
Service Pack 2 with 512 MB of RAM. The installation pack- The latest build includes improve-
age was around 150 MB; I downloaded it within 20 minutes ments for the ASPxGridView,
using a broadband connection. DevExpress deserves special ASPxPivotGrid, and ASPxScheduler
credit as they have created a user-friendly installer with suites, in addition to several suites
easy to understand instructions. It automatically creates the oriented for the development of
required items on the Start menu and adds the controls to Windows-based applications. A
the Visual Studio Toolbox. complete list of all the new features
is located at www.devexpress.com/
DXperience ships with numerous controls that can be used Products/NET/DXperience/
not only to develop Windows and Web-based projects, but WhatsNew2008v1. Moreover,
also to include libraries for developing applications that DevExpress has made available
make use of reports and charts in addition to IDE produc- for the entire ASP.NET product
tivity and ORM tools — CodeRush and eXpressPersistent line more than 10 popular theme
Objects, which I hope will be useful for advanced develop- styles, which I feel is a big bonus
ers. DevExpress also provides a product named eXpressApp for developers, as they can develop Figure 1: Easily select
Framework (www.devexpress.com/xaf) that leverages and applications with a uniform an item using the
exploits their rich set of presentation and reporting compo- look and feel. TreeList control.

44 October 2008 | www.aspnetPRO.com


I’m a big fan of the charts (www.devexpress.com/Products/NET/WinForms/
GridView control, so I XtraCharts) and reports (www.devexpress.com/Products/
was eager to test the NET/WinForms/XtraReports) into ASP.NET applications.
ASPxGridView control
using Visual Studio The chart control includes a wizard you can use to custom-
2005. I was able to ize the look and feel. For guidance purposes, I would sug-
populate the control gest DevExpress include the progress of the wizard (such
with the data using the as Step 4 of 15) at the top of the window. A key feature of
various options from the XtraCharts is its ability to render different types of 2D and
smart tag and custom- Figure 2: The ASPxGridView control 3D charts, such as Bar, Gantt, Point, Line, Area, Pie, Radar,
before selecting the Header Filter
ize the look and feel feature.
Polar, Candle Stick, Stock, and Manhattan Bar. Moreover,
of it by changing the it provides full support for True OpenGL Rendering, Full
theme without a single line Anti-Aliasing, Perspective Projection, Gradient Fill, and
of code. Developers should Texture and Transparency. An interesting point to note is
learn the use of the various that the chart demo application included with the product
properties included with provides a snapshot of each and every chart view, with
each of the controls so they Figure 3: The ASPxGridView the required explanation and customization features (see
control after selecting the
can make efficient use of Figure 4). This should help developers in making decisions
Header Filter feature.
them easily. during the development stage.

The column headers can now be displayed as filter drop- XtraReports comes with a full-blown designer, as well as the
down buttons with the help of the Header Filter feature ability to create subreports. It seamlessly integrates with Visual
included with the current build. This feature enables a user Studio, with support for Mail Merge, Master-Detail, Data Filter-
to dynamically filter a column based on a unique value ing, and Grouping. It ships with lots of native controls, such
(see Figures 2 and 3). It also reduces the search time for as Label, Line, BarCode, CheckBox, PageInfo, Panel, Picture-
locating specific data from the Grid for large databases. I Box, PageBreak, Table, and ZipCode, along with an enhanced
was amazed to see that I was able to implement this func- RichText control and Report Explorer. XtraReports enables you
tionality directly from the Properties window. to integrate your reporting applications with the XtraReports
Toolbar from within the Visual Studio IDE, as well as preview
There is absolutely no need for developers to write a sin- the generated report before its distribution. A notable feature is
gle line of code for performing standard tasks. However, that it ships with a report wizard that guides you in the report-
coding may be required for advanced projects (depending creation activities.
on the nature of the application being developed). The “DXperience Universal” continued on page 47
next component in my pipeline was Menus. I was able to
design a simple menu by making use
of the various styles. A key feature
is that menu items and correspond-
ing URLs can be directly added from
within the smart tag, and the required
changes are reflected immediately.

I also tested a few other controls, and


was able to work with them very easily.
DevExpress’ main goal was to simplify
programming time; they have achieved
this through the components included
in the DXperience suite.

And although my main objective was


to measure the performance of the
components designed for ASP.NET,
I also tested a few of the controls
oriented for Windows Forms; they
all worked like a charm. As men-
tioned, the product is bundled with
components designed for integrating Figure 4: Chart demo in action.

asp.netPRO | October 2008 45


B o o k Re p or t § By Dennis Hayes

ADO.NET 3.5 Cookbook

O
ne reason I often buy a book is because it solves rules. Chapter 8 has complete coverage of data binding in
a particular problem I am having writing an both Web Forms and Windows Forms. Chapter 9 covers XML
data, including schemas, XPath, and SQL Server XML data.
application; solving one problem in the middle of
a project can easily be worth the price of a book (which is Chapter 10 shows how to optimize data access in .NET
why I like the whole O’Reilly series of Cookbooks). with examples of executing multiple commands on a single
connection, bulk loading and copying, batch updates, and
working with large data from Oracle databases.
For example, let’s look at the first “recipe” in Bill Hamilton’s
ADO.NET 3.5 Cookbook, “Storing Connection Strings.” If Chapter 11 explains how to work with database metadata,
you are new to .NET database programming (and maybe including retrieving metadata, and information on columns
even if you are not so new), you need to know how to store (length, default types, etc.). It details how to retrieve a SQL
database connection strings. In .NET you have a number of Server query plan (I didn’t know you could do that with
options as to where to store connection strings. What are software). It shows how to create new databases and add
they, and which one is right for your situation? This recipe tables and relationships to a database. It continues with how
covers storing connection strings in the application, the reg- to enumerate different types of data providers (.NET, OLE
istry, Universal Data Link files (UDL), and custom files. This DB, ODBC, SQL), and closes by showing how to program-
section explains the advantages and disadvantages, security matically change SQL Server passwords.
ramifications, and ease of modifying each; it also provides
detailed instructions on how to use each of the preferred The final chapter covers CLR integration, which allows the
options. The book continues to do this for more than two use of .NET inside SQL Server, such as using C# or other
hundred recipes divided into twelve chapters. .NET-compatible languages to create stored procedures.
The book ends with an appendix that lists the changes in
The first chapter covers connecting to databases, including ADO.NET since version 1.0.
connecting to databases using Excel and text files, and how
to use connection pooling. Chapter 2 details working with This Cookbook has an incredible 900+ pages of short
disconnected data objects. Chapter 3 goes over retrieving examples showing how to perform specific tasks. If you are
data from databases, including hierarchical data; reading an experienced ADO.NET programmer, this book will pay
data from databases, text files, and Excel worksheets; and for itself many times over by speeding you through every-
querying using LINQ. Chapter 4 explains how to search day tasks. If you are learning ADO.NET, the best way is
and analyze data, including sorting, filtering, recursive by writing ADO.NET code — this book will keep you from
queries, and even how to access deleted rows (but only getting stuck by showing not only the how, but the why
before AcceptChanges is called). Chapter 5 covers adding of coding ADO.NET. Regardless of your skill level, this is a
and modifying data. book you cannot afford to be without. </>

Chapter 6 details copying and transferring data. It covers


moving data between data tables, as well as between data
tables, data sets, and data readers. It also explains how to ADO.NET 3.5 Cookbook
serialize and deserialize data. It shows how to export the Bill Hamilton
results of a query to a string or an array. As a bonus, it shows
Rating: 
how to read and write from and to legacy ADO databases. Publisher: O’Reilly
ISBN: 978-0-596-10140-4
Chapter 7 details maintaining database integrity using trans- Web Site: www.oreilly.com
Price: US$54.99
actions, checking for concurrency conflicts, resolving data
Page Count: 980
conflicts, and using column expressions to enforce business

46 October 2008 | www.aspnetPRO.com


Advertising Index DXperience Universal
(continued from page 45)
/n software ................................................................................ 41
Altova GmbH............................................................................. 11 DevExpress constantly provides updates and new products as
aspDotNetStoreFront.com........................................................ 21 and when a new technology/framework is released. At the
ASPOSE ...................................................................................... 7 time of this writing they were scheduled to release and show-
asp.netPRO ............................................................................... 32 case the beta of a new grid control for WPF and Silverlight,
asp.netPRO CD Works .............................................................. 37 which promises new features for these new platforms. With
ceTe Software.................................................. Inside Back Cover this new control, developers can use the grid to develop appli-
ComponentArt.......................................................................... 4-5 cations powered by Silverlight and/or WPF technology.
ComponentOne, LLC .................................. Outside Back Cover
DevConnections........................................................................ 17
DevExpress provides standard controls such as Button, Label,
Developer Express.................................................. 29, 31, 33, 35
TextBox, RadioButton, and many more, which enables you
DiscountASP ............................................................................. 39
to develop applications completely using the product without
dotNetVideos.net ...................................................................... 18
depending on the controls included with the .NET Framework.
dtSearch.................................................................................... 28
This enables you to develop applications with a uniform look
FarPoint Technologies ................................................................ 3
and feel. You also can develop and integrate your own themes
Infragistics ................................................... Inside Front Cover, 1
Syncfusion ................................................................................ 43 if you are an advanced developer.
Telerik ................................................................................... 24-25
Text Control ................................................................................. 9 I am very much impressed by the support provided By
DevExpress. They reply to all queries very systematically,
depending on the severity of the problem. In fact, they have
ASP.NET Crossword Puzzle (Answers) developed a dedicated support portal (www.devexpress.com/
(continued from page 6) Support/) that lists all the available options, including a com-
prehensive knowledge base, documentation, and online video
1
demonstrations presented by the support team and other
T
product team members. They also manage a blog, from which
H
2
M A
3
S T E R P A G E F I L E you can learn tips and tricks included with each product.
E S
S
4
O
5
S H O W M E S S A G E B O X
The entire product line is very extensive and it may take a
U I
6
H couple of days for a developer to become accustomed with it
7

8
T O
9 10
S E L E C T E D I T E M (depending on their skill level). Depending on the creativity
P A N E L I M
U R
11
X H T
12
M L L
and imagination, a developer can build any type of applica-
T
13
P R O X Y T A
14
B I R E A K P O I N T S tion, be it pure Windows-based word processing software or
C
15
O T I U
16
E
an ASP.NET-based online invoicing system. </>
A P R E C O M P I L A T I O N L X
C M H L I T
17 18 19
H E T R A C E D A T A S E T W Anand Narayanaswamy, a Microsoft Most Valuable Professional
E S N T E R
20
(MVP), works as an independent consultant based in Trivandrum,
S D I S P O S E D E X I
21
L O C A L S L N T T
India. Anand also works as chief technical editor for ASPAlliance.com.
22
G R E S O U R C E E M E He is the author of Community Server Quickly (www.packtpub.com/
23 R O
O D E D O M R R
C
community-server/book). He runs www.learnxpress.com,
S D
E www.dotnetalbum.com, www.csharpfaq.com, www.computerbook-
reviews.org, and www.devreviews.com. Find out more about him at
www.visualanand.net. He can be reached at visualanand@gmail.com.

asp.netPRO is published monthly by Informant Communications Group, Inc., 5105 Communications Group, Inc. asp.netPRO is a publication of Informant Communications
Florin-Perkins Road, Sacramento, California, 95826-4817. Basic one-year subscription Group, Inc. and is not sponsored by or affiliated with Microsoft Corporation. Microsoft is
rates: U.S. $34.99, Canada $44.99, all other countries $79.99, must be prepaid in U.S. not responsible in any way for the editorial policy or other contents of this publication.
dollars drawn on a U.S. bank. Printed in the USA. We welcome your comments and suggestions about the content of asp.netPRO, as
Postage paid at Elk Grove, CA and additional mailing offices. POSTMASTER: Send well as your commentary on the subject of ASP.NET development. We reserve the right
address changes to asp.netPRO, 5105 Florin-Perkins Road, Sacramento, California, to edit all submissions. Letters should include your name and address. Please direct all
95826-4817. Post International Publications Mail Product (Canadian Distribution) Sales letters to asp.netPRO, ATTN: Letters, 5105 Florin-Perkins Road, Sacramento, California,
Agreement No. 40028783. Subscription inquiries and orders should be directed to the 95826-4817. Letters may also be sent via e-mail to letters@aspnetPRO.com.
Circulation Department, asp.netPRO, 5105 Florin-Perkins Road, Sacramento, California, Informant is a registered trademark of Informant Communications Group, Inc., Elk
95826-4817, Phone 916-379-0609, Fax 916-379-0610. Code listings may be downloaded Grove, California. Microsoft and Visual Basic are trademarks of Microsoft Corporation
from the asp.netPRO Web site at www.aspnetPRO.com. and asp.netPRO is used by Informant Communications Group, Inc. under license from
Informant Communications Group, Inc. assumes no responsibility whatsoever for owner. Windows is a trademark of Microsoft Corporation. All other products men-
the uses made of any software code in this issue, whether modified or not. Informant tioned within are trademarks of their respective owners.
Communications Group, Inc. will not be liable for special, incidental, consequential, Microsoft, Visual Basic, Visual Studio, MSDN, ASP.NET, and the Visual Studio, .NET,
indirect, or other similar damages, even if we have been advised of the possibility of such Microsoft Office, and Visual Basic Logos are registered trademarks or trademarks of
damages. In no event will our liability for any damages to you or any other person ever Microsoft Corporation in the United States and/or other countries and are used by
exceed the price paid for your subscription to asp.netPRO, regardless of any form of the LICENSEE under license from owner. asp.netPRO, C# PRO, Informant, Microsoft Office
claim. Editorial contained within does not necessarily reflect the opinions of Informant Solutions Conference, and ASP.NET and XML Web Services Solutions Conference are
Communications Group, Inc. Informant Communications Group, Inc. assumes no respon- trademarks or registered trademarks of Informant Communications Group, Inc.
sibility for the products or services advertised within this publication. Writers interested in having works published in asp.netPRO may obtain a style guide
Copyright©2008 Informant Communications Group, Inc. All rights reserved. No part of by e-mailing David Riggs at driggs@informant.com. For direct mailings/e-mailings to
this publication may be reproduced in any way without the written consent of Informant our subscriber list please contact Rich Parker at rich@directmedia.com.

asp.netPRO | October 2008 47


B a c k D r a f t
§ By Jonathan Goodyear

Spreading the Word

U
nless you’ve been living in Antarctica for the lot bigger than the United States). Microsoft is doing a pretty
past year or so, you’ve undoubtedly heard of decent job of putting Silverlight applets on many of their
Web properties, but most of those don’t have broad appeal
Microsoft’s dynamic new cross-platform Web beyond software developers and business users. What
development and video streaming technology, Silverlight, surprises me greatly is that MSN Video (e.g., SoapBox) is
which is based on Windows Presentation Foundation still powered by Flash. In my opinion, Microsoft should be
pushing to re-deploy MSN Video powered by Silverlight as
(WPF). I’ve noted several times in this column that soon as possible. Even though Silverlight 2.0 is still in beta,
Silverlight stands to play an important role in the future if it can power NBCOlympics.com, I’m confident that MSN
of Web development. That is, if it catches on. Video won’t be any trouble.

An even bigger win would be if Microsoft could convince


What do I mean, “if it catches on”? We’re all on board, the big social network Web sites to utilize Silverlight
right? I agree that Microsoft is beginning to make great applets. Given Microsoft’s large ownership stake in Face-
strides in attracting Silverlight developers (much more book, I think that it would be the most logical target. A
so than for its big brother, WPF, but that’s a whole differ- few enterprising folks have created small Silverlight Face-
ent topic). Regardless of how compelling it is to us devel- book applications and games, which (if any of them catch
opers, though, Silverlight will only reach critical mass if on) could help tremendously on the Silverlight adoption
the runtime that is required to be installed on the client front. Mass adoption, however, will only come with the
goes mainstream. implementation of Silverlight-based banner advertise-
ments that appear site-wide.
Enter the Summer Olympics. In a brilliant move, Microsoft
and NBC teamed up to create NBCOlympics.com, a Web site Regardless of how Silverlight does among the masses, it will
that offers thousands of hours of Olympics video footage, likely gain appeal quickly in the controlled environments
available on-demand. All you need to do is download and of corporations who will immediately see the benefit of
install the Silverlight runtime. Perfect! As I write this, millions more powerful Web applications with frictionless deploy-
of users are installing Silverlight. We win! ment. With huge sites like YouTube still using Flash, though,
Microsoft has a very difficult task ahead of them when it
Well, not exactly. The big problem is that NBC only pur- comes to driving end-user adoption of Silverlight. Microsoft
chased the broadcast rights to the Olympics in the United always seems to have a few tricks up their sleeve, though,
States. So, they have been forced to restrict access to the so I never count them out. </>
NBCOlympics.com Web site to IP addresses originating in
the United States. So, aside from a few clever folks (names
omitted to protect the guilty) who are playing some VPN
tricks to gain access to the site from abroad, the big Silver-
light coming out party is pretty much restricted to those of Jonathan Goodyear is president of ASPSOFT (www.aspsoft.com), an
us who are States-side. Internet consulting firm based in Orlando, FL. Jonathan is Microsoft
Regional Director for Florida, an ASP.NET MVP, a Microsoft Certified
I’ve been accused in the past of being a bit of an ethno- Solution Developer (MCSD), and co-author of ASP.NET 2.0 MVP
centrist, but even I can see that Microsoft needs a break-out Hacks (Wrox). Jonathan also is a contributing editor for asp.netPRO.
application that has international visibility to push Silver- E-mail him at jon@aspsoft.com or through his angryCoder eZine at
light out to the rest of the world (which, as it turns out, is a www.angryCoder.com.

48 October 2008 | www.aspnetPRO.com


����������������������������������������������������

��������������� �����������������
���������������������������� �����������������
������������������ ����������������������������������������������������������������������������
����������������������������������������������������������
�����������������������������������������������������������������������������������������
����������������������������������
��������������������������������������
������������������������������ ������������������������������������������������
��������������������������������������������� ����������������������������������������������
���������������������������������������������� ������������������������������������
������������������������������������������ ����������������������������������������������������
�������������������������������������
�����������������������������������������
��������������������
�������������������������������
����������������������������������������������������
���������������������������������������������������
��������������������������������������������������������������

�������������������������������������
������������������������������������������������������������
���������������������������������������������������������
�������������������������������������������������
��������������������������������������������������

���������������������������������������������������������������������

������������������������������������������������������������������������������������������������������������������������
������������������������������������������������������������������������������������������������������������������
�����������������������������������������������������������������������������������������������������������������������
�����������������������������������������������������������������������
����������������������������������������������������
��������������������������������������������������������������
�����������������������������
� ���������������������������������������������������������������

� ��������������������������������������������������������

� ����������������������������������������������������
�����������������
� �����������������������������������������������
����������������������������
������ ��� �����������������������
������������� ����
� �����������������������������������������������������������������

����������������������������
������������������������� �������������������������
�������������������������������������������������
���������������������

�������� ����������� ������������ ������������� ��������������������� ��������� ������������� ����������� ���

������������������ ��� ���������������������� ���� ���� ����� �


�������������� ����������������������������
�����������������
�������� � �������� � ���� � ����������� � ��������� �������
�����������������������������������������������������������������������������������������������������������

Вам также может понравиться