Apr
18
Written by:
Michael Washington
4/18/2012 9:37 PM
The LightSwitch Silverlight screens allow you to easily group and total data. The LightSwitch OData services return one Entity collection at a time. This makes grouping and totaling across Entity collections difficult. Using WCF RIA Services provides a clean elegant solution.
In the Flower Shop application used in the tutorial: Calling LightSwitch 2011 OData Using Server Side Code we have two computed fields in the FlowerShopOrder Entity.
These fields allow us to easily display the Order Total and the name of the Customer.
However, if we connect to the OData service for that Entity, we see it does not contain the Order Total nor the name of the Customer.
To get this data, it requires additional queries of Customer Entity to get the Customer name, the Product Entity to get the Product price, and all the related Order Detail Entities to calculate the Order Total.
This is a problem because not only does it require additional database queries, it requires the client consuming the OData feed to now be responsible for complex business logic.
We can create an OData service with these computed fields using a WCF RIA Service.
Create A WCF RIA Service
Open up the Flower Shop application used in the tutorial: Calling LightSwitch 2011 OData Using Server Side Code and Add a New Project.
Create a Class Library called WCF_RIA_Project.
Delete the Class1.cs file that is automatically created.
Add a New Item to WCF_RIA_Project.
Add a Domain Service Class called WCF_RIA_Service.
When the Add New Domain Service Class box comes up, uncheck Enable client access. Click OK.
This domain class will be exposed by LightSwitch and will pass through its security and business rules.
We need additional references, add the following references to the WCF_RIA_Project…
- System.ComponentModel.DataAnnotations
- System.Configuration
- System.Data.Entity
- System.Runtime.Serialization
- System.ServiceModel.DomainServices.Server (Look in %ProgramFiles%\Microsoft SDKs\RIA Services\v1.0\Libraries\Server)
- System.Web
Add the following Using Statements to the class:
using ApplicationData.Implementation;
using System.Data.EntityClient;
using System.Web.Configuration;
(ApplicationData will display a squiggly red line because the class is missing, but it will be added in a subsequent step)
Reference The LightSwitch Object Context
Now, we will add code from the LightSwitch project to our WCF RIA Service project. We will add a class that LightSwitch automatically creates, that connects to the database that LightSwitch uses.
We will use this class in our WCF RIA Service to communicate with the LightSwitch database.
Right-click on the WCF_RIA_Project and select Add then Existing Item.
Navigate to ..Server\GeneratedArtifacts (in the LightSwitch project)and click on ApplicationData.cs and Add As Link.
We used “add As Link” so that whenever LightSwitch updates this class, our WCF RIA Service is also updated. This is how our WCF RIA Service would be able to see any new Entities (tables) that were added, deleted, or changed.
Create the Domain Service
We use the following code for the WCF RIA Service:
namespace WCF_RIA_Project
{
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.ServiceModel.DomainServices.Hosting;
using System.ServiceModel.DomainServices.Server;
using ApplicationData.Implementation;
using System.Data.EntityClient;
using System.Web.Configuration;
// This class is used as the class that is returned
// This can have any 'shape' you desire
// Make sure this is outside of the WCF_RIA_Service class
// but inside the WCF_RIA_Project namespace
public class EnhancedFlowerShopOrder
{
[Key]
public int ID { get; set; }
public DateTime OrderDate { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public decimal OrderTotal { get; set; }
}
public class WCF_RIA_Service : DomainService
{
// This Context property is code that connects to the LightSwitch database
// The code in the Database connection region can be reused as it is
#region Database connection
private ApplicationDataObjectContext m_context;
public ApplicationDataObjectContext Context
{
get
{
if (this.m_context == null)
{
string connString =
System.Web.Configuration.WebConfigurationManager
.ConnectionStrings["_IntrinsicData"].ConnectionString;
EntityConnectionStringBuilder builder = new EntityConnectionStringBuilder();
builder.Metadata =
"res://*/ApplicationData.csdl|res://*/ApplicationData.ssdl|res://*/ApplicationData.msl";
builder.Provider =
"System.Data.SqlClient";
builder.ProviderConnectionString = connString;
this.m_context = new ApplicationDataObjectContext(builder.ConnectionString);
}
return this.m_context;
}
}
#endregion
[Query(IsDefault = true)]
public IQueryable<EnhancedFlowerShopOrder> GetAllOrders()
{
// Get all the Orders
var colFlowerShopOrders = from Order in this.Context.FlowerShopOrders
// Shape the results into the
// EnhancedFlowerShopOrder class
select new EnhancedFlowerShopOrder
{
// The Order ID
ID = Order.Id,
// The Order Date
OrderDate = Order.OrderDate,
// The first name of the Customer
FirstName = Order.FlowerShopCustomer.FirstName,
// The last name of the Customer
LastName = Order.FlowerShopCustomer.LastName,
// The order Total
OrderTotal =
// Get all order details lines of the Order
(from FlowerShopOrderDetail in Order.FlowerShopOrderDetail
// Group the products in the Order Details
group FlowerShopOrderDetail
by FlowerShopOrderDetail.FlowerShopProduct into g
// Shape a new entity
select new
{
// Create a total property that is the Quantity times the
// Product price
TotalOrder = g.Sum(x => x.Quantity)
* g.Sum(x => x.FlowerShopProduct.Price),
}).Sum(x => x.TotalOrder) // Add the sum of all the TotalOrders
};
return colFlowerShopOrders;
}
// Override the Count method in order for paging to work correctly
protected override int Count<T>(IQueryable<T> query)
{
return query.Count();
}
}
}
Consume The WCF RIA Service
Build the solution.
(You will get a ton or warnings in the immediate window, you can ignore them)
In the Solution Explorer (of the LightSwitch project), right-click on the Data Sources folder and select Add Data Source.
Select WCF RIA Service.
Click Add Reference.
Click Browse…
Navigate to the WCF_RIA_Project.dll in FlowerShop/WCF_RIA_Project/bin/debug and select it.
It will display in the dialog box, select it and click OK.
Wait for the service to show up in the selection box, select it and click Next.
Check the box next to the Entities, and click Finish.
The Entity will display.
Display The Data
The WCF RIA Service will have its own node under Data Sources in the LightSwitch project.
That name plus “.svc” is used to navigate to the OData service.
We can now issue a simple query to access the data.
An Important Note About SSL
A production application must run on a webserver that has SSL enabled. Otherwise, a hacker with a packet sniffer can easily get the data and the usernames and passwords of your users who are connecting to your site using public Wi-Fi access points or other unsecure networks.
Also See
A Full CRUD DataJs and KnockoutJs LightSwitch Example Using Only An .Html Page
A Full CRUD LightSwitch JQuery Mobile Application
Calling LightSwitch 2011 OData Using Server Side Code
Using The OData Explorer with LightSwitch OData
Learn How To Make OData Calls In LightSwitch 2011
Accessing Your Visual Studio 2011 LightSwitch Application Using OData
Download Code
The LightSwitch project is available at:
http://lightswitchhelpwebsite.com/Downloads.aspx
9 comment(s) so far...
This is a wonderful article to get started with WCF RIA Services in lightswitch. Is it possible to get the routine: public IQueryable GetAllOrders() where the order is grouped by Order Date? Thanks so much for your contribution. Rachida
By Rachida on
7/9/2012 10:16 AM
|
@Rachida - Yes it is. Just change the Linq Query. Any site that describes grouping using Linq will be able to help you work out what you need.
By Michael Washington on
7/9/2012 12:38 PM
|
Thanks so much Michael for your fast response. Can you recommend any blog or book to learn RIA service for lightswitch. I added a seond routine like IQueryable GetAllOrders() with a different name, and rebuilt the whole solution but I got to the window called ( attach data source wizard), I can see only one entity EnhancedFlowerShopOrder, but NEVER the added routine. What I'm doing wrong? Thanks again. Rachida
By Rachida on
7/9/2012 2:57 PM
|
@Rachida - I don;t have a book to reccomend, but ANY book or article on WCF RIA Services will work. The WCF RIA Services are not LightSwitch specific.
As to the second method you added, I think you have to make sure you do NOT decorate it with "[Query(IsDefault = true)]".
By Michael Washington on
7/9/2012 3:09 PM
|
Thanks Michael again, Rachida
By Rachida on
7/9/2012 3:27 PM
|
******** Note: With the latest version of Visual Studio LightSwitch HTML Client you need to connect to "ApplicationDataObjectContext.cs", change "ApplicationDataObjectContext" (in the code) to "ApplicationData" and use: "using LightSwitchApplication.Implementation;" in the using statement section. ********
By Michael Washington on
4/11/2013 10:26 PM
|
How do add WCF RIA in VS 2013? There is no possibility to add a Domain Service Class
By blakcat76 on
11/20/2013 2:49 AM
|
@blakcat76: see: http://lightswitchhelpwebsite.com/Blog/tabid/61/tagid/21/WCF-RIA-Service.aspx
By Michael Washington on
11/20/2013 4:23 AM
|
Thanks Michael Washington
By blakcat76 on
11/20/2013 6:44 AM
|