An End-To-End LightSwitch HTML Example
Note: See the updated Visual Studio 2013 version here: An End-To-End Visual Studio LightSwitch 2013 HTML5 Application
Live Demo: https://endtoendexample.lightswitchhelpwebsite.com/Client/default.htm (use your username and password from http://LightSwitchHelpWebsite.com)
In this article we will create an end-to-end HTML application in Visual Studio LightSwitch. The purpose is to demonstrate how LightSwitch allows you to create professional business applications that would take a developer days to create. With LightSwitch you can create such applications in under an hour.
You can download LightSwitch at: http://www.microsoft.com/visualstudio/en-us/lightswitch.
The Scenario
In
this example, we will be tasked with producing an application that
meets the following requirements for a order tracking system:
- Products
- Add Products
- Edit Products
- Delete Products
- Orders
- Add Orders
- Edit Orders
- Add Order Details
- Edit Order Details
- Delete Order Details
- Delete Orders
- Business Rules
- Allow the current user to only see their orders
- Show the number of orders for the current user
- Allow an Administrator to see all orders
- Features
- Display the number of orders for a User
Creating The Application
Open Visual Studio and select File, then New Project.
Create a new LightSwitch HTML Application (note you must have the LightSwitch HTML Client installed).
The application will be created.
Right-Click on the Server node in the Solution Explorer and select Add Table.
Click on the table name to edit it.
Change the table name to Product.
Also, add ProductName and ProductPrice fields to the table.
Click the Save button to save the table.
Create an Order table (with the fields in the image above).
Create an OrderDetail table (with the fields in the image above).
Create Relationships
You will always want to make relationships when tables are related. This allows for optimal LightSwitch
application construction. When creating queries, having relationships
defined allows you to simply type a period (“.”) and traverse from one
entity to another. This saves a lot of coding work and reduces coding
errors.
When creating user interfaces, defining relationships allows you to save a lot of coding work because LightSwitch will be able to automatically associate, for example, Order Details with their associated Order.
Click on the Relationship button to create a relationship between the Order Detail and the Product table.
A box will appear. Select Product for the To table and click OK (ensure the other fields match the image above).
You will see that a relationship has been created. you can double-click on the line to edit the relationship.
Click on the Relationship button again and make a new relationship to the Order table.
Create a Filter
One
feature we are required to implement is to only show a user their own
orders (and allow an administrator to see all orders). We must keep in
mind that all LightSwitch applications expose all data via OData so we must always set security in the server-side code not only in the client-side code (such as the HTML or Silverlight LightSwitch clients).
The first thing we need to do is turn on security.
Next, we open the Orders table and select Write Code, then Orders_Filter.
Use the following code for the method:
partial void Orders_Filter(ref Expression<Func<Order, bool>> filter)
{
filter = (x => x.UserName == this.Application.User.Identity.Name);
}
All data that access this table will pass through this filter.
Set Defaults
Keeping in mind that we must set everything that relates to security
in server-side code, we realize that marking orders with the UserName of the current user must be set using server-side code.
Open the Orders table and select Write Code, then Orders_Inserting. Use the following code for the method:
partial void Orders_Inserting(Order entity)
{
entity.UserName = this.Application.User.Name;
}
Do the same for the Orders_Updating event.
Later, we will also set the UserName using client-side code, however, the server side code will always run and overwrite any value set client-side.
Create a Query
Another feature we are required to implement is to show the number of
orders for the current user. We will make a query that we can later
consume from the client-side.
Right-click on the Orders table and select Add Query.
Name the query OrdersForUser by clicking on the title and editing it. Save it first, then select the OrdersForUser PreprocessQuery.
use the following code for the method:
partial void OrdersForUser_PreprocessQuery(ref IQueryable<Order> query)
{
query = query.Where(x => x.UserName == this.Application.User.Identity.Name);
}
Create The User Interface For Products
We will first create a screen that will allow us to see Products.
Right-click on the Client node in the Solution Explorer and select Add Screen.
Create a Browse Data Screen using the Products table.
The screen will be created.
We will now create a screen that will allow us to edit a Product that is selected.
Click on the Products List and in its Properties select the Item Tap action.
Select Choose an existing method, choose editSelected.
We will now connect the Browse Data Screen to a new Edit Screen.
For Navigate To, select (New Screen…) and click OK.
The Add New Screen box will show. Select only the Product Details and click OK.
The screen will be created.
Now we will add a button that will create a new Product.
Return to the Browse Products screen.
Select the Command Bar, then Add then Choose an existing method, then AddAndEditNew.
For Navigate To, select Add Edit Product (the screen created in the earlier step) and click OK.
Hit F5 to run the application.
Click the ADD PRODUCT button to add a Product.
Add a product and click the Save button to save it.
The products will show in a list.
Create The Main Page
We will now create the Main screen
Create a new screen called Main using the Orders table for Screen Data.
Select the Item Tap action for the List control.
We will now connect the screen to a new Edit screen.
For Navigate To, select (New Screen…) and click OK.
The Add New Screen box will show. Select the Order Details and Order OrderDetails and click OK.
The screen will be created.
Format The Add Edit Order Screen
Change the User Name Text Box to a Text label.
We will now allow the user to select an Order Detail and edit it in a new screen.
Click on the Order Details List control and then click on the Tap action in its Properties.
Select OrderDetails.editSelected and then Navigate To: (New Screen…).
The Add New Screen box will show.
Select the OrderDetail Details and click OK.
The screen will be created.
Format The Add Order Detail Edit Screen
Right-click on the Rows Layout for the Order dropdown and Delete it.
We don’t need to show the Order (and allow it to be changed) because it will be set by the time the user gets to this screen.
We will return to this screen later to add a delete button. That delete button will require custom JavaScript and we will show how to do that later.
Therefore, we are done with this screen for now.
Create an Add Order Detail Button
We will create a button to allow the user to add a new Order Detail.
Return to the AddEditOrder screen.
Open the Command Bar for the Order Details Tab.
Select Add to add a new button.
In the Add Button popup, select OrderDetails.addAndEditNew and Navigate To: Add Edit Order Detail (the screen you created in the earlier step).
Create an Add Order Button
We will create a button to allow the user to add a new Order.
Return to the Main screen.
Open the Command Bar.
Select Add to add a new button.
In the Add Button popup, select Orders.addAndEditNew and Navigate To: Add Edit Order (the screen you created in the earlier step).
In the Solution Explorer, right-click on the Main page and select Set as Home Screen.
Setting Default Values
If we run the application, and click the Add Order button…
… and try to create an Order it wont save.
We are missing the User Name. We have already added code to overwrite the User Name with the current user, but since we made it a required field, it must still be supplied. We could just make the User Name field a text box and allow the user to type it in, but we can use ServerApplicationContext to insert it client side automatically.
See the following article for a step by step tutorial: Retrieving The Current User In The LightSwitch HTML Client.
Using Server Application Context
We will now create a file handler that will use the Server Application Context API to retrieve the currently logged in user’s User Name. We will then call that handler from JavaScript code on the client-side, to fill in the value on the screen.
In the Solution Explorer, click on the project and switch to File View.
Right-click on the Server/Web folder and select Add then New Item.
Create a new Generic Handler.
(note: you must create the file from scratch so
that the proper references are added to the project. If you simply copy
and paste, or drag and drop the file into the project, it will not
work.)
Use the following code for the file:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace LightSwitchApplication.Web
{
public class GetUserName : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
using (var serverContext = ServerApplicationContext.CreateContext())
{
context.Response.ContentType = "text/plain";
context.Response.Write(serverContext.Application.User.Name);
}
}
public bool IsReusable
{
get
{
return false;
}
}
}
}
Switch back to Logical View, open the Order table, select the Client (tab), Write Code, and then the created method.
Use the following code for the method:
myapp.Order.created = function (entity) {
entity.OrderDate = new Date();
msls.promiseOperation(CallGetUserName).then(function PromiseSuccess(PromiseResult) {
entity.UserName = PromiseResult;
});
};
function CallGetUserName(operation) {
$.ajax({
type: 'post',
data: {},
url: '../web/GetUserName.ashx',
success: operation.code(function AjaxSuccess(AjaxResult) {
operation.complete(AjaxResult);
})
});
}
(note: see Using Promises In Visual Studio LightSwitch for more information on using the msls.promiseOperation)
When we run the application, the User Name and Date are now set to their default values when a new record is created.
You will now be able to create and save records.
Formatting Output
When we look at the Order Details, we see that it is not formatted the way we want.
We return to the Add Edit Order screen and change the Order Detail Summary control to a Custom Control.
In the Properties for the control we select Edit Render Code.
We use the following code:
myapp.AddEditOrder.RowTemplate_render = function (element, contentItem) {
contentItem.dataBind("value.Product.ProductName", function (newValue) {
element.innerHTML = "";
var itemTemplate = $("<div></div>");
var ProductName = contentItem.value.Product.ProductName;
var ProductQuantity = "";
if (contentItem.value.Quantity !== undefined) {
ProductQuantity = ' [' + contentItem.value.Quantity + ']';
}
var FinalName = $("<h2>").text(ProductName + ProductQuantity);
FinalName.appendTo($(itemTemplate));
itemTemplate.appendTo($(element));
});
};
(note: for more information about Promises see: Using Promises In Visual Studio LightSwitch.
Also see: Writing JavaScript That Implements The Binding Pattern In Visual Studio LightSwitch)
When we run the application, the output is formatted as we desire.
Calling A Custom Query
Next, we will call the query we created earlier.
Open the Main screen, select Add Data Item, and create a Integer property.
Drag and drop the property from the View Model to the screen layout.
In the Properties, make the label Left-aligned.
To set the value for the property, select Write Code, then the created method.
Use the following code:
myapp.Main.created = function (screen) {
myapp.activeDataWorkspace.ApplicationData.OrdersForUser().execute().then(function (results) {
var TotalCountOfOrders = CountOrders(results);
screen.TotalOrdersForCurrentUser = TotalCountOfOrders.toString();
});
};
function CountOrders(Orders) {
var TotalOrders = 0;
var orders = Orders.results;
orders.forEach(function (order) {
TotalOrders = TotalOrders + 1;
});
return TotalOrders;
}
When we run the application we see a count of the Orders.
Easy Formatting
When we look at the Main screen, we see that it shows the User Name and we would like to show the Order Date.
In Visual Studio, open the Main screen.
Change the Order Summary control to a Rows Layout.
Right-click on the User Name label and delete it.
When we run the application, we will see the Order Date.
Deleting A Record
Open the Add Edit Order Detail screen and add a button to the Command Bar.
Make a Delete method for the button.
Right-click on the Delete method in the View Model and select Edit Execute Code.
use the following code for the method:
myapp.AddEditOrderDetail.Delete_execute = function (screen) {
screen.OrderDetail.deleteEntity();
return myapp.commitChanges().then(null, function fail(e) {
myapp.cancelChanges();
throw e;
});
};
When you run the application, you will be able to delete the selected Order Detail.
You will need to Save the changes to actually delete the record.
We can also add a Delete button to the Add Edit Order screen using the following code:
myapp.AddEditOrder.Delete_execute = function (screen) {
screen.Order.deleteEntity();
myapp.commitChanges().then(null, function fail(e) {
alert(e.message);
myapp.cancelChanges();
throw e;
});
};
You will notice that if we try to delete an Order that still has Order Detail records…
…it will throw an error because the relationship that we created between the tables earlier was set to not allow an Order to be deleted if there were associated records.
Delete all the Order Details first and then you can delete the Order.
Navigate To A Screen
Open the Main screen and create a button that will navigate to the Browse Products screen.
The Show Browse Products button will show.
LightSwitch Help Website Articles
Full Control LightSwitch (ServerApplicationContext And Generic File Handlers And
Ajax Calls)
Saving Data In The Visual Studio LightSwitch HTML Client (Including Automatic
Saves)
Creating A Desktop Experience Using Wijmo Grid In LightSwitch HTML Client
Creating ASP.NET Web Forms CRUD Pages Using ServerApplicationContext
Using Promises In Visual Studio LightSwitch
Retrieving The Current User In The LightSwitch HTML Client
Writing JavaScript That Implements The Binding Pattern In Visual Studio
LightSwitch
Implementing The Wijmo Radial Gauge In The LightSwitch HTML Client
Writing JavaScript In LightSwitch HTML Client Preview
Creating JavaScript Using TypeScript in Visual Studio LightSwitch
Theming Your LightSwitch Website Using JQuery ThemeRoller
Using Toastr with Visual Studio LightSwitch HTML Client (Preview)
LightSwitch Team HTML and JavaScript Articles
Visualizing List Data using a Map Control
Enhancing LightSwitch Controls with jQuery Mobile
Custom Controls and Data Binding in the LightSwitch HTML Client (Joe Binder)
Creating Screens with the LightSwitch HTML Client (Joe Binder)
The LightSwitch HTML Client: An Architectural Overview (Stephen Provine)
Writing JavaScript Code in LightSwitch (Joe Binder)
New LightSwitch HTML Client APIs (Stephen Provine)
A New API for LightSwitch Server Interaction: The ServerApplicationContext
Building a LightSwitch HTML Client: eBay Daily Deals (Andy Kung)