Click here to Skip to main content
15,879,068 members
Articles / Web Development / ASP.NET / ASP.NET4.0

Using JayData to Consume the Visual Studio LightSwitch OData Business Layer in a AngularJs CRUD Application

Rate me:
Please Sign up or sign in to vote.
5.00/5 (6 votes)
26 Oct 2013CPOL2 min read 31K   9   10
You can consume your backend OData Visual Studio LightSwitch services in AngularJs

image

Introduction

You can consume your backend OData Visual Studio LightSwitch services in AngularJs. Coding your business layer in LightSwitch will save you a lot of development time and reduce the code you will be required to write.

image

This example uses JayData, a unified data access library for JavaScript that will be used to allow AngularJs to read and write to the LightSwitch OData layer.

The Application

image

Tasks are displayed in a list.

image

Clicking the Add new button will display the form to allow a new task to be created.

image

The task can be entered and saved.

image

New tasks will appear immediately.

image

Clicking on an existing task will open it in a form so that it can be edited.

Clicking the remove button deletes a task.

image

Business rules created in the LightSwitch business layer are enforced.

Creating the LightSwitch Application

image

Use Visual Studio 2013 (or higher), create a New Project.

image

Create a new LightSwitch application.

image

Right-click on the Data Sources folder and select Add Table.

image

Create a table called ToDo and save it.

image

The table will be pluralized to ToDoes.

image

Select Write Code, then ToDoes Validate.

Use the following code for the method:

JavaScript
partial void ToDoes_Validate(ToDo entity,
    EntitySetValidationResultsBuilder results)
{
    // Do not allow a task to be called {New Task]
    if (entity.TaskName == "[New Task]")
    {
        results.AddEntityError(
            "Task cannot be named [New Task]"
            );
    }

    // Do not allow more than 1 incomplete Task
    if (entity.IsComplete == false)
    {
        int intCountOfIncomplete =
            this.DataWorkspace.ApplicationData.ToDoes
            .Where(x => x.IsComplete == false).Count();

        if (intCountOfIncomplete > 0)
        {
            results.AddEntityError(
                "Cannot have more than 1 incomplete Task"
                );
        }
    }
}

image

We can create LightSwitch HTML Client screens to allow us to enter sample data.

(See: Visual Studio LightSwitch 2013–Hello World! for directions on creating LightSwitch screens.)

image

We also see that the LightSwitch business rules are enforced.

Create the Entity Context

JayData tracks the changes of the entities using an entity context. Adding, updating, deleting entities happen through the context, which holds the reference to the added, updated and deleted objects and dispatches the operations (HTTP requests) to the OData endpoint after calling context.saveChanges(). Entity contexts can be defined manually or generated the JaySvcUtil.exe. You can download the latest version from JaySvcUtil CodePlex page.

Image 17

When we run the application, we note the URL.

Image 18

If we change the path to ApplicationData.svc, we see the OData service.

Image 19

We use the JayScvUtil tool to create the entity context using the format:

JaySvcUtil.exe -m http://{domain}:{port}/ApplicationData.svc/$metadata -o ApplicationData.js

Image 20

We add the resulting file to the project.

Creating the AngularJs View Page

image

We will first make a simple page that displays data.

Right-click on the Server project and Add a new HTML page.

image

Name the page JayDataView.

Use the following code for the page:

HTML
<html>
<head>
<title>JayData.org Sample</title>
<script src="http://code.jquery.com/jquery-2.0.3.min.js"></script>
<script src="http://code.angularjs.org/1.2.0-rc.3/angular.js"></script>
<script src="http://include.jaydata.org/datajs-1.0.3.js"></script>
<script src="http://include.jaydata.org/jaydata.js"></script>
<script src="http://include.jaydata.org/jaydatamodules/angular.js"></script>
<script src="JayDataView.js"></script>
<script src="ApplicationData.js"></script>
</head>

<body data-ng-app="app">
<div ng-controller="ToDoesController">
	<ul>
		<li ng-repeat="ToDo in ToDoes">
			<input id="checkSlave" type="checkbox" ng-model="ToDo.IsComplete">
			{{ToDo.TaskName}}
		</li>
	</ul>
</div>
</body>
</html>

Create a JavaScript file called JayDataView.js and use the following code:

JavaScript
// Create an Angular app and inject JayData
var app = angular.module('app', ['jaydata']);
// Define a controller
function ToDoesController($scope, $data) {
    // Make a empty collection for ToDoes
    $scope.ToDoes = [];

    var ApplicationData = new LightSwitchApplication.ApplicationData({
        name: 'oData',
        oDataServiceHost: '/ApplicationData.svc'
    });

    ApplicationData.onReady(function () {
        // Connect the ToDoes collection to the
        // JayData toLiveArray()
        $scope.ToDoes = ApplicationData.ToDoes.toLiveArray();
    });
}

image

Run the application.

image

Navigate to the JayDataView page in the root of the website and the tasks will show.

Create the AngularJs CRUD Page

Create a new page called JayData.html and use the following code:

HTML
<html>
<script src="http://code.jquery.com/jquery-2.0.3.min.js"></script>
<script src="http://code.angularjs.org/1.2.0-rc.3/angular.js"></script>
<script src="http://include.jaydata.org/datajs-1.0.3.js"></script>
<script src="http://include.jaydata.org/jaydata.js"></script>
<script src="http://include.jaydata.org/jaydatamodules/angular.js"></script>
<script src="JayData.js"></script>
<script src="ApplicationData.js"></script>

<body>
	<div data-ng-app="app" ng-controller="ToDoEditorController">
	<ul>
	<li ng-repeat="ToDo in colToDoes">
	<input id="checkbox" type="checkbox" 
	ng-model="ToDo.IsComplete" disabled="disabled">
	<a href="#" ng-click="$parent.selectedToDo = ToDo">{{ToDo.TaskName}}</a>
	</li>
	</ul>
	<button ng-click="newToDo()">add new</button>
	<p>
	<form ng-if="selectedToDo">
	<fieldset style="width: 300px; background-color: #FFFFCC;">
	<legend>{{selectedToDo.TaskName}}</legend>
	<br />
	<label>
	<span><strong>Id:</strong></span>
	<span>{{selectedToDo.Id}}</span>
	<span>
	<br />
	<strong>Task Name:</strong>
	</span>
	<input ng-model="selectedToDo.TaskName" size="20" />
	<span>
	<br />
	<strong>Is Complete:</strong>
	</span>
	<input type="checkbox" ng-model="selectedToDo.IsComplete" />
	<br />
	<br />
	</label>
	<button ng-click="save()">Save</button>
	<button ng-click="remove()">Remove</button>
	</fieldset>
	</form>
	</p>
	</div>
</body>
</html>

Use the following code for the JayData.js file:

JavaScript
var app = angular.module('app', ['jaydata']);

function ToDoEditorController($scope, $data) {
    $scope.ToDoes = [];
    $scope.selectedToDo = null;

    var ApplicationData = new LightSwitchApplication.ApplicationData({
        name: 'oData',
        oDataServiceHost: '/ApplicationData.svc'
    });

    ApplicationData.onReady(function () {
        $scope.ApplicationData = ApplicationData;
        $scope.ToDoes = ApplicationData.ToDoes.toLiveArray();
    });

    // This will be called when the collection changes
    Object.defineProperty($scope, "colToDoes", {
        get: function () {
            return $scope.ApplicationData
              .ToDoes
              .toLiveArray();
        }
    });

    $scope.save = function () {
        if ($scope.selectedToDo.Id) {
            // Save an existing ToDo item
            $scope.ApplicationData.ToDoes.attach($scope.selectedToDo, true);
            $scope.selectedToDo.entityState = $data.EntityState.Modified;
        }
        else {
            // Save a new ToDo item
            $scope.ApplicationData.ToDoes.add($scope.selectedToDo, true);
        }
        $scope.saveChanges();
    };

    // Save any changes
    $scope.saveChanges = function () {
        $scope.ApplicationData.saveChanges()
        .then(function () {
            $scope.selectedToDo = null;
        }, function (error) {
            // Get the validation error messages from LightSwitch
            var xml = error.message,
            xmlDoc = $.parseXML(xml),
            $xml = $(xmlDoc),
            $ValidationResults = $xml.find("ValidationResults");

            angular.forEach($ValidationResults, function (ValidationResult) {
                angular.forEach(ValidationResult.childNodes, function (childNode) {
                    alert(childNode.childNodes[0].textContent);
                });
            });

            $scope.ApplicationData.stateManager.reset();
        });
    };

    $scope.remove = function () {
        // Remove the ToDo item
        $scope.ApplicationData.ToDoes.remove($scope.selectedToDo);
        $scope.saveChanges();
    };

    $scope.newToDo = function () {
        var ctx = $scope.ApplicationData;
        // Add a new ToDo item
        $scope.selectedToDo = new ctx.ToDoes.elementType({
            // Set the default value for the Task Name
            TaskName: "[New Task]"
        });
    };
}

JayData Links

LightSwitch Help Website Links

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior) http://ADefWebserver.com
United States United States
Michael Washington is a Microsoft MVP. He is a ASP.NET and
C# programmer.
He is the founder of
AiHelpWebsite.com,
LightSwitchHelpWebsite.com, and
HoloLensHelpWebsite.com.

He has a son, Zachary and resides in Los Angeles with his wife Valerie.

He is the Author of:

Comments and Discussions

 
QuestionDeploying Pin
Anas Karm.20-May-14 0:35
Anas Karm.20-May-14 0:35 
AnswerRe: Deploying Pin
defwebserver20-May-14 2:06
defwebserver20-May-14 2:06 
QuestionUnable to reference properties of my objects Pin
Big Bad Rog4-Mar-14 10:09
Big Bad Rog4-Mar-14 10:09 
AnswerRe: Unable to reference properties of my objects Pin
defwebserver4-Mar-14 10:17
defwebserver4-Mar-14 10:17 
GeneralRe: Unable to reference properties of my objects Pin
Big Bad Rog5-Apr-14 18:10
Big Bad Rog5-Apr-14 18:10 
GeneralRe: Unable to reference properties of my objects Pin
defwebserver5-Apr-14 18:20
defwebserver5-Apr-14 18:20 
GeneralRe: Unable to reference properties of my objects Pin
Big Bad Rog5-Apr-14 19:08
Big Bad Rog5-Apr-14 19:08 
GeneralRe: Unable to reference properties of my objects Pin
defwebserver6-Apr-14 1:47
defwebserver6-Apr-14 1:47 
I am sorry but I never tried to connect that way. The only thing I can think of is that perhaps it doesn't work with a SQL 2005 data source, but I do not know. The http://jaydata.org/[^] site may be able to help.
GeneralRe: Unable to reference properties of my objects Pin
Big Bad Rog5-Apr-14 19:11
Big Bad Rog5-Apr-14 19:11 
AnswerRe: Unable to reference properties of my objects Pin
Derek T Bodendorfer15-Jul-16 12:42
Derek T Bodendorfer15-Jul-16 12:42 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.