Jan Van der Haegen
Visual Studio LightSwitch was initially released in mid-2011 as the easiest way to build business applications for the desktop or the cloud. Although it was soon adopted by many IT-minded people, some professional developers quickly concluded that LightSwitch might not be ready for the enterprise world. After all, a rapid application development technology might be a great way to start a new and small application now, but, unfortunately, history has proven that these quickly created applications don’t scale well once they grow large, they require a lot of effort to interoperate with existing legacy systems, they aren’t adaptive to fast-paced technological changes, and they can’t handle enterprise requirements such as multitenant installations or many concurrent users. On top of that, in a world of open standards such as RESTful services and HTML clients being adopted by nearly every large IT organization, who would want to be caught in any closed format?
With the release of LightSwitch 2012 coming near, I thought it was a perfect time to convince some friends (professional developers and software architects) to put their prejudices aside and (re)evaluate how LightSwitch handles these modern requirements.
The outcome? It turns out LightSwitch 2012 doesn’t just handle all of these requirements, it absolutely nails them.
LightSwitch is a designer-based addition to Visual Studio 2012 to assist in working with data-centric services and applications. When working with a LightSwitch project, the Visual Studio IDE changes to a development environment with only three main editors (in so-called “Logical mode”): the Entity Designer, the Query Designer and the Screen Designer. These editors focus on getting results quickly by being extremely intuitive, fast and easy to use. This adds some obvious benefits to the life of a LightSwitch developer:
Designing data with LightSwitch can be considered equivalent to creating domain models, in the professional developer’s vocabulary. The IDE first asks you about “starting with data,” specifically where you want to store this data. Two possible answers are available. You can choose to “Create new table,” in which case LightSwitch uses the Entity Framework to create the required tables in SQL Compact (when debugging the application), SQL Server or Azure SQL Database. Or you can choose to design your entities over an existing data source, such as SharePoint, an OData service, an existing database or a WCF RIA Services assembly. The latter two can really help you keep working on an existing set of data from a legacy application, but expose it through modern and open standards in an entirely new service or application.
As an example, you can take an existing OData service (an extensive list of examples is available at odata.org/ecosystem) and import one or multiple entities into a new LightSwitch application.
Figure 1 shows you how the Employee entity from the Northwind data source is first represented in the Entity Designer. With a few clicks and a minimal amount of coding effort where needed, you can redesign the entity in several ways (the end result can be found in Figure 2). These include:
Figure 1 The Entity Designer After Importing from an Existing OData Service
Figure 2 The Same Employee Entity After Redesign
LightSwitch understands a large set of commonly used business types such as E-mail Address and Phone Number, and more can be found in the many available extensions, or you can create your own business types via a LightSwitch extensibility project. With respect to the underlying data type, business types augment a property with specific characteristics such as specialized validation (for example, checking the E-mail or Web Address formats) and specific extended properties (Phone Number formats for Phone Number business types), and will often come with specialized controls used (by default) to represent or interact with the property in the client apps.
Entities are hardly ever totally unrelated. Using the Entity Designer, you can design relationships between different entities where needed. These relationships will be enforced on all layers—through code in the client and middle tier, and through foreign keys in the database when designing entities that will be stored in an intrinsic (a “new”) data source, such as SQL Compact, SQL Server or Azure SQL Database.
However, a truly powerful feature of LightSwitch is that you can define new relationships on existing data sources as well. This is especially handy when trying to move forward with existing sets of data, such as XML files or old and malformed databases without indexes, keys or proper relationships. These so-called virtual relationships will be enforced in the client and on the middle tier without actually having to alter the legacy data source. Even more powerful is that these virtual relationships can be defined between entities in different data sources.
For example, by right-clicking on Data Sources in Solution Explorer and selecting Add Table, you can create a new Holiday entity that will be stored in a new database, which has virtual relationships with the Employee entity from the Northwind OData service (see Figure 3).
Figure 3 Virtual Relationships over Different Data Sources
Creating a holiday tracker application this way is a great example of how LightSwitch helps you break the boundaries of using data in just one application to provide additional value in another.
LightSwitch tries to keep the amount of code needed to get started to an absolute minimum, which speeds up initial development tremendously. Before a data service truly is ready to be exposed, it will often need some tweaks and modifications to shape the business inside the data. This is often easier to express in code than through the editor.
For every imaginable event, LightSwitch has an extension point that can be accessed from the Write Code button in the designer (see Figure 4). Depending on whether your code will be called on the server, in the client or on both tiers, this will generate a method stub where you can implement your custom code in either the client, common or server subproject of a LightSwitch project.
Figure 4 LightSwitch Supports Many Extension Points
Continuing the example of the holiday tracker application, you could use these code extension points to initialize an entity. For example, the following code will automatically assign an employee’s supervisor as the person to approve the holiday, or approve the holiday if the person has no supervisor:
public partial class ApplicationDataService
// Initializing a new Holiday - server only
partial void Holidays_Inserting(Holiday entity)
if (entity.Employee.Supervisor != null)
entity.ApprovalBy = entity.Employee.Supervisor;
entity.Approved = true;
Similarly, these code extension points can help you write custom validation code beyond what the business type of the property already validates:
public partial class Holiday
// Determine if an "EndDate" is valid - executes client and server
partial void EndDate_Validate(EntityValidationResultsBuilder results)
if (StartDate > EndDate)
results.AddPropertyError("End date must follow the start date");
Besides custom validation and business rules, LightSwitch also ships with a built-in, optional access control model based on roles and permissions. Checking access control can be done from these code extensibility points as well, both vertically and horizontally.
Vertical access control is where you’d impose limitations per screen, entity or property based on the permissions of the currently logged-in user. For example, the following code would limit the approval process to only those employees within a particular department of the organization, such as human resources:
public partial class Holiday
// Determine if "Approved" can be modified by the user -
// executes client and server
partial void Approved_IsReadOnly(ref bool result)
result = !Application.User.HasPermission("ApproveHolidays");
Horizontal access control is where you’d filter which records are visible to the end user. Note that this code runs on the server tier, meaning data that’s not allowed to be accessed by the end user is never sent through the wire:
public partial class ApplicationDataService
// Filtering out records - runs on the server only
partial void Holidays_Filter(ref Expression<Func<Holiday, bool>> filter)
filter = holiday => holiday.Employee.NameSummary ==
Application.Current.User.FullName == holiday.ApprovalBy.NameSummary;
Horizontal access control, also called row-level security, is an important addition to LightSwitch in Visual Studio 2012.
First, the filter is executed on the server. This restricts the amount of data that can be needlessly transferred per call because the user isn’t allowed to interact with these rows in the first place. In vertical access control, the end user will still see the data, even if he can’t interact with it because the controls are read-only or exceptions are thrown in the case of violating actions. However, in the case of horizontal access control, the excess data is completely hidden from the end user.
This brings us to another powerful use for row-level security: It can grant ownership of parts of the entire data set only to particular users or organizations. This allows you to create an application that only needs to be installed once, and you can provide access to different groups, companies, individuals or organizations. Each of them acts as a tenant in that they all use the same client application and the same services, but only own a slice of the data. These multitenant installations tremendously lower hosting costs for all parties and offer other benefits such as the ability to update just once in one central location, such as the cloud. Those who had the pleasure of spending hour after hour dialing in to on-site servers to update installation after installation of an urgent hotfix will probably be the first to acknowledge the power of these multitenant capabilities in LightSwitch 2012.
When thinking about the value of the data a company collects, many tend to think about it only in terms of the product that uses the data. However, collecting and analyzing broad categories of data is becoming more valuable than ever. When freed from the silo of a single application and treated correctly, analyzing and mining data can provide additional revenue beyond the traditional product-based business model. For this to work, it’s important to embrace open standards, such as the OData protocol that’s used on the service that’s automatically built when building a LightSwitch project.
Here’s a summation of OData from odata.org:
“OData, short for the Open Data Protocol, is a Web protocol for querying and updating data … OData does this by applying and building upon (open) Web technologies such as HTTP, Atom Publishing Protocol and JSON … OData is consistent with the way the Web works—it makes a deep commitment to URIs for resource identification and commits to an HTTP-based, uniform interface for interacting with those resources (just like the Web). This commitment to core Web principles allows OData to enable a new level of data integration and interoperability across a broad range of clients, servers, services and tools.”
In other words, OData is implementing a service that can be interacted with through the use of simple HTTP verbs and resource identifiers (or URLs). An OData service can be consumed from almost any client technology, and in its simplest use, this means the service can even be browsed with an HTTP “Get” request from a Web browser, for example, by typing the following in as the Web address:
Such a URL is always composed of the service root URL (the endpoint of the service), a resource path (the name of the entity) and, optionally, query options. Note that the latter makes the service itself quite agnostic of the use case; the OData protocol has an extensive query language that can be used to sort or filter data via the URL however the caller needs it. You can find the full set of operators at bit.ly/LSiPAj.
When you’re designing the LightSwitch data service and you’re aware of how the data will be consumed, you can also take advantage of the Query Designer to create queries before publishing, for your own convenience. Figure 5 shows a simple query that returns only the unapproved holidays that start during the current year. Note how the source of the query is the entire Holidays set, which will, of course, be prefiltered by the filter I set in the code earlier.
Figure 5 Using the Query Designer for a Simple Query
After spending some time in the Entity Designer and Query Designer, you can have an OData service ready to be deployed. This can be done directly from the Visual Studio IDE by right-clicking on the LightSwitch project in Solution Explorer and choosing the “Publish…” option from the context menu.
This brings up the LightSwitch Publish Application Wizard (see Figure 6), with which you can set up some final application-specific properties such as required connections strings, authentication types (none, username and password combination, or Windows authentication), an application administrator account and the destination of your installation (which can be an installation package or entail directly publishing to IIS or Azure from the IDE). This last option especially has seen some tremendous improvements over the past couple of months, which makes deploying your data service to the cloud a fast and worry-free experience.
Figure 6 The LightSwitch Publish Wizard
By adopting an open standard, the set of clients that can be used to interact with this data service is one that almost every end user will have available already. Spreadsheet applications such as Microsoft Excel allow the data service to be consumed and turned into PowerPivot tables and graphs without any coding required (see Figure 7). (Note: PowerPivot, built-in to Office 2013, is a separate, free add-on to Office 2010.) You can find a step-by-step walk-through about this at bit.ly/xETG0V.
Figure 7 Consuming a LightSwitch OData Service in Excel
Another key benefit of LightSwitch is that you can use the same IDE experience to build client applications. LightSwitch supports both thick clients (Silverlight 5, in-browser or out-of-browser) and mobile companion applications (HTML5) with the same design speed it provides on the server side, or even faster. Note that the ability to create HTML5 apps is only available in the preview release, but will be available as an add-on after the final Visual Studio 2012 release.
To get started, click the Add Screen button in either the Entity Designer or Query Designer. This will bring up a wizard where you can select a screen template, which can either be one of the many built-in templates or one you’ve created yourself or downloaded from the available extensions.
As you can see in Figure 8, the application is clean, intuitive and fully functional. However, don’t let the ease with which it was created trick you into believing it’s anything but complete. For example, under the covers, it uses an advanced version of MVVM, based on runtime interpretation of metadata, which I covered in an online April 2012 article, “The LightSwitch MVVM Model” (msdn.microsoft.com/magazine/hh965661). Because of this, the Screen Designer that was used inside Visual Studio to do the initial design can be brought up inside the application by clicking the design screen link at the bottom right, so you can make further modifications to the view metadata while the application is running in debug mode. These modifications can then be persisted back to the project.
Figure 8 A Simple LightSwitch Client Application
While further exploring the LightSwitch client architecture, you’ll find there are many more technological wonders to discover. For example, controls or screens will automatically become read-only or hidden if you lack the permission to edit the underlying entity.
Equally convenient is that you no longer need to worry about raising NotifyPropertyChanged events yourself to get your bindings to function correctly. If the end user changes an employee entity’s family name property, for example, a control bound to a computed fullname property (based on the family name property, of course) will automatically be updated to display the new value.
Speaking of changing a property: All of the models used in the client are actually “dual-dispatcher objects” to help keep the UI responsive while processing business logic. From the UI thread, you can do a simple assignment of a value to a property. This will internally send a notification that’s picked up on a weighted priority basis in a second thread, called the logical thread. Once the business logic has finished processing, the same event-notification system is used to inform the UI thread of the eventual end result and update the UI accordingly.
One last interesting fact I wanted to share about the client comes from the very active Visual Studio LightSwitch Team Blog, where it’s explained that each screen actually represents a unit of work (see bit.ly/9vENdF). Each screen has its own data workspace, which it shares with any child screen opened by that initial screen, such as pop-ups or an entity’s detail screen. All changes are kept locally until the end user decides to save or discard all of them. This means that by opening a screen twice (allowing multiple instances is disabled by default but can be enabled in the Properties window from the screen designer), you can simulate how LightSwitch handles different users making concurrent modifications on some data and then saving them at the same time (see Figure 9).
Figure 9 Handling Concurrent Modifications
If you’re wondering how well LightSwitch handles this, as I said in the introduction, it doesn’t just handle all of these requirements, it absolutely nails them.
Jan Van der Haegen is a green geek who turns coffee into software. He’s a loving husband, a proud scrum master of an international team at Centric Belgium, and so addicted to learning about any .NET technology—Visual Studio LightSwitch in particular—that he maintains a blog on his coding experiments. You can find his latest adventures at switchtory.com/janvan.
Thanks to the following technical experts for reviewing this article: Joe Binder and Beth Massi