Monday, November 10, 2014

Asp.Net MVC Dynamic View

Dynamic type view is not new, in this post i explain how a single view supports multiple types of Models.
As We know, a view created with dynamic type gets neither intellisense support nor strongly typed templated helpers and you have to deal with the model's properties which may be intrinsic or complex and may also be readonly.
In order to show you that a single view supports any type viewModel, i have created 3 Model classes:
Hotel - which contains basic and complex type properties. (complex type here List<HotelRoom>)
Customer - which contains basic and complex type properties. (complex type here is HotelRoom type)
HotelRoom - which contains only basic types.

These are the ViewModels passed to the view:
  1. List<HotelRoom>
  2. Hotel
  3. Customer
Below are the screenshots for each viewModel rendered by single view:
 ViewModel - List<HotelRoom>

ViewModel - Customer

ViewModel - Hotel

What View contains?
The view contains the logic to iterate over the ViewData.ModelMetadata.Properties to generate label and control for each field and also checks for readonly metadata for a field and injects disabled attribute into the html control.
For complex type handling whether its a property or ViewModel, calling the Editor() will takes care of rendering it. If the ViewModel type is a collection, we have to provide a custom EditorTemplate (partial view) for the type used in the collection.
Note: For a property which is applied with readonly metadata attribute on a Model, it doesn't get its value submitted (even if you use hidden field it doesn't works) means it gets null value when (form post) submitted.

I don't recommend this approach for real scenarios, consider it as an example case where you can learn something from its code.

This sample contains:
  • 2 View files (view, partial-view)
  • 1 Class file (contains 3 Models)
  • 1 Controller file (3 Get Action methods and 3 Post Action Methods)
You can find the above files for download (only MVC folders):
Dowload Link

Monday, February 17, 2014

AngularJS CRUD Grid


      I created a sample web application which showcases how to do CRUD operations + search + sort + page on a Table (lets call it DataGrid) using AngularJS, Bootstrap for standalone version and angular-notifications, NodeJS, MySql for servercode version.

What I learned:
    While am doing edit functionality for this application, i tried to get the edit textboxes values (DOM code) into the controller, after i learned somewhere the good practice - "DOM code should not be used in controller" - i wanted to try mapping bindings to these textboxes.
    First i approached with adding edit option (property) in each item instance, later i realized its just a waste of code repetition, so i came with edit option on $scope which maintains just ID of item instance in edit-mode. Later i refined it as 'updateItem' object on $scope, it maps binding to these textboxes in edit-mode and maintains values and error statuses. This object is also reused in insert operation.

While developing, i faced a challenge, how can i track 'records count' when angularjs built-in filter is used for search?
I found a way, i tracked it in 'paging' filter (which i created for page navigation on grid). To get access of 'records count' property of $scope into filter, there is no easy way, of course we can pass scope from UI into filter as parameter, but that's not good practice, so i had to create a service (SharedObject) which contains properties shared between controller and filter.

I created another service (HelperService), so that scope related logic should not get mixed-up with unrelated (reusable, independent) code blocks.

Javascript coding has:

1 Controller - appCtrl
2 Services:

  • RecordCount - which tracks total records count used between controller and paging filter.
  • HelperService - provides generic functionalities: validation operation, deletes a record from set of records, parses error object.

1 Filter:
paging - to support page navigation on the grid.

You can find both standalone (html), and restful supported versions for download below.
I haven't created test-cases for unit-testing the angular code.

RESTful support:

       Javascript code is implemented slightly different here than standalone version.

For restful support i have used:
at serverside:

  • node.js with express package used as restful server.
  • for database, i have used mysql.

at clientside:
  • ngResource - angularjs directive which is useful in restful coding.
  • ng-notification - is a third-party angularjs module, used as notification service.

Why MySql?
         I used mysql because my system (Ubuntu) already has it as part of LAMP stack. I don't want to install another DB (like, MongoDB) just because for this Application. Of course you can change app code to use MongoDB with minor changes if you like.
I used Phpmyadmin to create DB and Table, you can find the scripts in sql file in download Zip.

What i learned:
Mysql returns date with GMT time, but not with serverside local time (here IST).
It creates problem, it returns date with one day less with GMT time, because it converts serverside local time to GMT time while returning json. To resolve it, i did convert json date string to date object then manually create correct date string. (browser by default coverts GMT date to local (here IST: +5:30) date). If you think there is a better solution, you can share in comments.

I modified CSS, js code of ng-notification, to suit our purpose and to support bootstrap for icons.

For testing the restful server, i have used 'Postman' plugin for Chrome. (you can find 'postman_dump' file in downloads for your local import and test). Application development done in Ubuntu OS with sublime text editor.

In download Zip file, i haven't included node.js dependencies - express, mysql npm packages - you have to add them manually into unzipped folder (TestOne) or, since the Zip file has package.json, you can try running "npm install" using CLI pointing to the unzipped folder to install dependencies for the restful server (WebSqlRest.js).

How to Execute:
Run server from CLI pointing to the unzipped folder:

$ node WebSqlRest.js

Now open browser and type the url:

References:   (for color themes)

Download and Demo:
Check the Demo here (and save locally)!
Download the Zip file here (restful)!