Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

LightSwitch Online Ordering System

0.00/5 (No votes)
8 Dec 2011 2  
An example of an end-to-end LightSwitch application

OnlineOrdering/img4E.jpg

Introduction

In this article, we will create an end-to-end application in LightSwitch. The purpose is to demonstrate how LightSwitch allows you to create professional business applications that would take a single developer weeks to create. With LightSwitch, you can create such applications in under an hour.

Background

This is an application that is like applications I have built in the past. I am familiar with the requirements and I know exactly how long it takes to build this any other way. I estimate that using LightSwitch saves at least 98% in development time.

LightSwitch

The big advantage to using LightSwitch is in refactoring and validation. Refactoring is important because there are always changes to add and remove fields. Normally, this is very time-consuming. With LightSwitch, it takes seconds to make big changes to the database that are automatically reflected in the UI.

Validation is also a very big deal. Lightswitch has things like Concurrency Checking that would be very time-consuming to implement manually.

The Scenario

In this example, we will be tasked with producing an application that meets the following requirements for an order tracking system:

  • Products
    • Allow Products to be created
    • Allow Products to have weight
    • Allow Products to have a price
  • Companies
    • Allow Companies to be created
    • Allow Companies to log in and see their orders
  • Orders
    • Allow administrators to see all Companies and to place an order for any Company
    • Allow Companies who log in to see and place orders only for themselves
  • Business Rules
    • No single order can be over 10 pounds
    • No single order can be over $100
    • An order status must be one of the valid order types

Creating the Application

Image 2

Open Visual Studio and select File, then New Project.

Image 3

Select LightSwitch, and then the programming language of your choice. This tutorial will use C#.

Image 4

In the Solution Explorer, open Properties.

Image 5

Select Web as the Application Type, and indicate that it will be hosted in IIS.

Image 6

Select Create new table.

Image 7

Click on the table name to change it to Customer. Enter the fields for the table according to the image above.

(Note: We will also refer to the Tables as Entities, because when you are writing custom programming, it is best to think of them as Entities.)

Image 8

Click on the UserName field, and in the Properties, check Include in Unique Index. This will prevent a duplicate UserName from being entered.

LightSwitch does not allow you to create primary keys for Entities created inside LightSwitch (you can have primary keys for external tables you connect to). Where you would normally create a primary key, use the Include in Unique Index.

Image 9

Right-click on the ApplicationData node to add a new Table (Entity).

Image 10

Add a Product Entity according to the image above.

Image 11

Add an Order Entity according to the image above.

Image 12

Add an OrderDetail Entity according to the image above.

Creating a Choice List

Image 13

Open the Order Entity and select the OrderStatus field. In Properties, select Choice List.

Image 14

Enter the choices according to the image above.

This will cause screens (created later) to automatically provide a drop down with these choices.

Connect (Associate) the Entities (Tables) Together

It is important that you create associations with all the Entities in your LightSwitch project. In a normal application, this would be the process of creating foreign keys (and that is what LightSwitch does in the background). Foreign keys are usually optional because most applications will continue to work without them. With LightSwitch, you really must create the associations for things to work properly.

It will be very rare for an Entity to not have one or more associations with other Entities.

Image 15

Open the Order Entity and click the Relationship button.

Image 16

Associate it with the Customer Entity according to the image above.

Image 17

Repeat the process to associate the OrderDetail Entity to the Order entity according to the image above.

Image 18

Repeat the process to associate the OrderDetail Entity to the Product entity according to the image above.

Create Computed Columns

A computed column is a column that shows data that isn't actually stored in a table. This is why I like to refer to them as Entities rather than tables. If you look in SQL Server, the table will not have the field, but when you write code against the Entity, the field is there.

The reason you have a computed field is that LightSwitch will automatically display the data on screens without you needing to write far more complicated code. For example, we want the total of an Order to be displayed. We could leave this calculation until later when we create the screens, or we can simply make a computed field now.

Later, we simply tell Lightswitch to display the Order Entity. The total for the Order will automatically be displayed.

Image 19

Click on the OrderTotal field, and check Is Computed in Properties.

Image 20

Click Edit Method.

Image 21

A method will display.

Change the method to the following:

partial void OrderTotal_Compute(ref decimal result)
{
    decimal dOrderTotal = 0.0M;

    // Get OrderDetails that have products
    var colOrderDetails = from OrderDetails in this.OrderDetails
                          where OrderDetails.Product != null
                          select OrderDetails;

    foreach (var order in colOrderDetails)
    {
        dOrderTotal = dOrderTotal + (order.Quantity * order.Product.ProductPrice);
    }

    result = dOrderTotal;
}

Image 22

The calculator symbol will appear next to the OrderTotal field so you will know it is a computed field.

Make OrderWeightTotal and OrderName computed columns, and use the following code for their respective methods:

partial void OrderWeightTotal_Compute(ref double result)
{
    double dblWeightTotal = 0;

    // Get OrderDetails that have products
    var colOrderDetails = from OrderDetails in this.OrderDetails
                          where OrderDetails.Product != null
                          select OrderDetails;

    foreach (var order in colOrderDetails)
    {
        dblWeightTotal = dblWeightTotal + 
           (order.Quantity * order.Product.ProductWeight);
    }

    result = dblWeightTotal;
}

partial void OrderName_Compute(ref string result)
{
    if (this.Customer != null)
    {
        result = String.Format("{0} [{1} {2}]", 
          this.Customer.CustomerName, this.OrderStatus, 
          this.OrderDate.ToShortDateString());
    }
}

Image 23

The Order table will resemble the image above.

While we could have created code on the LightSwitch screens to do much the same thing (we will create screens in a later step), the Entity (the Table) is the proper place for this code for two main reasons:

  • The fields will automatically appear on any screen or dropdown the Entity appears on
  • We can write code against the computed value

Validation Code

The purpose of validation code is to prevent an Entity record from being saved or updated when it does not meet certain rules. It is important to note that validation code only operates on one Entity at a time, however the "rule" can be based on data from multiple entities.

We can validate a single Field or an entire Entity. First, we will look at validating a single Field (or Property).

Image 24

Open the OrderDetail Entity and click on the Quantity field. In Properties, click Custom Validation.

Image 25

You will see a method that simply asks you to add a PropertyError to the results collection. The presence of an error will prevent the Entity from being saved and the error will show.

Change the method to the following:

partial void Quantity_Validate(EntityValidationResultsBuilder results)
{
    if (this.Quantity < 1)
    {
        results.AddPropertyError("Quantity must be greater than zero.");
    }
}

"this." is the entity being saved. We simply check to see that Quantity is greater than 0.

Now we will look at the Entity validation:

Image 26

Open the OrderDetail Entity and select Write Code, then OrderDetails_Validate.

Use the following code for the method:

partial void OrderDetails_Validate(OrderDetail entity, 
             EntitySetValidationResultsBuilder results)
{
    // Total for order cannot be over $100
    if (entity.Order.OrderTotal > 100)
    {
        results.AddEntityError(String.Format(
           "Total order cannot be over $100.00"));
    }

    // Weight for order cannot be over 10 lbs
    if (entity.Order.OrderWeightTotal > 10)
    {
        results.AddEntityError(String.Format(
          "Total Weight for order cannot be over 10 lbs"));
    }
}

Image 27

Select the Orders_Validate method on the Order Entity.

Change the method to the following:

partial void Orders_Validate(Order entity, 
        EntitySetValidationResultsBuilder results)
{
    // Weight for order cannot be over 10 lbs
    if (
        (entity.OrderStatus != "New") &&
        (entity.OrderStatus != "Processing") &&
        (entity.OrderStatus != "Complete")
        )
    {
        results.AddEntityError(String.Format(
          "The only valid Status is 'New', 'Processing', or 'Complete'"));
    }
}

Note, LightSwitch will automatically create a dropdown for the OrderStatus field because it is using a choice list; however, you can still override this and change it to a text field. In that case, you would need this validation.

PreProcess Queries

PreProcess Queries allow us to alter the query used to access data. The normal query is executed, but any PreProcess method will add an additional constraint to the query. In this example, we will use it to:

  • Allow a Company (a non-administrator) to see, and only place orders, for themselves

Essentially, we will only apply the PreProcess query if the user is not an Administrator. We will apply this query to the Entities that we will give a Company access to if they log into the application:

  • Customers
  • Orders
  • Order Details

We will prevent a Customer/Company from accessing the Companies screen (that we will create in a later step). Also note, while we do not plan to allow a Customer to see the master Companies screen, we do need to set the security so that any drop down that shows Customers is constrained to only show a Customer's own record.

This is an example of learning to think "in the LightSwitch way". You want to implement business rules and security at the Entity level whenever possible. Any screen or drop down that you create later will automatically follow the rules you create. This saves an incredible amount of time, and makes the final application far more stable and robust than simply creating code at the time a list or dropdown is displayed on a screen.

Image 28

Open the Order Entity and select Orders_All_PreProcessQuery.

Change the method to the following:

partial void Orders_All_PreprocessQuery(ref IQueryable<Order> query)
{
    // This will run if the user is not an Administrator
    bool IsAdmin = this.Application.User.HasPermission(
                        Permissions.SecurityAdministration);
    if (!IsAdmin)
    {
        // This will restrict this query to Orders that belong to the current Customer
        query = query.Where(x => x.Customer.UserName == this.Application.User.Name);
    }
}

Perform the same steps for the OrderDetail Entity (OrderDetails_All_PreprocessQuery):

partial void OrderDetails_All_PreprocessQuery(ref IQueryable<OrderDetail> query)
{
    // This will run if the user is not an Administrator
    bool IsAdmin = this.Application.User.HasPermission(
                          Permissions.SecurityAdministration);
    if (!IsAdmin)
    {
        // This will restrict this query to Orders that belong to the current Customer
        query = query.Where(x => x.Order.Customer.UserName == this.Application.User.Name);
    }
}

Perform the same steps for the Customer Entity (Customers_All_PreprocessQuery):

partial void Customers_All_PreprocessQuery(ref IQueryable<Customer> query)
{
    // This will run if the user is not an Administrator
    bool IsAdmin = this.Application.User.HasPermission(
                          Permissions.SecurityAdministration);
    if (!IsAdmin)
    {
        // This will restrict this query to the current Customer
        query = query.Where(x => x.UserName == this.Application.User.Name);
    }
}

Creating Screens

Creating screens is very easy. In this example, we will just use the default screens, but they are highly customizable and you can also consume your own Silverlight custom controls. For more on this, see the tutorials on my site at: http://LightSwitch.ADefWebserver.com.

Image 29

Open an Entity and select the Screen button.

Image 30

Select the Editable Grid Screen template and select Customers for Screen Data.

Image 31

The screen designer will appear and the screen will show in the Screens folder. This is the place where you would normally customize a screen. We won't customize the screens in this tutorial, but we will add a small piece of code to prevent the screen from being accessed by a non-Administrator.

Image 32

Select Write Code, then EditableCustomerGrid_CanRun.

Change the method to the following:

partial void EditableCustomersGrid_CanRun(ref bool result)
{
    // User must be an Administrator
    result = this.User.HasPermission(Permissions.SecurityAdministration);
}

Perform the same steps to create a screen for the Product Entity.

Also, use the following code for the EditableProductsGrid_CanRun method of that screen:

partial void EditableProductsGrid_CanRun(ref bool result)
{
    // User must be an Administrator
    result = this.User.HasPermission(Permissions.SecurityAdministration);
}

Image 33

For the Orders Entity, select the List and Details Screen template, and select Orders for Screen Data, and Order Details and Order OrderDetails for Additional Data to Include.

Where is My Code?

You may get a bit nervous putting code in various places. You may wonder how you can easily find custom code that has been created in a LightSwitch project. This is not a problem.

Image 34

In the Solution Explorer, select File View.

Image 35

Select Show All Files.

Image 36

You will easily locate all the custom code you have written in the UserCode folders.

Run the Application

At this point, we have completed creating the application. If you are a professional developer and a cold chill just went through your body, you are not alone. Rest assured, a professional developer will still be needed to create LightSwitch programs like the one described at this link.

Image 37

Before we run the application, let us look at the user we will be. Go into Properties...

Image 38

Select Access Control, and ensure that Granted for Debug is checked for SecurityAdministration. When we run the project in Debug mode, we will be a user called TestUser. That user will be an Administrator when we have that box checked.

Later, we can uncheck this box, and we will be able to see what a normal Customer would see when they run the application. However, that Customer will have to have an account in the user table as "TestUser" because that is who you always are when running a LightSwitch application in Debug mode.

Image 39

Hit F5 to build and run the application.

Image 40

You will automatically be logged in as TestUser. When we deploy the application, a log in screen will show first.

Image 41

We enter two Customers. We make sure one of the users is "TestUser".

Image 42

Make sure you hit the Save button to save your data.

Image 43

Enter a few Products...

Image 44

When we go to the Order List Detail screen, we can click the big green plus button to open the Add New Order popup.

(Yes, you can control the design and layout of all these screens and popups (including preventing popups), but notice how much has been created for us with little effort on our part.)

Image 45

We can add Order Details to the Order.

Image 46

If we stop the program and uncheck the Granted for Debug box and then hit F5 again...

Image 47

We see that the only screen we can access is the Orders List Detail screen, and we can only see and place orders for "TestUser".

Deploy the Application

Image 48

Create a database in SQL Server. Make sure you have an account that has database ownership.

Image 49

In Visual Studio, select Build, then Configuration Manager.

Image 50

Change to Release mode (if you don't do this, you will see the "screen design" box in the deployed application).

Image 51

In Visual Studio, select Build then Publish OnlineOrdering..

Image 52

Select Web.

Image 53

Select IIS.

Image 54

Enter the address you want to deploy the website to (this server must have the LightSwitch Deployment Prerequisites installed; there is a link for it on the previous page of the wizard).

Image 55

Enter the SQL Server account you created earlier.

Image 56

On this screen, you need to create a user for the application. The first time you run the application, this will be the only user. This is the user you will need to log in as, to create accounts for all the other users.

Image 57

You can just click Next on the Specify a Certificate page.

Image 58

Click Publish.

Image 59

Navigate to the website in your web browser. Log in using the account you created in the wizard.

Image 60

Because this user is an Administrator, it is able to see Administration in the Menu. Click on Users.

Image 61

You will be able to create other users.

Image 62

When you make entries in the Customers screen, make sure the User Name matches the User Name created on the Users screen.

Image 63

If you close your web browser and log in as the user you created, you will see that the user is only able to place and view their own orders.

Image 64

All the business validation will also work.

You Can't Put the Genie Back in the Bottle

If you are a professional developer, you have to accept the truth, things have changed permanently. The days of six figured budgets to employ half a dozen developers on a run of the mill LOB application for weeks may be over. While some projects will still need costly customized HTML front-ends, the majority of any application is "back office stuff", and that can be done in LightSwitch by a single developer in only days.

The good news is that LightSwitch will primarily be used to replace projects that are currently done manually in Excel. The market for forms-over-data applications just got a lot bigger. However, any project that can be done in LightSwitch can be completed with a 75%+ savings in time and cost. The only way to compete is to use LightSwitch wherever it is appropriate.

I have more LightSwitch tutorials on my site at http://LightSwitchHelpWebsite.com.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here