Pages

Wednesday, 29 May 2013

How I wrote my SharePoint 2013 Bill Tracker App


I am writing this post to help myself and other fellows who are developers like me and are interested in developing SharePoint 2013 Apps.

In this post I am going to explain how I developed my BillTracker App for SharePoint 2013 using Javascript/CSOM for accessing SharePoint List Items using Repository and Knockout JS for displaying bills using MVVM patterns.
I am starting by showing high level architecture so it will make it easier to understand at first glance then project structure and code snippets.

Below is high level architecture:
 
And MVVM with the help of Knockout JS as shown below:

And here is my project structure:

and here is repository implementation in javascript using CSOM:

window.Masood = window.Masood || {};
window.Masood.BillTracker = window.Masood.BillTracker || {};
window.Masood.BillTracker.Repositories = window.Masood.BillTracker.Repositories || {};

window.Masood.BillTracker.Repositories.SharePointRepository = function (context, web, listName) {

    //properties
    this.context = context;
    this.web = web;
    this.listName = listName;
    var listItems;
    var listItem;

    var dateFormat = 'dd-MMM-yyyy';
    //collection for getAllItems
    this.Results = [];
    this.ErrorMessage;

    //result for getBill method
    this.Result;

    var clientSuccessCallback;
    var clientFailureCallback;

    this.getAllItems = function (sucCallback, failCallback) {

        //save the client's callback to variables 
        //that will be used in getAllItemsSuccessCallback event
        clientSuccessCallback = sucCallback;
        clientFailureCallback = failCallback;

        //use CSOM to grab SharePoint items
        listItems = null;
        var oList = web.get_lists().getByTitle(listName);
        var camlQuery = new SP.CamlQuery();
        //ste your CAML to filter items

        listItems = oList.getItems(camlQuery);
        context.load(listItems);
        context.executeQueryAsync(Function.createDelegate(this, getAllItemsSuccessCallback),
                                                                    Function.createDelegate(this, failureCallback));
     
    };

function getAllItemsSuccessCallback() {
        var listItemInfo = '';
        var listItemEnumerator = listItems.getEnumerator();

        this.Result = null;
        this.Results = [];

        paymentDate = '';
        while (listItemEnumerator.moveNext()) {
            var oListItem = listItemEnumerator.get_current();

            //push your Item/Model to Results array
        }

        //call client's success callback    
        clientSuccessCallback();
    }
}
and here is the ViewModel that calls the repository to get all/filtered items:

window.Masood = window.Masood || {};
window.Masood.BillTracker = window.Masood.BillTracker || {};
window.Masood.BillTracker.ViewModels = window.Masood.BillTracker.ViewModels || {};

window.Masood.BillTracker.ViewModels.AllBillsViewModel = function (context, web) {

    //private variables
    var self = this;
    var repository = new window.Masood.BillTracker.Repositories.SharePointRepository(context, web, 'MyBills');
    helper = new Helper();
    var _totalAmount = 0;

    //observable properties those are bind to UI elements
    self.Items = ko.observableArray();
    self.message = ko.observable("");
    self.totalAmount = ko.observable("");


    self.load = function () {
        self.message("Please wait, loading all your bills...");
        repository.getAllItems(onSuccess, onFailure);
    };

    function onSuccess() {
        //clear all items from observable collection
        self.Items.removeAll();
        var allBills = repository.Results;
        
        //populate observable collection
        _totalAmount = 0;
        for (i = 0; i < allBills.length; i++) {
            var item = allBills[i];
            self.Items.push(item);

            _totalAmount += parseFloat(item.Amount);
        }

        self.totalAmount(_totalAmount.toFixed(2));
        self.message("");
    }

    function onFailure() {
        alert('Something went wrong while fetching all your bills. Please contact administrator or  email at mmasood@gmail.com');
        self.message("Something went wrong while fetching all your bills. Please contact administrator or  email at mmasood@gmail.com");
    }
}
 
If you look above code, it does not update UI elements rather it just updates observable collections and property those are bind to UI elements as shown below:


 
 

And each .aspx or .html file has got its codebehind .js file that glue ViewModel instance as shown below:
var context;
var web;

//this function is called when page is loaded and DOM
//is ready
function sharePointReady() {
    context = new SP.ClientContext.get_current();
    web = context.get_web();
    
    //create instance of AllBills ViewModel 
    //and rest is taken care by KnockoutJs

    var viewModel = new window.Masood.BillTracker.ViewModels.AllBillsViewModel(context, web);
  
    //call load to fetch items from SharePoint
    //and populate all observable property and collection
    viewModel.load();
    ko.applyBindings(viewModel);
}


One last thing, before packaging, you need to minify all .js files using Micrsoft Ajax Minifier tool.
That’s it. Hope it would help you to understand and will help you to write better apps.

Tuesday, 14 May 2013

Firewall port open check

You might need to check whether some ports are open in an environment where Firewall are between servers.

Telnet is the tool to check the connectivity. Recently I was resolving one issue related to People search across multiple domains so I needed a tool to verify connectivity for ports 88, 139 and 445.

I used telnet to check, here is the command

telnet target_server_name_or_ip_address port_to_check

For example, log on to the server where you want to check connectivity from:

C:> telnet AD_SERVER_IP 88

There is another tool called PortQry that checks whether the port is listening or not, please visit http://support.microsoft.com/kb/816103

That's it.

Thursday, 9 May 2013

Provisioning WebParts through Module

If you want to provision a web-part (or many) for a Page(s) through Module, here is what I use in my project (especially WCM)

I alway create a Feature (as I love it) and it gives Administrator a control to add or remove functionality and also it gives flexibility for deployment. I will share my WCM project structure in future. So stay tuned to my site please.

Before creating Visual Studio Project, please follow below steps:

1. Create a page using your desired page layout (or the page you want to package)

2. Download a copy of the page you created in step 1.
3. Insert Content Editor or the webpart you want to include in the page using Module. For simplicity I am using Content Editor web-part.
4. Configure above added web-part. For instance add image or add some javascript whatever you want to do.
5. Export web-part and save the file.

Now create a Visual Studio Project for SharePoint and follow below steps:
1. Create Module or SharePoint mapped folder to drop required files
2. Create a Module, name it for instance HomePageModule and copy the file (from step 2 in before section) and configure Pages library of desired site.
3. Copy the contents from exported web-part file. Do NOT copy <webparts> node
4. Check whether the contents has got <!CDATA section, if yes then Encode the ONLY text srrounded by <!CDATA[[ and ]]> section and replace <!CDATA[[<your encoded html>]]> with encoded html
5. Add <AllUserWebPart WebPartZoneID="Zone 1" ZoneOrder="1"><!CDATA[[your copied text goes here]]>
6. Add Feature and include above created Module.
7. Deploy the Feature and you will see the page with configured web-part


Happy coding !!!