Monday, March 25, 2013

Ext JS 4.2 with .Net Web Service for CRUD grid

Here a step by step guide to teach how to use the Ext JS 4.2 with the .Net web service as backend for a CRUD grid, and of course with a complete example.

1. Let starts by create an empty web application. New Project > ASP.NET empty web application


2. Copy necessary files from the Ext JS package and you should have your project like this. I have keep the original path for those files so you should find those from the Ext JS package.


3. Next create a html page and drag all necessary path to the page as below.

<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <title></title>
        <link href="examples/shared/example.css" rel="stylesheet" type="text/css" />
        <link href="resources/css/ext-all-neptune-rtl-debug.css" rel="stylesheet" type="text/css" />
        <link href="resources/ext-theme-neptune/ext-theme-neptune-all-rtl-debug.css" rel="stylesheet" type="text/css" />
        <script src="ext-all-debug.js" type="text/javascript"></script>
        <script src="examples/shared/examples.js" type="text/javascript"></script>
        <script src="examples/restful/restful.js" type="text/javascript"></script>
    </head>
    <body></body>
</html>
4. Up to now all client stuff is complete except a little modification on the javascript, which will leave on the last step. Next we go back to the server side and add our web service. Right click on the web project and add an AJAX-enabled WCF service and name it PersonService.


5. Next let define the Person Object such that it match with the model in the sample javascript. For demo purpose, I just put it inside the PersonService class.
        // the person model align with the restful sample
        [DataContractAttribute]
        public class Person
        {
            [DataMemberAttribute]
            public int id { get; set; }
            [DataMemberAttribute]
            public string email { get; set; }
            [DataMemberAttribute]
            public string first { get; set; }
            [DataMemberAttribute]
            public string last { get; set; }
            public Person(int id, string email, string first, string last)
            {
                this.id = id;
                this.email = email;
                this.first = first;
                this.last = last;
            }
        }

6. I want the grid support remote sorting, so I need one more class for the sorting parameter and will be used later also. The class as follow:
        public class sortPara
        {
            public string property;
            public string direction;
        }

7. Again for demo purpose, I want to show some data and use a static variable to store the list, so i create the following stuff again in the PersonService class.
        static List<Person> _pList = null;
        static int _id = 0;
        // let init and get some data to show
        private static List<Person> GetList()
        {
            if (_pList == null)
            {
                _pList = new List<Person>();
                _pList.Add(new Person(1, "fred@flintstone.com", "Fred", "Flinstone"));
                _pList.Add(new Person(2, "wilma@flintstone.com", "Wilma", "Flinstone"));
                _pList.Add(new Person(3, "pebbles@flintstone.com", "Pebbles", "Flinstone"));
                _pList.Add(new Person(4, "barney@rubble.com", "barney", "rubble"));
                _pList.Add(new Person(5, "betty@rubble.com", "betty", "rubble"));
                _pList.Add(new Person(6, "bambam@rubble.com", "bambam", "rubble"));
                _id = 7;
            }
            return _pList;
        }

8. Finally we create the four services for handling the CRUD request from Ext Grid. Please note that the read request require a Get request while other is Post request. The read request has 3 input parameter, the start, limit and the sort, which i did not handle the start and limit here. It would be easy to do so when your data come from a database.

        [OperationContract]
        [WebGet(RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
        public List<Person> GetPersonList(int start, int limit, sortPara[] sort)
        {
            List<Person> pList = GetList();
            // handle sorting
            foreach (sortPara sp in sort)
            {
                if (sp.property == "id" && sp.direction == "ASC")
                {
                    pList = pList.OrderBy(o => o.id).ToList();
                }
                else if (sp.property == "id" && sp.direction == "DESC")
                {
                    pList = pList.OrderByDescending(o => o.id).ToList();
                }
                else if (sp.property == "email" && sp.direction == "ASC")
                {
                    pList = pList.OrderBy(o => o.email).ToList();
                }
                else if (sp.property == "email" && sp.direction == "DESC")
                {
                    pList = pList.OrderByDescending(o => o.email).ToList();
                }
                else if (sp.property == "first" && sp.direction == "ASC")
                {
                    pList = pList.OrderBy(o => o.first).ToList();
                }
                else if (sp.property == "first" && sp.direction == "DESC")
                {
                    pList = pList.OrderByDescending(o => o.first).ToList();
                }
                else if (sp.property == "last" && sp.direction == "ASC")
                {
                    pList = pList.OrderBy(o => o.last).ToList();
                }
                else if (sp.property == "last" && sp.direction == "DESC")
                {
                    pList = pList.OrderByDescending(o => o.last).ToList();
                }
            }
            return pList;
        }
        [OperationContract]
        [WebInvoke(Method = "POST", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
        public Person CreatePerson(string email, string first, string last)
        {
            // create the object and add to list
            Person p = new Person(_id, email, first, last);
            _id += 1;
            GetList().Add(p);
            return p;
        }
        [OperationContract]
        [WebInvoke(Method = "POST", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
        public Person UpdatePerson(int id, string email, string first, string last)
        {
            // look for the object by id and update it
            List<Person> obList = GetList();
            foreach (Person p in obList)
            {
                if (p.id == id)
                {
                    p.email = email;
                    p.first = first;
                    p.last = last;
                    return p;
                }
            }
            return null;
        }
        [OperationContract]
        [WebInvoke(Method = "POST", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
        public Person DeletePerson(int id)
        {
            // delete the object from list
            List<Person> obList = GetList();
            foreach (Person p in obList)
            {
                if (p.id == id)
                {
                    obList.Remove(p);
                    return p;
                }
            }
            return null;
        }

9. The last step is to modify the restful.js such that it call my web service instead of the original REST one. look for the definition of proxy and change it to following

         proxy: {
            type: 'ajax',
            // Call web service method using GET syntax
            api: {
                read: 'PersonService.svc/GetPersonList',
                create: 'PersonService.svc/CreatePerson',
                update: 'PersonService.svc/UpdatePerson',
                destroy: 'PersonService.svc/DeletePerson'
            },
            reader: {
                type: 'json',
                root: 'd'
            }
        },

10. Also we want to support remote sorting so i add the following to the store object also
        remoteSort: true,
        sorters: [{
            property: 'id',
            direction: 'ASC'
        }],

11. finally after build, go to the sample.htm and you should get a nice grid





password : nothing