Like
most .NET Developers, I do a lot of Line of Business application programming,
and I’m very excited about .NET
RIA Services. In this (very long) blog post, I’ll update my Beer DB Demo
using .NET
RIA Services and the Silverlight Business Application Template. In the
past, I’ve used the Beer DB for several talks and demos, including a Silverlight
1.1 Alpha Demo named Andy’s
Fridge, and a Silverlight
and LINQ to SQL demo.
While there is a ton of great information out there on .NET RIA Services, I
found many details hard to find and I hope this walkthrough will be helpful to
people encountering the same issues I did. Note that this was created using the
.NET RIA Services July 2009 Preview – so if you’re using this with a later
release there may be breaking changes.
DOWNLOAD
THE SAMPLE CODE
Here is a look at what the completed app looks like – a simple
Master/Detail interface with validation and Insert/Update/Delete operations:

Contents
Getting
Started. 2
Adding a New
Page. 5
Adding the
Database and Image Assets. 7
Creating the
Entity Data Model 7
Creating the
Domain Service Class. 9
Querying
using DomainDataSource. 11
Sorting and
Filtering using DomainDataSource. 12
Adding a
DataForm (Details View). 13
Customizing
the DataForm in Blend. 15
Adding
Validation. 20
Custom
Validation and Shared Classes. 21
Styling the
Application. 22
Displaying
the Product Image. 23
Debugging
and Error Handling. 24
1. Ensure
you have all of the required setup components (available from http://silverlight.net/getstarted/
a. Microsoft
Visual Studio 2008
b. Microsoft
Expression Blend 3
c. Silverlight
3 Tools for Visual Studio
d. .NET
RIA Services (this walkthrough created with July 2009 Preview)
e. A copy
of the Beers Database and Images. These are available in the ZIP download,
under \BeerDB.Web\ClientBin\images and \BeerDB.Web\App_Data.
2. Create
a new “Silverlight Business Application” named BeerDB.

3. The
Business Application Template creates a solution with .NET RIA Services
enabled, and includes a Silverlight Navigation application with separate
“Views” and a MainPage. Run the application by hitting F5 and note the template
that was generated. At the top-right of the screen are “home” and “about”
links. When you click these, you are brought to the appropriate View in the
project. Close the browser window to stop debugging.

4. In
Solution Explorer, right-click the BeerDB (Silverlight) project and select
properties. Note the .NET RIA Services link, which is pointing the Silverlight
project to the Web project in the solution. This link is required because, as
we’ll see, automatic code and proxy generation is performed when the solution
is compiled. For example, when we add a new server-side domain method to
retrieve data, a proxy is created to call that method.
1. Let’s
add in a new View to display our Beer Maintenance page. Right-click the Views
subfolder in the BeerDB (Silverlight) project and select Add/New Item. Select
Silverlight Page and name this page “BeerMaintenance.xaml”


2. In
Solution Explorer, find MainPage.xaml in the Silverlight project. Right-click
it and select “Open in Expression Blend”
3. In
the Objects and Timeline panel (or on the artboard), find and select the
Divider1 and Link2 elements. Then Right-click and Copy, then Right-click and
Paste.

4. Change
the text for this newly copied link to “beers” – and in the Properties Panel,
change the NavigateUri to “/BeerMaintenance”


5. Run
the project. Note that the new “beers” link is available and you can navigate
between all of the Views.
1. In
the BeerDB.Web Project (Web Application), right-click the App_Data folder and
select Add/Existing Item. Browse to the “Database.mdf” file (from the download
for this walkthrough).
2. In
the BeerDB.Web Project (Web Application), right-click the ClientBin folder and
select Add/New Folder. Name the new folder Images. Right-click the Images
folder and select Add/Existing Item. Browse and select all of the beer label
images (from the download for this walkthrough.
3. Your
BeerDB.Web project should now look something like this:

1. In
the BeerDB.Web Project (Web Application), right-click and select Add/New Item.
Select ADO.NET Entity Data Model and name the model BeerModel.edmx

2. Select
Generate from Database and click Next

3. On
this step, select Database.mdf for the data connection, and Save entity
connection settings in Web.Config. Change the Connection settings to
“BeerEntities” and click Next.

4. Select
the Beers and Brewers Tables in this step and enter “BeerModel” for the Model
Namespace. Then Click Finish.

5. Note
our simple database schema. Close the BeerModel.edmx and select Ctrl+Shift+B to
build the solution.
1. Right-click
the BeerDB.Web project and select Add/New Item. Select Domain Service Class and
name the class BeerService.

2. Be
sure that the BeerEntities Entity Framework model is selected (if it is not
available, make sure you did a rebuild!) Check the Beers and Brewers entities,
Enable Editing, and check the “Generate associated classed for metadata” checkbox.

1. Back
in the BeerDB (Silverlight) project, open the BeerMaintenance.xaml page.
2. At
the top of the page, add in a new xmlns for the current project. This will
allow access to the generated proxy classes from the web project.
xmlns:BeerDB.Web="clr-namespace:BeerDB.Web"
3. Add
in a Resources section to the navigation page, and add an instance of the beer
Domain Context. Note: we need to create a single instance of the beer domain
context to avoid issues
with nested listbound elements such as ComboBox and ListBox.
<navigation:Page.Resources>
<BeerDB:BeerContext x:Key="beerDomainContext"
/>
</navigation:Page.Resources>
4. Add
in a DomainDataSource control from the toolbox, and tweak it like so –
a. Add
in a DomainContext that points to our static resource BeerContext
b. Set
AutoLoad to True
c. Set
the QueryName to Beers
d. Handle
the LoadError and LoadedData events
<riaControls:DomainDataSource x:Name="ddsBeers"
DomainContext="{StaticResource beerDomainContext}"
AutoLoad="True"
QueryName="GetBeers"
LoadError="ddsBeers_LoadError"
LoadedData="ddsBeers_LoadedData">
</riaControls:DomainDataSource>
5. Drag
in a DataGrid from the toolbox and tweak it so that it binds to the ddsBeers Domain
Data Source.
<data:DataGrid x:Name="grdBeers"
ItemsSource="{Binding
Data, ElementName=ddsBeers}">
</data:DataGrid>
6. In
the code-behind file, implement the ddsBeers_LoadError and ddsBeers_LoadedData
methods so that they raise any exceptions that occur during processing (see the
section Debugging and Error Handling for more info).
private
void ddsBeers_LoadError(object sender, LoadErrorEventArgs
e)
{
if (e.Exception != null)
throw e.Exception;
}
private void
ddsBeers_LoadedData(object sender, LoadedDataEventArgs e)
{
if (e.Error != null)
throw e.Error;
}
7. Run
the project – you should see a DataGrid with Beers data.
1. To
sort our Beers by BeerName, we can use a SortDescriptor on the DomainDataSource.
First add in another xmlns namespace at the top of BeerMaintenance.xaml:
xmlns:riaData="clr-namespace:System.Windows.Data;assembly=System.Windows.Ria.Controls"
2. Now
we can use the Sort Descriptor by adding it inside the DomainDataSource control.
In this example, we are sorting by BeerName:
<riaControls:DomainDataSource x:Name="ddsBeers"
DomainContext="{StaticResource beerDomainContext}"
AutoLoad="True"
QueryName="GetBeers"
LoadError="ddsBeers_LoadError"
LoadedData="ddsBeers_LoadedData">
<riaControls:DomainDataSource.SortDescriptors>
<riaData:SortDescriptor Direction="Ascending" PropertyPath="BeerName"
/>
</riaControls:DomainDataSource.SortDescriptors>
</riaControls:DomainDataSource>
3. Note
that we can also add filtering declaratively, by using a FilterDescriptor. Add
in a TextBox named txtFilter, along with a label control and place these at the
top of the DataGrid:
<StackPanel
Orientation="Horizontal">
<TextBlock
Text="Filter: "/>
<TextBox x:Name="txtFilter"
Width="100" />
</StackPanel>
4. Now
we can add a FilterDescriptor to our DomainDataSource and filter on BeerName.
The value of the filter is bound from the txtFilter.Text value using a
ControlParameter.
<riaControls:DomainDataSource x:Name="ddsBeers"
DomainContext="{StaticResource
beerDomainContext}"
AutoLoad="True"
QueryName="GetBeers"
LoadError="ddsBeers_LoadError"
LoadedData="ddsBeers_LoadedData">
<riaControls:DomainDataSource.SortDescriptors>
<riaData:SortDescriptor Direction="Ascending"
PropertyPath="BeerName" />
</riaControls:DomainDataSource.SortDescriptors>
<riaControls:DomainDataSource.FilterDescriptors>
<riaData:FilterDescriptorCollection x:Name="DataSourceFilters">
<riaData:FilterDescriptor PropertyPath="BeerName" Operator="StartsWith">
<riaData:ControlParameter ControlName="txtFilter" PropertyName="Text" RefreshEventName="TextChanged" />
</riaData:FilterDescriptor>
</riaData:FilterDescriptorCollection>
</riaControls:DomainDataSource.FilterDescriptors>
</riaControls:DomainDataSource>
A DataForm can quickly add Update, Insert, and Delete
functionality to an application.
1. Open
BeerMaintenance.xaml in Blend. Place the grdBeers Grid in a StackPanel and add
a DataForm into the StackPanel, so that the resulting XAML resembles the
following:
<StackPanel
Orientation="Vertical">
<data:DataGrid x:Name="grdBeers"
ItemsSource="{Binding
Data, ElementName=ddsBeers}">
</data:DataGrid>
<dataFormToolkit:DataForm>
</dataFormToolkit:DataForm>
</StackPanel>
2.
Add the following attributes to the DataForm:
<dataFormToolkit:DataForm x:Name="dataForm1"
ItemsSource="{Binding Data, ElementName=ddsBeers}"
CommandButtonsVisibility="All" AutoEdit="True"
AutoCommit="True"
EditEnded="dataForm1_EditEnded"
DeletingItem="dataForm1_DeletingItem"
>
<d:DataContext>
<BeerDB:Beers></BeerDB:Beers>
</d:DataContext>
</dataFormToolkit:DataForm>
a.
x:Name=”dataForm1” - this is the ID of the DataForm in code.
b.
ItemsSource=”{Binding Data, ElementName=ddsBeers}” - this is the
runtime databinding source for the form to get data. Since this is the same
data source as the DataGrid, they will stay in sync.
c.
CommandButtonsVisibility=”All” - this shows all of the Edit and
Paging buttons on the DataForm.
d.
AutoEdit=”True” - this allows the user to edit the data in the
form without explicitly selecting an “Edit” command button.
e.
AutoCommit=”True” - this automatically commits changes to the
DataForm when the user selects a different row.
f.
EditEnded Event – handle this so that we can commit updates.
g.
DeletingItem – handle this so that we confirm if the user wants
to delete an item.
h.
d:DataContext – this is what Blend uses at Design Time to determine
what binding context is available. We set this to an instance of the Beers
class so that we can bind fields for the Beer using Blend’s design tools.
3.
In the code-behind file for this page, import the BeerDB.Web
namespace so that we can access the proxy classes generated from the
server-side context.
using BeerDB.Web;
using System.Windows.Ria.Data;
4.
Add an instance of the BeerContext as a class-level variable.
BeerContext _beerContext;
5.
In the OnNavigatedTo event handler, get a reference to the beerDomainContext
page resource and wire up an event handler for the CollectionChanged event.
// Executes when the user navigates to this page.
protected override
void OnNavigatedTo(NavigationEventArgs
e)
{
// Our main Data Context is in the Page's
Resource section
_beerContext = this.Resources["beerDomainContext"] as BeerContext;
// We need to handle CollectionChanged for
Delete's performed on the DataForm
ddsBeers.DataView.CollectionChanged += new
System.Collections.Specialized.NotifyCollectionChangedEventHandler(DataView_CollectionChanged);
}
6.
Implement the following event handlers to Update/Insert and
Delete beer records from the DataForm. Note that we need to handle the
CollectionChanged event in order to Delete records, and the EditEnded event
handles both Insert and Update operations.
private void dataForm1_EditEnded(object sender, System.Windows.Controls.DataFormEditEndedEventArgs e)
{
dataForm1.CommitEdit();
// is this a NEW beer? If so we need to default
the RowVersionId
Beers beer =
(dataForm1.CurrentItem as Beers);
if (beer.BeerId == 0)
{
beer.RowVersionId = new byte[1];
}
if (e.EditAction == DataFormEditAction.Commit)
_beerContext.SubmitChanges(SubmitChangesComplete, null);
}
void DataView_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
// We need to handle this event for Deletes,
since EditEnded is not called on a delete.
if (e.Action ==
System.Collections.Specialized.NotifyCollectionChangedAction.Remove
&& (e.OldItems[0] as Beers).BeerId > 0)
_beerContext.SubmitChanges(SubmitChangesComplete, null);
}
void SubmitChangesComplete(SubmitOperation op)
{
if (op.HasError)
throw op.Error;
}
7.
Run the project and test the Add, Update, and Delete methods of
the DataForm.
1.
Note that, when we added the DataForm, we included the following “d:DataContext”
attribute:
<d:DataContext>
<BeerDB:Beers></BeerDB:Beers>
</d:DataContext>
This informs Blend of the type of data that we will be binding to the
DataForm at run-time, so that it can support design time data binding information.
Anytime a property is prefixed with “d:”, it is defined in Blend’s namespace
and is generally used to set design time properties.
2.
Right-click BeerMaintenance.xaml and select “Open in Expression
Blend”
3.
In the Objects and Timeline Panel, find dataForm1. Right-click it
and select Edit Additional Templates/Edit EditTemplate/Create Empty.

4.
On the “Create DataTemplate Resource” dialog, accept the defaults
and click OK.
5.
Resize the Grid in the data template so that it is about 500
pixels wide and 400 pixels high.
6.
Increase the number of rows in the Grid so that there are 6 rows.
You can do this by clicking in the left-hand border of the Grid on the arboard:
7.
Increase the number of columns in the Grid so that there are 2
columns. You can do this by clicking in the top border of the Grid on the
arboard:

8.
Add a TextBlock into the first row and column of the Grid. Ensure
that its Margins are set to 0, set its HorizontalAlignment to Left and
VerticalAlignment to Center. Change the text property to “Beer Name:”

9.
Add a TextBox into the first row and second column of the Grid.
Ensure that its Margins are set to 0, set its HorizontalAlignment to Left and
VerticalAlignment to Center. Your Grid should now look something like this:

10.
Next we’ll create the databinding for the TextBox. Select the
Advanced Property Options control (the little white square) to the right of the
Text property for the TextBox.

11.
Select the Data Binding option from the popup menu.

12.
On the Create Data Binding Dialog, select the BeerName field.
Note that this is on the “Explicit Data Context” tab.

13.
Repeat the steps above to add TextBlocks, TextBoxes, and Data
Bindings for the Color, Alcohol, ImageUrl, and MoreInfo properties. Put a
placeholder in for the Brewery Label (later on we’ll use a ComboBox for this
field). The resulting XAML in the Data Template should look similar to the
following:
<Grid x:Name="grdBeerDetails"
Grid.Column="1">
<Grid.ColumnDefinitions>
<ColumnDefinition
Width="100"/>
<ColumnDefinition
Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition
Height="40" />
<RowDefinition
Height="40" />
<RowDefinition
Height="40"/>
<RowDefinition
Height="40"/>
<RowDefinition
Height="40" />
<RowDefinition
Height="40" />
</Grid.RowDefinitions>
<TextBlock x:Name="txtBeerNameLabel"
Margin="0,0,4,0" VerticalAlignment="Top"
Grid.Column="0" Grid.Row="0"
Text="Name:" />
<TextBox x:Name="txtBeerName"
VerticalAlignment="Top"
Grid.Column="1" Grid.Row="0"
Height="24" Text="{Binding
BeerName, Mode=TwoWay}" />
<TextBlock x:Name="txtColorLabel"
Margin="0,0,4,0" VerticalAlignment="Top"
Grid.Column="0" Grid.Row="1"
Text="Color:" />
<TextBox x:Name="txtColor"
VerticalAlignment="Top"
Grid.Column="1" Grid.Row="1"
Height="24" Text="{Binding
Color, Mode=TwoWay}" />
<TextBlock x:Name="txtAlcoholLabel"
Margin="0,0,4,0" VerticalAlignment="Top"
Grid.Column="0" Grid.Row="2"
Text="Alcohol:" />
<TextBox x:Name="txtAlcohol"
VerticalAlignment="Top"
Grid.Column="1" Grid.Row="2"
Height="24" Text="{Binding
AlcoholContent, Mode=TwoWay}"
/>
<TextBlock x:Name="txtBreweryLabel"
Margin="0,0,4,0" VerticalAlignment="Top"
Grid.Column="0" Grid.Row="3"
Text="Brewery:" />
<TextBlock x:Name="txtImageUrlLabel"
Margin="0,0,4,0" VerticalAlignment="Top"
Grid.Column="0" Grid.Row="4"
Text="Image Url:" />
<TextBox x:Name="txtImageUrl"
VerticalAlignment="Top"
Grid.Column="1" Grid.Row="4"
Height="24" Text="{Binding
ImageUrl, Mode=TwoWay}" />
<TextBlock x:Name="txtMoreInfoLabel"
Margin="0,0,4,0" VerticalAlignment="Top"
Grid.Column="0" Grid.Row="5"
Text="More Info Url:" />
<TextBox x:Name="txtMoreInfo"
VerticalAlignment="Top"
Grid.Column="1" Grid.Row="5"
Height="24" Text="{Binding
MoreInfoUrl, Mode=TwoWay}"
/>
</Grid>
14.
Next we’ll add a ComboBox into the DataForm for the BreweryName
selection. Note that we need to query a list of Brewery Names to fill this
ComboBox. To query these, add in a new DomainDataSource control just
inside the Grid for the Data Template.
<riaControls:DomainDataSource x:Name="ddsBrewers"
AutoLoad="True"
QueryName="GetBrewers"
LoadError="ddsBrewers_LoadError"
DomainContext="{StaticResource
beerDomainContext}"
LoadedData="ddsBrewers_LoadedData"/>
15.
Now we can add in a ComboBox into the DataTemplate which uses the
ddsBrewers Data Source above. Note the ItemsSource binding which uses the Data
Source, and the SelectedItem binding, which uses the Brewers property of the
Beer that the record is bound to.
<ComboBox x:Name="cboBrewery"
Grid.Column="1" Grid.Row="3" Height="24"
ItemsSource="{Binding Data, ElementName=ddsBrewers}"
SelectedItem="{Binding Brewers, Mode=TwoWay}"
DisplayMemberPath="BreweryName"/>
16.
Add in the event handlers for the LoadError and LoadedData events
for the Brewers query. Note that any errors from the DataContext are not
automatically raised, so we need these event handlers to do so.
private void
ddsBrewers_LoadError(object sender, LoadErrorEventArgs e)
{
if (e.Exception != null)
throw e.Exception;
}
private void
ddsBrewers_LoadedData(object sender, LoadedDataEventArgs e)
{
if (e.Error != null)
throw e.Error;
}
17.
Run the project, and test the new DataForm template.
1. Run
the application and try setting the Alcohol Content field to a string value.
Since the underlying field is a decimal, you get a validation warning.
Validation on Data Types is built in automatically to the Data Form.

2. To
add in validation other than data type checking, go to the BeerDB.Web project
and open the BeerService.metadata.cs file. Find the BeersMetadata class and add
the following attributes to enforce string lengths, required fields, and
format. You can also optionally add in the error message to display when the
validation errors occur.
internal sealed class BeersMetadata
{
// Metadata classes are not meant to be
instantiated.
private BeersMetadata()
{
}
public Nullable<Decimal> AlcoholContent;
public int
BeerId;
[Required]
[StringLength(100, ErrorMessage="You must enter a Beer Name.")]
public string
BeerName;
public Brewers
Brewers;
[StringLength(100)]
public string
Color;
public EntityState
EntityState;
[StringLength(200, ErrorMessage = "Image Url must be less than 200 chars.")]
public string
ImageUrl;
public Nullable<DateTime> IntroductionDate;
[StringLength(200, ErrorMessage = "More Info Url must be less than 200 chars.")]
[RegularExpression(@"^http\://[a-zA-Z0-9\-\.]+\.[a-zA-Z]{2,3}(/\S*)?$",
ErrorMessage="More Info Url must be a valid
Url.")]
public string
MoreInfoUrl;
public byte[]
RowVersionId;
}
3. Run
the application and note the new validation for the data form.

Besides the “canned” validation shown above, we can also
define Custom Validation based on any kind of logic we prefer. Since the
validation must execute on both the Server and the Silverlight Client, we place
this Custom Validation in a Shared class. Shared Classes are automatically
compiled into the Silverlight client when they are created on the Server side
web project.
In this example, we’ll add a validation method that only
allows certain colors. Note that, in a real world example, we would probably
define this in a “lookup table” instead of code.
1. Add
a new Class named CustomValideColors.shared.cs to the BeerDB.Web project. Note
that simply by adding the “.shared.cs” suffix, this will cause RIA Services to
automatically copy and compile the class to the Silverlight application.

2. Add
a new static method to the class which validates that the color of a beer is
within a given list. Note the signature of the method.
public static ValidationResult IsValidBeerColor(object value,
ValidationContext context)
{
string[] colors = { "Light", "Amber",
"Dark" };
if (colors.Contains(value))
{
return ValidationResult.Success;
}
else
{
return new
ValidationResult(context.DisplayName + " must be Light, Amber, or Dark.");
}
}
3. You
can now use this new validation method on a property in the metadata class.
Open BeerService.metadata.cs and add in a CustomValidation attribute which uses
the IsValidBeerColor method to validate the beer color.
[StringLength(100)]
[CustomValidation(typeof(CustomValidateColors), "IsValidBeerColor")]
public string
Color;
4. Run
the project and note the validation message for Color.
The Silverlight Business Application Template has a single
Styles.xaml resource file which defines the overall look and feel of the
application. We can replace this file with a different set of style
information, and can even use one of many free styles available from the
community.
1. In
the BeerDB (Silverlight) project, expand the Assets folder and note the Styles.xaml
file. This contains the style information for our application.

2. There
are many free
alternate style templates for RIA Services available on the Expression
Community Site. Simply download the ZIP and extract the contents into your
Assets subfolder, overwriting the existing Styles.xaml. Below is the
application with the Seeing
Sound style applied.

Our database contains links to beer labels, so let’s use
these to overlay a beer bottle and create a copy of the “product.” This will
give the Details view a bit more spice!
1. Open
BeerMaintenance.xaml in Expression Blend.
2. Edit
the DataForm’s Data Template by right-clicking dataForm1 and selecting Edit
Additional Templates/Edit EditTemplate/Edit Current
3. Right-click
grdBeerDetails and select Group Into/StackPanel. Set the StackPanel’s
Orientation to Horizontal.
4.
Add a Canvas into the StackPanel, and add two Image controls into
the Canvas. Set the Source of the first image to /images/beerBottle.png, and
bind the Source of the second image to the ImageUrl property. Align the Images
so that the label overlays the bottle. The resulting XAML should look similar
to the following:
<StackPanel Orientation="Horizontal" HorizontalAlignment="Left" Width="600">
<Grid x:Name="grdBeerDetails"
Width="300" Margin="0,40,40,0">
<!-- Grid details removed for brevity -->
</Grid>
<Canvas Height="340" Width="200">
<Image x:Name="imgBeerBottle"
Source="/images/beerBottle.png" Width="93" Height="311" Canvas.Left="0" Canvas.Top="0"
/>
<Image x:Name="imgBeerLabel" Source="{Binding ImageUrl}" Width="73" Height="95" Canvas.Left="10" Canvas.Top="160" Stretch="Fill"
/>
</Canvas>
</StackPanel>
Here are a couple of hints on Debugging and Error Handling
with .NET RIA Services.
1. If
an error occurs during a remote call, such as an authorization failure, the
Silverlight client will not raise the exception by default. This is because exceptions
are silent by default. So be sure to handle the LoadError and LoadedData
Events…
<riaControls:DomainDataSource x:Name="ddsBeers"
DomainContext="{StaticResource beerDomainContext}"
AutoLoad="True"
QueryName="GetBeers"
LoadError="ddsBeers_LoadError"
LoadedData="ddsBeers_LoadedData">
</riaControls:DomainDataSource>
…and then implement these handlers to check for an error, and
minimally raise the exception:
private
void ddsBeers_LoadError(object sender, LoadErrorEventArgs
e)
{
if (e.Exception != null)
throw e.Exception;
}
private void
ddsBeers_LoadedData(object sender, LoadedDataEventArgs e)
{
if (e.Error != null)
throw e.Error;
}
2. In
the current (July 2009) version of .NET RIA Services, some exceptions are not
properly raised to the Silverlight client. When this happens you will generally
get the following error:
Exception has been thrown by the target of an invocation.
To debug this issue, and see the exception on the server side, be sure to
enable CLR Exceptions – in Visual Studio, select Debug/Exceptions, and check
the Thrown checkbox for “Common Language Runtime Exceptions.”
