LightSwitch Architecture: OData (John Rivard)

LightSwitch Architecture: OData (John Rivard)

Rate This
  • Comments 18

In Visual Studio 2012, LightSwitch data services publish OData feeds and LightSwitch clients consume the OData feeds. This is an implementation change from LightSwitch 2011 where we used WCF RIA Services as the data protocol between client and server.

In this post we’ll take a look at the OData protocol itself and why it is valuable to LightSwitch applications. And we’ll cover a lot of ground related to producing and consuming OData feeds with LightSwitch, including the ability to consume LightSwitch OData feeds from non-LightSwitch clients.

What is OData?

OData is an open REST-ful protocol for exposing and consuming data on the web. It attempts to break down the silos of data that are common across the web by standardizing on the way that data is accessed. Instead of requiring application-specific APIs to access data specific to each application’s web service, OData provides a common way to query and update data via REST. Beth Massi has already published a good introduction to OData and LightSwitch:

Enhance Your LightSwitch Applications with OData
Creating and Consuming LightSwitch OData Services

Why OData?

By moving the LightSwitch middle-tier services to OData we open up the LightSwitch to a growing ecosystem of OData producers and consumers. A LightSwitch application no longer lives in a silo.

This adds more value to your LightSwitch investment. In addition to the LightSwitch client, you can also connect to your LightSwitch data feeds from applications like Microsoft PowerPivot, or from a Browser or Windows 8 JavaScript client using the open-source datajs library.

OData allows LightSwitch applications to consume more data sources. There is a growing list of live services and systems support the OData protocol. Some interesting producers for business applications include SAP NetWeaver Gateway and SQL Server Reporting Services.

OData Basics

OData is a a REST protocol based on existing internet standards including HTTP, AtomPub, JSON, and hyper-media design patterns. A main feature of REST APIs is the use of existing HTTP verbs against addressable resources identified in the URI. Conceptually, OData is a way of performing database-style CRUD using HTTP verbs:

Create : POST
Read: GET
Update: PUT
Delete: DELETE

The URI specifies the resource (entity set or entity) and the body of the request or response encodes the entity data in AtomPub or JSON format. The top level resource in an OData feed is an entity container. The entity container has one or more entity sets. An entity set contains instances of entities of a given entity type. Entity sets are analogous to Lists or Tables. Entities within the entity set can be addressed individually via key values, or as collections via query options.

OData specifies URI conventions for addressing entity sets, individual entities, and paths to linked entities via navigation properties. It also specifies a simple query language that allows a client to request arbitrary filtering, sorting, and paging. The entity data is encoded in the body of the request or response using uniform AtomPub or JSON formats.

OData is strongly typed. It uses the Entity Data Model (EDM) to describe the entity types, entity sets, and entity relationships in the entity container. The data schema is typically referred to as  the metadata. A live OData feed can return a metadata document so that any consumer can discover the resources available and can use the protocol’s URI conventions to address them. 

Examples:

(TIP: Your browser might have formatted feed reading enabled. To see the XML formatting for these links, turn off feed reading in your browser options.)

You can learn a lot more about OData at www.odata.org.

Producing OData Feeds with LightSwitch

LightSwitch automatically publishes one OData feed per data source that you create or attach to in your LightSwitch project. There is no additional configuration or coding required. LightSwitch exposes the same data model that you define using the LightSwitch entity designer.

Mapping the LightSwitch data model to OData is trivial because both LightSwitch and OData are based on the EDM type system. The entity types, relationships, entity sets and queries that you define in LightSwitch are exposed as resources in the OData feed.

LightSwitch Element OData Element
Product entity Product entity type
Product.Category navigation property Product.Category navigation property
Products table Products entity set
AvailableProducts query AvailableProducts function import

As you can see, there is a fairly direct correspondence between the LightSwitch elements and the corresponding OData elements.

When you publish your LightSwitch application, LightSwitch uses the data source name to construct the base feed URL. By default the “intrinsic” data source is called “ApplicationData”. This is created when you define hew tables in the LightSwitch Data Designer. LightSwitch will use “/ApplicationData.svc” as the feed URL. If you attach to an external SQL database and call the data source “NorthwindData”, LightSwitch will use “/NorthwindData.svc” as the feed URL. To access the Products table in the NorthwindData data source, you’d construct the URL using your web-sites base address.

http://www.contoso.com/NorthwindData.svc/Products

During F5, these services are addressable via http://localhost at port number selected by the project. This port number will be visible in the Browser URL and in the Windows tray icon. Say the port number is 1234. You can view the OData metadata for your ApplicationData at the following URL.

http://localhost:1234/ApplicationData.svc/$metadata

Securing LightSwitch OData Feeds

Opening your application data via OData raises the obvious question: How do I secure access to my application data?

You can turn on access control for LightSwitch applications using the project settings. LightSwitch supports three authentication settings: None, Forms, and Windows.

When you select Forms, LightSwitch enables two modes of authentication. One is a custom protocol used by the LightSwitch clients Login dialog. This uses a custom web service API to pass credentials and obtain a forms-authentication cookie. If a request for data doesn’t have a valid forms-authentication cookie, LightSwitch will respond with an HTTP Basic challenge. This allows non-LightSwitch clients to pass credentials via a standard HTTP protocol.

If you choose Windows authentication, LightSwitch will require an authenticated Windows user. This works great for in-house applications. LightSwitch doesn’t currently support this option for Azure-hosted services, although you can configure ADFS manually outside of LightSwitch.

Whatever authentication mechanism you use, you should considering transport-level security, via HTTPS, to secure any credentials, tokens, and data that pass on the wire. Without HTTPS, forms and basic credentials will pass in clear text, as will forms-authentication tokens. Windows authentication is more secure, but without HTTPS, any data flowing between client and server will still be clear text. To mitigate this, LightSwitch has a publish setting that causes the runtime to require a secure connection.

security settings

With this setting On, LightSwitch will redirect requests from HTTP to HTTPS. But you still need to obtain and configure the HTTPS certificate on your web site.

This version of LightSwitch doesn’t provide a direct mechanism for hiding or excluding entity sets or entity properties from the OData endpoint. Whatever you connect to on the back-end will be visible on the front-end of your service. You can control access to those resources by using the CanXxx access control methods in your data service code. We have also added true row-level filtering in this release using the entity_Filter query method, so you can filter out any or all entities from escaping the service interface. Unfortunately, we have no column-level filtering, so a client will either get all or none of the entity.

Here is an example of how to prevent all Update, Delete and Insert from the Animals table.

can_xxx listing

Consuming LightSwitch OData Feeds from Non-LightSwitch Clients

The OData protocol isn’t specific to .NET or Microsoft. OData feeds published by LightSwitch can be consumed by any OData client on a variety of platforms. By using HTTP Basic authentication, most existing clients will be able to attach to your feed securely.

The two main opportunities this opens up for LightSwitch developers are generic OData clients and custom OData clients.

Many new products like Microsoft PowerPivot and Microsoft Codename “Data Explorer” are generic OData consumers. They are designed for ad-hoc query and analysis of OData feeds. You’ll find several more from on the OData ecosystem web site.

You can also author your own custom clients for whatever platforms and devices your solution requires. The OData SDK has client libraries for a variety of popular platforms including JavaScript, PHP, Java, Ruby, and Objective-C.

Attaching to External OData Feeds

You can attach to external OData feeds as data sources in your LightSwitch projects. When you attach to another OData feed, LightSwitch fetches the $metadata and imports the external data schema into your LightSwitch project. LightSwitch will list any unsupported data elements at attach time and will not import these into the LightSwitch project. Unfortunately, these data elements will be unavailable to your LightSwitch application. (See Protocol Support below.)

Some OData producers are known to work well with LightSwitch. These are SharePoint 2010 (using the SharePoint option at in the Attach dialog), most feeds produced in Visual Studio with WCF Data Services and Entity Framework, and of course feeds produced by LightSwitch.

Not all OData feeds in the wild support the same level of functionality. Some don’t support pagination, or sorting, or certain kinds of query filters, features that screens use by default. We are still working out the best way to give a great experience using these feeds. Our current thinking is to disable a lot of the built-in query functionality for unknown OData feeds. The developer can progressively turn these features back on after experimenting with the feed and determining what works and what doesn’t.

In the meantime, the LightSwitch team is working with the OData community to find better ways for arbitrary consumers to negotiate capabilities with arbitrary feeds. We are big fans of OData and we want to improve the experience for LightSwitch customers and for other products that adopt OData.

Upgrading from LightSwitch 2011

It was a design principle in LightSwitch 2011 to hide the data-access implementation details, to avoid lock-in to any one data access technology. That decision as paid off. The LightSwitch engineers were able to re-plumb both the LightSwitch client and server using OData and to maintain an extremely high degree of compatibility with earlier APIs and runtime semantics. We replaced our earlier dependency on WCF RIA Services with WCF Data Services (the .NET implementation of OData). We considered the prior WCF RIA Service endpoints to be private, so they no longer exist, but that shouldn’t break anyone. On the server, they are replaced with public OData endpoints.

When you upgrade to Visual Studio 2012, your data model remains the same and any entity and data service pipeline code you wrote stays the same. LightSwitch simply changes the code-generation for the underlying plumbing to use OData instead of WCF RIA Services, as well as updating the LightSwitch runtime libraries.

You might be wondering about custom data sources. Did these go the way of the dodo when we took out WCF RIA Services as our service endpoint? No, we still support using the WCF RIA Services DomainService as a back-end data adapter. These will upgrade and continue to work as-is.

Implementation Details

If you’re interested in some low-level details, I’m going to look at the features of the OData protocol that LightSwitch supports, the general runtime architecture, and some client-side optimizations that enhance our use of OData.

OData Protocol Support

OData has published v2.0 of the protocol and has recently announced OData v3.0. The v3.0 protocol isn’t yet finalized and LightSwitch isn’t taking advantage of any v3.0 capabilities.

LightSwitch supports a broad set of the OData 2.0 capabilities:

Data Types Most primitive EDM data types, entity types
Relationships Associations, navigation properties, links
Feed Formats atom, json
Query Options Filtering, sorting, paging, count, selection, expansion
Query Expressions OData comparison operators; OData string, date, and math functions
Update and Batch http put, patch, delete, post
Concurrency Control ETags and If-Match headers

There are certain OData v1.0 and v2.0 features that LightSwitch doesn’t support. These include the DataTimeOffset data type, complex types, inheritance, many-many relationships, media resources, open types, and custom service operations. Each of these has value in certain scenarios. We haven’t excluded any of these on principle or merits. It is just a matter of resources and investment to get new scenarios lit up. 

Runtime Architecture

The overall architecture of the LightSwitch client and server doesn’t change too much from LightSwitch 2011. The simplified architecture stacks for client (presentation) and server (logic) tiers now look like the following:

clip_image005odata arrowclip_image006

Note that for LightSwitch 2011 you would have seen WCF RIA Services playing a prominent role in both the client and the server. You’ll see that these are simply replaced by WCF Data Services.

Client Optimizations

Under the hood, we did a lot to ensure that our use of OData maintained compatibility and is as efficient as possible. The OData protocol allows a client to request which related entities should be included in a query by using the $expand option. To avoid server round trips when loading screens, LightSwitch automatically expands screen queries to include related entities that are used in the screen—for example, including the customer and the order lines with the order record. The screen designer has advanced options where you can explicitly control this.

Another optimization we made is to include a RowVersion property for LightSwitch entities. OData uses ETags to handle data concurrency. These ETags can get large if they include original values from all of the entity properties—sometimes too large to fit in the request headers. By using RowVersion, we shrink the ETag to just one property value, while maintaining full support for concurrency checking and resolution. The introduction of a RowVersion also makes concurrency more robust because all properties are considered whereas in the past we excluded potentially large values like text, binary, and images.

Summary

The OData protocol is great for cross-platform data interoperability—whether inside your corporate network or on the internet. LightSwitch allows you to consume OData feeds and mash them up together with SQL Server data, SharePoint data and other OData feeds. LightSwitch applications automatically expose application data as OData feeds, so even non-LightSwitch clients can consume your application data. This opens up the opportunity of connecting your LightSwitch application with a variety of devices—HTML/JavaScript, iOS, and Windows 8 just name a few.

The LightSwitch data pipeline lets you publish OData safely. You can secure your feeds via HTTPS and use LightSwitch access control mechanisms like Basic and Windows authentication and permissions-based authorization. You can use the LightSwitch query and update pipelines to control access to data, keep the data clean, and manage business rules—regardless of which client is using the data.

Feedback

How will you use OData with LightSwitch in your business applications? What new scenarios can you accomplish? What else do you need in OData in specific and data access in general? Give it a try, and let us know what you think!

John Rivard, LightSwitch Team

Leave a Comment
  • Please add 5 and 8 and type the answer here:
  • Post
  • Thank you for this.

  • Very helpful, thanks!

  • Thanks for this.

  • Very good article.

  • Good, basic explanation of how to start with the OData application in LightSwitch.

  • Hi John,

    Great article. John LS odata is not returning Json format. Could you please help me or instruct me how to get json format odata using LS 2011 Beta. I would like to use  in another application using jason format odata.

    Rama

    rama@shoppersstop.com.au

  • @Rama, you have to add the following HTTP header to your request:

    Accept: application/json

    The OData spec also mentions $format=json query option as an alternative mechanism, but that option is not supported by WCF Data Services, which LightSwitch is using under the covers.

    Hope that helps!

    Karol

  • Step 1: I develop the application in C# or VB without persistance layer. Usually realtime stuff or simulations.

    Step 2: I add a persistance/DB layer using EF Code First.

    Step 3: From this I generate the data management/data entry app using LightSwitch. From this angle EF TPC looks best.

    Step 4: My app acts as a singleton in-memory data structure and acts as an OData server.

    Step 5: Android smartphones use OData to access the server.

    Step 1 to 5 has been used throughout the last months.  

    Step 6: Future dedicated Lightswitch apps will access my server app (ie Business Logic)  using OData.

    There are many small and big wishes which I have all posted to the appropriate forums. Common to all product borders is the absence of enumeration handling both in the EF metadata table as well as in OData. Lightswitch lookup tables and enumerations are not the same. Lightswitch does not know which implicit rules Entity Framework uses.

    Furthermore more WCF behaviours needs to go into OData, which then must be reflected in all OData client code and server code generators. So far both OData and Lightswitch is made for plain vanilla business apps. Not for realtime stuff, high performance stuff, event-driven stuff.

    Biggest problem when talking to prospective customers: Will Silverlight survive, cause if not, then Lightswitch is dead too. Will Lightswitch output Metro/HTML5 in a future release?

    In general: The above mentioned process, using EF CF to gen the DB and Lightswitch to gen the basic application saves a *lot* of development time. Learning time is minimal. I really don't know any alternative. I can do what I am paid for: concentrate on my domain knowledge.

    You did great work! Thank you and please keep going!

  • Karol,

    coudl you please tell me how to add HTTPHeaders for LightSwitch Odata service?

    I understand that we should submit few more parameters i.e $format=json but how we can add headers in LS published Odata by default it is Atom.

  • Rama, check out this blog post:

    blogs.msdn.com/.../what-happened-to-application-json-in-wcf-ds-5-0.aspx

    It describes the current level of JSON support in WCF DS 5.0 (this is what LightSwitch 2012 uses) and has a little datajs example at the end that shows how to make a service built on top of WCF DS return a JSON response. This should be enough to get your JavaScript-based client to work. If you are using some other client technology, you will have to use different API of course, but it should be as simple.

    Hope that helps!

  • I just have a question around updates that require multiple operations: if each OData-based operation is an HTTP Verb executed with a single resource (like POST to insert a new Order, and PUT to Update the available qty of a product, or say a client adds a new product, as well as a new category for that new product), does that mean when one calls SaveChanges, each of these would be a separate network call to the OData Service, using the required POST / PUT http operations on the relevant URI's?

  • Shawn, good question. As it turns out, the OData protocol allows you to POST to the root service URI plus a special token "$batch", which basically means that the content of the request contains one or more nested operations including the appropriate HTTP verb and information about the entity being updated. So, there is only one network call when you save changes, regardless of the size of the change set.

  • How I Can publish a:

    SERVER A: LightSwitch Application

    SERVER B: RIA SERVICE

    SERVER C; SQL SERVER DATABASE

    How i can link the RIA SERVICE Located in SERVER A with the LightSwitch Application Located in a SERVER B

    Please and thanks for your recommendattion

  • Carlos, LS does not support this configuration directly. RIA services are designed to be accessed primarily by SL clients, and not by ASP.NET server-side code (running inside LS middle tier). While it is technically possible to call a RIA service from the middle tier (make a network call), it is quite hard to do and VS/LS do not help you with that (e.g. there is no service proxy generator for server-side code).  

    My suggestion would be to develop an OData-based, alternative endpoint for your service that is currently available via RIA protocol. LS middle tier can consume OData services directly -- see John's "Attaching to External OData Feeds" paragraph above, so once this alternative endpoint is in place, it should be very little work to consume it from your LS application and the topology would be exactly like you described.

    Hope that helps. Karol

  • Hello Fourm Member,

    Can anybody telling me somthing about decompil proces in Lightswitch.

    How can i make Erorr file and how can i fix it after publishing , please its ergent.

    Thanks

Page 1 of 2 (18 items) 12