}
}
}
CRMCache.cs
756 .
chaPter 34 SynchronizATion SerViceS
If you were synchronizing other tables, you would need to set SyncDirection on each of
the corresponding SyncTables. An alternative implementation would be to place this code in the
OnInitialized method of the SyncAgent itself, setting the SyncDirection on each sync table (for
example the CustomerSyncTable). Whichever way you choose, you still need to apply the
Bidirectional value to all tables you want to synchronize in both directions.
suMMary
In this chapter you have seen how to use the Microsoft Synchronization Services for ADO.NET to
build an occasionally connected application. While you have other considerations when building
such an application, such as how to detect network connectivity, you have seen how to perform
synchronization as a background task and how to separate the client and server components into
different application tiers. With this knowledge, you can begin to work with this new technology to
build richer applications that will continue to work regardless of where they are being used.
35 35
WCf ria services
what’s in this chaPter?
.
Understanding WCF RIA Services
.Creating a domain service
.
Exposing data
.
Consuming WCF RIA Services in Silverlight
In Chapter 31 you saw how WCF provided a standardized means of communication in
a technology-agnostic manner. WCF RIA Services (commonly referred to as just RIA
Services) is a layer on top of WCF that provides a prescriptive pattern and framework for
designing data-driven applications that consume data from a server. WCF RIA Services
currently target Silverlight applications, but with a view to support additional presentation
technologies. This chapter looks at how to use RIA Services to create an end-to-end
Silverlight application.
GettinG started
RIA Services is currently most closely associated with and focused toward Silverlight for
the client platform, so you will start by creating a Silverlight project. You will find
a Business Application template (as shown in Figure 35-1 under the Silverlight category),
which will create all the solution structure required to start with RIA Services
(a Silverlight project, an ASP.NET web application, and the RIA Services link between
the two).
758 .
chaPter 35 WcF riA SerViceS
fiGure 35-1
This creates a Silverlight project and an ASP.NET project —
with the structure of the ASP.NET project shown in
Figure 35-2.
The ASP.NET project already supports and implements some basic
functionality using the RIA Services pattern. You’ll note from
Figure 35-2 that there is a Services folder and a Models folder
in the project. The Services folder already contains two domain
services (AuthenticationService and UserRegistrationService) for
providing authentication and user registration operations to the
client. The Models folder contains two data classes (User and
RegistrationData) that are passed between the server and the
client. You will also find a Shared folder under the Models folder,
which has a file called User.shared.vb or User.shared.cs
that contains code to be shared between the server and the
client projects.
As demonstrated in Chapter 22, the Silverlight and the ASP.NET projects are linked together such
that the Silverlight application is copied to somewhere in the ASP.NET project when the project/
solution is compiled (configured in the project properties for the ASP.NET project). However, by
introducing RIA Services into the picture you will now have another link between the projects.
This link is configured in the project properties of the Silverlight project to select the ASP.NET
project that will be acting as the server that it will be communicating with, and from which project
the RIA Services build task will generate the code based on, as shown in Figure 35-3.
fiGure 35-2
Getting started .
759
fiGure 35-3
This link will already be set up by using the Business Application project template; however, if you
have an existing Silverlight project or web application that you want to use RIA Services with
you can manually link the projects together by linking the Silverlight project to an ASP.NET
project with this option.
Now you are ready to start writing some code. The example you work through in this chapter
demonstrates some of the key concepts of the RIA Services pattern. Your aim will be to expose
customer data and operations from the server and make the data and operations accessible from
the client.
You will be using your Entity Framework model of the AdventureWorksLT database that you
created back in Chapter 29. It’s not necessary to pass entities from your model back and forth
between the server and the client, and in many cases it’s considered bad practice. The entities are
essentially a model of your data layer, which conceptually is not something that the presentation
layer should be exposed to. Whether or not you pass entities or POCO (Plain Old CLR Objects)
objects of your own design (referred to as presentation model types in RIA Services) back and
forth is a decision you will have to make, dependant on many factors. Using entities will make
development much faster, but will also be less flexible than using presentation model types. RIA
Services works just as well using presentation model types as it does with entities, despite more work
being involved in initially creating the Domain Services. Therefore, the best practice would be to use
presentation model types as the data transfer mechanism; however, we will focus on using entities in
this chapter because they provide the easiest means to get started.
760 .
chaPter 35 WcF riA SerViceS
doMain serVices
Now that you have your server and client projects connected via RIA Services, it’s time to
expose some data and operations from the server, which you will consume from your client at a
later point.
Start by assuming that the Entity Framework model of the AdventureWorksLT database from
Chapter 29 has been added to your ASP.NET project (including adding the connection string that it
uses to the web.config file). If not, do so now.
Ensure that you compile the ASP.NET project before continuing on to the
next step, otherwise the Domain Service Class Wizard will not display your
entity model in the available DataContexts/ObjectContexts drop-down list.
To expose the customer data from your entity model you need to add a domain service to your
ASP.NET project. The best place in your project to add this service is under the Services folder.
Add a new item to this folder, and select Domain Service Class under the Web category as the item
template (as shown in Figure 35-4). You will be using this service to serve up customer data, so call
it CustomersService
(.cs or .vb).
fiGure 35-4
Domain services .
761
Clicking OK initiates the Domain Service Class
Wizard, shown in Figure 35-5.
If it hasn’t automatically selected your Entity
Framework model for the AdventureWorksLT
database in the Available DataContexts/
ObjectContexts drop-down list, select it
now. All the entities from your entity model
will be displayed in the list. Here you can select
one or more entities that you want to expose from
your domain service. When you select an entity
the wizard creates a domain operation to return
a collection of that entity from the domain service.
If you select the Enable Editing option for an entity,
the wizard also creates Insert, Update, and Delete
domain operations for that entity on the domain
service.
fiGure 35-5
If you’re using POCO/presentation model types instead of Entity Framework
or LINQ-to-SQL types, you can select the <empty domain service class>
option from the Available DataContexts/ObjectContexts drop-down list and
implement the domain operations yourself.
You should ensure that the Enable client access checkbox is checked. This will ensure that the
EnableClientAccess attribute is applied to the service when it is created, which means that code
will be generated on the client by the RIA Services code generator to enable it to access the domain
service.
You will note that there is also a Generate associated classes for metadata checkbox on the wizard.
Metadata classes enable you to add special attributes to properties on the data class being transferred
(such as how the entity should be created on the client, and data validation rules) without the need to
modify the source object (which is important when, for example, you regenerate your object’s code
with a code generator or an ORM). Instead, you can apply attributes to the properties in a metadata
class that correlate with the properties on the actual class, and these attributes will control how
the associated entity is created on the client, and apply other attributes (such as validation rules) to
the entity it creates on the client. You will find a more thorough explanation of metadata classes in
Chapter 23 (Dynamic Data).
It ’s not essential to generate metadata classes for your entities, although it does provide a degree of
control over the data passed between the server and the client, so it is recommended that you create them.
762 .
chaPter 35 WcF riA SerViceS
Select the Customer entity, select the Enable Editing checkbox for it, and ensure both the Enable
client access and Generate associated classes for metadata checkboxes are selected. Clicking OK
creates the domain service and metadata classes for you.
doMain oPerations
Domain operations are operations on a domain service that can be called from the client. The types
of domain operations that exist in a domain service can each be considered to be a CRUD (Create,
Read, Update, Delete) operation, an invoke operation, or a custom operation.
The names and/or the method signature of these operations are convention-based so RIA Services
can implicitly determine what type of operation it is and generate the correct corresponding
operation in the client project. If for some reason you don’t want to use the given conventions you
can decorate the operation (that is, the method) with an attribute to specify what type of operation
is being represented.
Some people prefer to decorate their operations even when they follow the
naming/signature convention in order to explicitly define what type of operation
is being represented.
Let’s now take a look at what domain operations have been generated for you in your domain
service by the wizard, and what other types of operations you can create.
query operations
When you open the CustomersService (.cs or .vb) fi le you will see that the basic CRUD operations
have been implemented for your Customer entity. The default Read (aka Get or Query) operation returns
a collection of entities with the following method signature:
Vb
Public Function GetCustomers() As IQueryable(Of Customer)
c#
public IQueryable < Customer > GetCustomers()
Note how the GetCustomers operation returns an IQueryable collection of the Customer entity.
This is one of the most powerful features of RIA Services, in that this feature enables you to write
a LINQ query on the client that can be used to filter and shape the entities that it wants returned.
This LINQ query is actually serialized and sent to the server before being executed. Where you will
see the power of this feature is when you try to implement filtering/paging/grouping/sorting on the
client. Instead of requiring a raft of complex operations on the server to implement these behaviors,
you only need the one simple operation that returns an IQueryable collection, and then a LINQ
Domain operations .
763
query can be provided by the client to filter/shape the results on the server before returning them.
Alternatively, you can modify the Get operation and add your own parameters to it, which the
operation can use to filter and shape the results to return to the client.
insert/update/delete operations
The insert (also known as create), update, and delete operations are automatically called when you
submit a change set to the server (based on the actions taken upon the results of a query operation
on the client), and cannot be called explicitly from the client. These actions are covered later in the
chapter, but for now take a look at the operations that have been implemented for you automatically
by the Domain Service Class Wizard and how they are implemented. The operations that were
created for you have the following method signatures:
Vb
Public Sub InsertCustomer(ByVal customer As Customer)
Public Sub UpdateCustomer(ByVal currentCustomer As Customer)
Public Sub DeleteCustomer(ByVal customer As Customer)
c#
public void InsertCustomer(Customer customer)
public void UpdateCustomer(Customer currentCustomer)
public void DeleteCustomer(Customer customer)
Each of these accepts an entity of the given type, and performs the appropriate server-side action
on that entity. They each have a convention for its naming, they must not return a value, and
their method signature must accept an entity as the only parameter. The naming convention and
alternative attribute is as follows:
.
The method name of insert operations must start with Insert, Create, or Add. Otherwise,
apply the Insert attribute to the method.
.
The method name of update operations must start with Update, Change, or Modify.
Otherwise, apply the Update attribute to the method.
.
The method name of delete operations must start with Delete or Remove. Otherwise, apply
the Delete attribute to the method.
other operation types
Other types of operations supported by RIA Services (but not fully detailed here) are as follows:
.
An invoke operation is essentially the same as a service operation in a standard WCF Service
(that is, a method exposed by the service). Invoke operations are created as methods on the
domain context on the client, and are called immediately (that is, they aren’t queued until