In this section, we will implement a sample application that illustrates how you can design and implement a WCF 4.5 RIA Service and then consume it using Silverlight 5. When you create a Silverlight application, you can check the Enable WCF RIA Services checkbox. This will ensure that an RIA services link is created, when you eventually build the complete solution, the client-side code will be generated for the domain services and the shared code.
To get started using WCF 4.5 RIA Services in Silverlight 5, follow these simple steps:
Class1.cs
files in the server and client projects in the Solution Explorer window.Class1.cs
file in both the Server and Client projects, the Solution Explorer window would look like this:Once you click on Install, the installation of Entity Framework will start.
Note that you can install Entity Framework also by executing commands in the Package Manager Console. You can learn more details about the version of Entity Framework from the NuGet web site: http://www.nuget.org/packages/entityframework.
After Entity Framework has been successfully installed, you can see the green tick symbol as shown in the following screenshot:
Models
, and a new entity data model using the AdventureWorks
database.App-Code
and the other named Services
.DomainService
class. To do this, navigate to Add | New Item on the Services
solution folder, and select Web from the list of the installed templates. Then select Domain Service Class. Name this class DepartmentDomainService.cs
and, click on Add.If you would like to leverage the Entity Framework entity data model with WCF 4.5 RIA Services, you should convert it to "ObjectContext" based model, otherwise you wouldn't see the entities listed when you are creating the domain service. You would observe a message that states: Some Entity Framework context classes may have been excluded.
To overcome this, open your entity data model in the designer mode, and change the Code Generation Strategy from None to Default. Next, delete the two .tt
files that are adjacent to the model, and then rebuild the project.
It should be noted that if you add a class library project to a Silverlight business application project, you are constrained from adding an authentication service to the server project. The reason of this is that the user object in the Silverlight business application template cannot be accessed from the class library project.
It should be noted that Silverlight is incapable of sharing assemblies with the server side. To bridge this gap .NET RIA Services are used. If .NET RIA Services are used, classes that are almost a replica of the domain classes are code generated on the client side. This ensures that you can move objects back and forth between the server side and the client side. The following diagram illustrates how the RIA Link is established between a Silverlight Application and a Web Application, when you use WCF RIA Services and consume them using Silverlight:
Now let's take a look at the Domain Service
class that was automatically generated. Here's how the DepartmentDomainService
class will look like:
namespace Demo.Web.Services { using System.Data; using System.Linq; using System.ServiceModel.DomainServices.EntityFramework; using System.ServiceModel.DomainServices.Hosting; using Demo.Web.Models; [EnableClientAccess()] public class DepartmentDomainService : LinqToEntitiesDomainService<AdventureWorks2008R2Entities> { public IQueryable<Department> GetDepartments() { return this.ObjectContext.Departments; } public void InsertDepartment(Department department) { if ((department.EntityState != EntityState.Detached)) { this.ObjectContext.ObjectStateManager.ChangeObjectState(department, EntityState.Added); } else { this.ObjectContext.Departments.AddObject(department); } } public void UpdateDepartment(Department currentDepartment) { this.ObjectContext.Departments.AttachAsModified(currentDepartment, this.ChangeSet.GetOriginal(currentDepartment)); } public void DeleteDepartment(Department department) { if ((department.EntityState != EntityState.Detached)) { this.ObjectContext.ObjectStateManager.ChangeObjectState(department, EntityState.Deleted); } else { this.ObjectContext.Departments.Attach(department); this.ObjectContext.Departments.DeleteObject(department); } } } }
Refer to the preceding code snippet. When building LOB applications, common features are create, update, read, and delete operations on the data. The EnableClientAccessAttribute
attribute in the System.Web.Ria
namespace enables the client-side code to be generated at the compile time.
You can now specify the necessary configuration to consume the data exposed by this WCF 4.5 RIA Service.
Now, let's quickly create a domain service class based on SecurityDB
we created earlier in this book.
Follow these steps:
DomainServices
.SecurityDB
as shown in the following screenshot:SecurityDomainService.cs
and click on Add. You will see a page that looks like the following screenshot:As you can see, two entities Control and
ControlType are listed. Select both of them and click on OK. The Domain service Class will now be generated. At first glance, the SecurityDomainService
class looks like this:
namespace DomainServices { using System.Linq; using System.ServiceModel.DomainServices.EntityFramework; using System.ServiceModel.DomainServices.Hosting; [EnableClientAccess()] public class SecurityDomainService : LinqToEntitiesDomainService<SecurityDBEntities> { public IQueryable<Control> GetControls() { return this.ObjectContext.Controls; } public IQueryable<ControlType> GetControlTypes() { return this.ObjectContext.ControlTypes; } } }
The next step is to add the necessary CRUD methods to Domain Service for creating a new record, updating an existing record, deleting an existing record, and retrieving one or more records belonging to the Control
or ControlType
tables.
Here's the complete code of the SecurityDomainService
class after the necessary CRUD methods have been added:
namespace DomainServices { using System.Data; using System.Linq; using System.ServiceModel.DomainServices.EntityFramework; using System.ServiceModel.DomainServices.Hosting; [EnableClientAccess()] public class SecurityDomainService : LinqToEntitiesDomainService<SecurityDBEntities> { public IQueryable<Control> GetControls() { return this.ObjectContext.Controls; } public IQueryable<ControlType> GetControlTypes() { return this.ObjectContext.ControlTypes; } public IQueryable<Control> GetControls() { return this.ObjectContext.Controls; } public IQueryable<ControlType> GetControlTypes() { return this.ObjectContext.ControlTypes; } public void InsertControl(Control control) { if ((control.EntityState != EntityState.Detached)) { this.ObjectContext.ObjectStateManager.ChangeObjectState(control, EntityState.Added); } else { this.ObjectContext.Controls.AddObject(control); } } public void InsertControlType(ControlType controlType) { if ((controlType.EntityState != EntityState.Detached)) { this.ObjectContext.ObjectStateManager.ChangeObjectState(controlType, EntityState.Added); } else { this.ObjectContext.ControlTypes.AddObject(controlType); } } public void UpdateControls(Control controlObj) { this.ObjectContext.Controls.AttachAsModified(controlObj, this.ChangeSet.GetOriginal(controlObj)); } public void UpdateControlTypes(ControlType controlTypeObj) { this.ObjectContext.ControlTypes.AttachAsModified(controlTypeObj, this.ChangeSet.GetOriginal(controlTypeObj)); } public void DeleteControls(Control controlObj) { if ((controlObj.EntityState != EntityState.Detached)) { this.ObjectContext.ObjectStateManager.ChangeObjectState(controlObj, EntityState.Deleted); } else { this.ObjectContext.Controls.Attach(controlObj); this.ObjectContext.Controls.DeleteObject(controlObj); } } public void DeleteControlTypes(ControlType controlTypeObj) { if ((controlTypeObj.EntityState != EntityState.Detached)) { this.ObjectContext.ObjectStateManager.ChangeObjectState(controlTypeObj, EntityState.Deleted); } else { this.ObjectContext.ControlTypes.Attach(controlTypeObj); this.ObjectContext.ControlTypes.DeleteObject(controlTypeObj); } } } }
To consume the Domain Service from Silverlight 5, you need to follow the same steps as discussed earlier in this chapter.
Here are a few links for further reference on this topic: