Monday 24 March 2014

Building Single Page Application with AngularJS and Web API - Part 1

On this post, we will see the first part of building a simple single page CRUD application using AngularJs and Web API. The application will manage user registrations data. Complete source codes can be downloaded from here.

First we configure AngularJS routing for our views. See this post to learn more about AngularJS routing.
userApp.config(['$routeProvider',
function ($routeProvider) {
    $routeProvider
    .when('/', {
        templateUrl: 'Partials/home.html',   // this is the partial view for listing page
        controller: 'UserCtrl'
    })
    .when('/create', {
        templateUrl: 'Partials/create-edit.html',   // this is the partial view for creating user page
        controller: 'UserCtrl'
    })
    otherwise({
        redirectTo: '/'
    });
}]);

Create Functionality
Create the partial html page for creating a user.
<div>
  <span style="color:red" data-ng-show="error">An error has occured.</span>
</div>
<div>
  <label>First Name</label>
  <input type="text" data-ng-model="user.Firstname" />
</div>
<div>
  <label>Last Name</label>
  <input type="text" data-ng-model="user.Lastname" />
</div>
<div>
  <label>Organisation</label>
  <input type="text" data-ng-model="user.Organisation" />
</div>
<div>
  <label>Position</label>
  <input type="text" data-ng-model="user.Position" />
</div>
<div>
  <label>Email</label>
  <input type="text" data-ng-model="user.Email" />
</div>
<button data-ng-click="submit(user)">Save</button>
Note that there are some ng-model attributes on the input fields to instruct AngularJS to bind the value. The attributes were prefixed with 'data-' to be HTML5 compliant. ng-click attribute is also used to tell AngularJS to execute a function.

Then create our Web API method (this one is scaffoled by Visual Studio when creating a new controller):
// POST api/UserRegistration
[ResponseType(typeof(User))]
public async Task<IHttpActionResult> PostUser(User user)
{
  if (!ModelState.IsValid)
  {
    return BadRequest(ModelState);
  }

  db.Users.Add(user);
  await db.SaveChangesAsync();

  return CreatedAtRoute("DefaultApi", new { id = user.UserId }, user);
}

Now, we create our AngularJS custom service to call the Web API method:
userApp.factory('userService', ['$resource', function ($resource) {
    return {
        createUser: function (user) {
            return $resource('/api/UserRegistration').save(user);
        }
    }
}]);
Here AngularJS $resource service is used to interact with the Web API method. $resource service is useful for interacting with RESTful based services such as Web API. It is simpler to use than $http service. To use this service, ngResource module will need to be included as well in our application. In this JavaScript function, we call the save() method of the $resource service, passing user object as the argument. The service will invoke a HTTP POST call to the specified url.

Finally we create our AngularJS controller:
userApp.controller('UserCtrl', ['$scope', '$location', '$routeParams', 'userService', function ($scope, $location, $routeParams, userService) {
   
    $scope.submit = function (user) {
        $scope.error = false;        
        userService.createUser(user).$promise.then(
          //success
          function (data) { $location.url('/'); },
          //error
          function (response) { 
                         //console.log(response);
                         //console.log(response.status);
                         $scope.error = true }
        );        
    }
}]);
Here we create a submit function that calls the user service that we have just created. The submit function is called by the save button in our partial view through ng-click attribute.

Note that $promise is also used to determine what action to take if the service call is successful and if it has error. $promise is part of $resource service. If it is successful, $promise will return data object (similar to the one we passed to the service call). If it fails, it will return a HTTP response object. It might be useful to see the headers and status properties of the response object.

$scope.error variable is used to show an error message if an error has occurred. This variable is referred to by ng-show in our partial view.


Listing Functionality
We have already implemented the create user functionality, now let us do the listing function.

First, create the partial view.
<div>
    <span style="color:red" data-ng-show="error">An error has occured.</span>
</div>
<table>
    <thead>
        <tr>
            <th>Firstname</th>
            <th>Lastname</th>
            <th>Email</th>
        </tr>
    </thead>
    <tbody ng-repeat="user in users">
        <tr>
            <td>{{ user.Firstname }}</td>
            <td>{{ user.Lastname }}</td>
            <td>{{ user.Email }}</td>
        </tr>
    </tbody>
</table>

Then the Web API method:
// GET api/UserRegistration
public IQueryable<User> GetUsers()
{
  return db.Users;
}

Add our user service with this method:
getAllUsers: function () {
  return $resource('/api/UserRegistration').query();
}
Here we use the $resource service's query() method that will invoke a HTTP GET call.

Then add the following codes in our controller:
$scope.init = function () {
  // Get all users
  userService.getAllUsers().$promise.then(
    //success
    function (data) {
      $scope.users = data;
    },
    //error
    function (response) {
      //console.log(response);
      //console.log(response.status);
      $scope.error = true;
    }
  );
}

In the coming post, we will see the edit and delete functionality.

Thursday 6 March 2014

Validating Model with Data Annotations in Unit Test

We could use the classes inside System.ComponentModel.DataAnnotations to help us in testing model with data annotations.

First, include the assembly in the test project reference libraries.

Then we can use this method of Validator class to do the validation, along with a ValidationContext instance and a collection of ValidationResult type as parameters.
public static bool TryValidateObject(
 Object instance,
 ValidationContext validationContext,
 ICollection<ValidationResult> validationResults,
 bool validateAllProperties
)
We need to pass a validation context instance, a collection to hold the result of each failed validation and a boolean value to indicate whether to validate all properties that are decorated with data annotations or only properties that are decorated with [Required] attribute only. To create a new instance of validation context, we could simply pass the object to be validated into ValidationContext() constructor method:
ValidationContext context = new ValidationContext(object_to_be_validated);

Below is a full example:
List<ValidationResult> validationResults = null;
var itemSellingDto = new ItemSellingDto() { InvoiceId = 0, ItemId = 1, ItemName = "", ItemSellingId = 0, Price = 0, Quantity = 10 };
var validationContext = new ValidationContext(itemSellingDto);

var isValid = Validator.TryValidateObject(itemSellingDto, validationContext, validationResults, validateAllProperties: true);

isValid.should_be(false);
validationResults.Any(vr => vr.ErrorMessage == "Price must be bigger than 0").should_be(true);


Saturday 1 March 2014

TransactionScope and SaveChanges in Entity Framework

TransactionScope class in .Net is great but if not used properly can cause table locks for long time and suffer application performance.

When using it with Entity Framework, only use TransactionScope when operation cannot be done within one SaveChanges() method or involves more than one data context.

Let's see the following codes. Imagine for some reasons, two data contexts are used.
using (var scope = new TransactionScope(TransactionScopeOption.Required))
{
    // some codes that do not involve database

    // some queries
	var student = contextOne.Students.Where( . . . );
	var schoolList = contextTwo.Schools;
	
	// more queries and validations
	//		check if student is allowed to move out ...
	//		check if student is allowed to move in ...
	
	// update student
	student.School = newSchool;
	
	// update some data in school context
	. . .
	
	
	contextOne.SaveChanges();
	contextTwo.SaveChanges();
	
    scope.Complete();
}
When we check SQL Profiler with tracing transactions enabled, we can see that Begin Transaction is executed immediately before the first database related operation. In this case is before the first data context querying a student (line #6). The transaction is wrapped up after the two data contexts are updated. This is a long time of locking and far beyond the necessary.

To enable tracing transactions, go to 'Events Selection' tab, click 'Show all events' then scroll to almost the end, expand 'Transactions' and tick the ones starting with 'TM: ...'

What should have been done is like the following:
    // some codes that do not involve database

    // some queries
	var student = contextOne.Students.Where( . . . );
	var schoolList = contextTwo.Schools;
	
	// more queries and validations
	//		check if student is allowed to move out ...
	//		check if student is allowed to move in ...
	
	// update student
	student.School = newSchool;
	
	// update some data in school context
	. . .
	

    using (var scope = new TransactionScope(TransactionScopeOption.Required))
    {	
	    contextOne.SaveChanges();
	    contextTwo.SaveChanges();
	
        scope.Complete();
    }
You can add try catch as well around the codes and discard the changes when there is an error.


Secondly, if there is only one data context needs to be updated, TransactionScope is not needed. Calling SaveChanges() method alone is enough and will create a transaction in database and execute any changes that have been made to the objects within the context.


For more information about TransactionScope, please see my previous article.