Apr
14
Written by:
Michael Washington
4/14/2012 5:42 PM
Visual Studio LightSwitch (In Visual Studio 11 Beta) allows you to access your LightSwitch application via OData. This provides access to the security and business rules of your LightSwitch application.
In this article we will demonstrate using JQuery, DataJs and KnockoutJs to create a page that will cover Creating, Reading, Updating, and Deleting data (otherwise known as CRUD) in LightSwitch. As described in the article: LightSwitch Architecture: OData (John Rivard), OData allows CRUD using the following HTTP verbs:
Create : POST
Read: GET
Update: PUT
Delete: DELETE
Many may find that communication with LightSwitch is easer when using the server side methods shown in the articles: Calling LightSwitch 2011 OData Using Server Side Code and A Full CRUD LightSwitch JQuery Mobile Application. However, an advantage of using client-side JavaScript is:
- You do not need to create a service reference
- You can place the code on a normal .html or .htm page
This disadvantage is that the code does not compile at design-time, and one small typo can cause the page not to work.
The HTML Page In Action
When we run the application and navigate to the page, security (if enabled) is enforced.
The page will display the Products and the edit and delete buttons to any valid user…
But, if a non-administrator tries to insert, edit or delete records, LightSwitch server-side security in the OData feed, will enforce all business rules, and in this case prevent the user from performing the action.
Also, LightSwitch returns end-user understandable messages (you will want to parse the entire response to just show the Message tags) for all validation errors.
DataJs and KnockoutJs
This sample uses DataJs and KnockoutJs (in addition to JQuery).
Here are some links on DataJs and KnockoutJs:
DataJs – This JavaScript library is used to make the OData calls into LightSwitch. You can find documentation and samples at this link. Their Simple CRUD Sample is used as the basis for this article.
KockoutJs – This JavaScript library is used to display the data from DataJs. It is recommended that you go through these interactive tutorials to understand how it works.
LightSwitch OData Security
The sample consists of a page that allows an administrator to perform CRUD operations on the Product table in the Flower Shop application used in the article: Calling LightSwitch 2011 OData Using Server Side Code .
First we need to prevent non-administrators from updating the Products entity (table). We open the Products entity and select the CanUpdate method.
We use the following code:
partial void FlowerShopProducts_CanUpdate(ref bool result)
{
result = this.Application.User.HasPermission(Permissions.SecurityAdministration);
}
We do the same for the CanDelete and CanInsert methods:
partial void FlowerShopProducts_CanDelete(ref bool result)
{
result = this.Application.User.HasPermission(Permissions.SecurityAdministration);
}
partial void FlowerShopProducts_CanInsert(ref bool result)
{
result = this.Application.User.HasPermission(Permissions.SecurityAdministration);
}
The HTML Page
The next thing we do is to switch to File View mode and add the dataJs.htm page and the .js files required to support DataJs and KnockoutJs. We also need to unload the LightSwitch project and add the pages to the project manifest. That process is covered in the article: Calling LightSwitch 2011 OData Using Server Side Code.
The Code
For the top of the dataJa.htm page we use the following code:
<!DOCTYPE html>
<html>
<head>
<title>Products</title>
<style type="text/css">
body {
color: #444444;
font-family: Calibri, Verdana;
}
.titleSpan {
font-weight: bold;
}
.sectionArea {
border: 1px solid gainsboro;
padding: 8px;
margin-bottom: 8px;
background-color: #f1edb9;
width: 50%;
}
.ideaBox {
cursor: pointer;
padding-top: 8px;
}
#modelArea {
border: 1px solid gainsboro;
padding: 8px;
margin-bottom: 8px;
}
button, input, textarea { font-family: Calibri, Verdana; font-size: 100%; }
</style>
</head>
<body>
<h1>Products</h1>
<p>
This page shows how to create / read / update / delete information from a LightSwitch OData service.
</p>
Next, we add a DIV that will display a message when the page is busy communicating with LightSwitch:
<div id='newproductArea' class="sectionArea">
Then we put in the Refresh button. This is a normal HTML button except for the KnockoutJs attributes that will trigger the “loadproducts” JavaScript method:
<button id="refreshButton" data-bind="click: loadproducts, disable: communicating">Refresh</button>
We see that loadproducts is a JavaScript function that calls the LightSwitch OData service:
// Discards all products and reloads them from the server.
this.loadproducts = function () {
makeRequest({ requestUri: serviceUri + "FlowerShopProducts" }, function (data) {
that.products().splice(0, productsViewModel.products().length);
$.each(data.results, function (index, value) {
that.products.push(productModelToViewModel(value));
});
});
};
This is the makeRequest method that the loadproducts method invokes:
// Make a request, setting the 'communicating' flag.
var makeRequest = function (request, success) {
productsViewModel.communicating(true);
$("#messageBar").text("Contacting server...").show();
return OData.request(request, function (data) {
productsViewModel.communicating(false);
$("#messageBar").hide();
success(data);
}, function (err) {
productsViewModel.communicating(false);
$("#messageBar").hide();
alert("Error while contacting server: " + err.message + " - " + JSON.stringify(err));
});
};
The following is the DIV and the template used to display the products:
<div id="productsArea"
data-bind="template: { name: 'productTemplate', foreach: products }"
class="sectionArea">
</div>
<script type="x-jquery-tmpl" id="productTemplate">
<div class='productBox'>
{{if editing}}
<input type="text" data-bind="value: ProductName" size="80" /><br />
<textarea data-bind="value: Description" cols="80" rows="4"></textarea><br />
<input type="text" data-bind="value: Price" size="80" /><br />
<button data-bind="click: saveproduct, disable: communicating">Save</button>
{{else}}<br />
<span class='titleSpan'>${ProductName}</span><br />
${Description}<br />
$${Price}<br />
<button data-bind="click: editproduct, disable: communicating">Edit</button>
{{/if}}
<button data-bind="click: deleteproduct, disable: communicating">Delete</button>
<br />
</div>
</script>
(notice there are really two possible templates, a display template and an edit template, separated by the {{if editing}} value)
When the Edit button is clicked, the following code runs and sets the editing flag to true, and the edit template is displayed for the Product:
// Start editing an product.
model.editproduct = function () {
this.editing(true);
};
When the Save button is pressed this code runs:
// Save the changes to the product.
model.saveproduct = function () {
var that = this;
var data = productViewModelToModel(that);
var request = {
requestUri: data.__metadata.uri,
headers: { "If-Match": " *" },
method: "PUT",
data: data
};
makeRequest(request, function (data) {
that.editing(false);
});
};
When the Delete button is pressed this code runs:
// Deletes this product from the server and removes it from the view model.
model.deleteproduct = function () {
var that = this;
var request = {
requestUri: that.__metadata.uri(),
headers: { "If-Match": " *" },
method: "DELETE"
};
makeRequest(request, function (data) {
productsViewModel.products.remove(that);
});
};
When a Product is Inserted, this code runs:
// Adds the newproduct placeholder to the list and saves to the server.
this.addNewproduct = function () {
var request = {
requestUri: serviceUri + "FlowerShopProducts",
Accept: "application/json",
method: "POST",
data: {
Id: that.newproduct.id(),
ProductName: that.newproduct.productName(),
Description: that.newproduct.description(),
Price: that.newproduct.price()
}
};
makeRequest(request, function (newItem) {
that.newproduct.id("Id");
that.newproduct.productName("New product");
that.newproduct.description("Product description");
that.newproduct.price("Price");
that.products.push(productModelToViewModel(newItem));
});
};
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.
Still… Use The Silverlight Screens When You Can
Silverlight is not “dead”. In fact it provides the best, most efficient user experience. You will want to use the normal Silverlight screen whenever you can. For example, allow users to place and track orders using a web page, but use the LightSwitch Silverlight screens for customer service, inventory management, and other administration functions.
The advantage of using LightSwitch is that all business rules and security are maintained in one place.
Also See
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...
Congratulations Michael on yet another great LightSwitch - oData post. I especially like the se of Knockout for data binding.
By Delordson on
4/14/2012 8:55 PM
|
@Delordson - Thanks for the feedback!
By Michael Washington on
4/14/2012 9:04 PM
|
Nice article. Really help me in my new project
By Avinash on
9/18/2012 7:22 AM
|
you can also do a post using jquery, this is how I save a game
var data = { PlayerName: self.playerName(), Score: self.currentScore() }; $.post("/games/gameover/", data, function (returnedData) { if (returnedData) { self.isSaved(true); } });
By wordsearch on
10/1/2012 9:01 AM
|
Great article,
you have to remove the reference to the id when inserting products, otherwise you can only insert one product.
The ID is set automatic
By StePro on
10/22/2012 6:57 AM
|
hi,
i have front end code HTML page but using only back end code from light switch HTML client if it is possible?
By sekar kandan on
12/20/2012 5:05 AM
|
@sekar kandan - It may be but I have no examples.
By Michael Washington on
12/20/2012 5:06 AM
|
Are there any examples of using two-way binding and dependency chains like in knockout (http://knockoutjs.com/documentation/computedObservables.html) to make LS computed properties work in HTML client? or better yet, does anyone know how soon MS may include such functionality?
By joshbooker on
1/11/2013 8:47 AM
|
@joshbooker - Sorry no.
By Michael Washington on
1/11/2013 8:47 AM
|