Friday, April 18, 2014

Session and Profile in Knockout Durandal SPA

Session and Profile is not a typical tenants of a single page application. But coming from a web development background we are so much used to these words. Hence I decided to carry the same terminology to the SPA also.

As you know Session is used to persist data between pages and Profile is used to store user details.  Let’s take the same concepts to the single page application. Web applications are stateless in nature and hence we need complex patterns to persist the state. Whereas SPA is a statefull environment running in a browser. Hence persisting state is very simple. But you need to be cautious and keep an eye for memory leaks and too much memory usage.

I will declare a global object (called session) and store that object in the window object. Here is my code for this session object

define(['services/profile'], function (profile) {

    var lookups;
    var vm = {
        profile: profile,
        lookups: lookups  //any additional data you want to persis
    };

    return vm;

});

As you see I am currently persisting profile data in session object. In addition I am also persisting additional data (lookups).

My profile object stores user details and is also used to check whether user is logged in or not. Here is the complete code for of my Profile object

define([], function () {
    var userID = ko.observable();
    var firstName = ko.observable();
    var lastName = ko.observable();
    var userName = ko.observable();
    var isAuthenticated = ko.observable(true);


    var vm = {
        userID: userID,
        firstName: firstName,
        lastName: lastName,
        userName: userName,
        photoUrl: photoUrl,
        isAuthenticated: isAuthenticated,
        populate: populate,
        logout: logout
    };

    return vm;

    function populate(data) {
        this.userID(data.UserID);
        this.firstName(data.FirstName);
        this.lastName(data.LastName);
        this.userName(data.UserName);
        this.isAuthenticated(true);
    };

    function logout() {
        this.isAuthenticated(false);
    };
});

Finally we need to define this session object and set it in the window object. We will do this in the Shell. Here is the simplified version of my shell class

define(['plugins/router', 'services/session'], function (router, session) {

    function activate() {
        //routing logic goes here
      
        //global variables
        window.session = session;

    }
}

As we transition from stateless environment to statefull environment we need to shift our mindset and embrace the client paradigm and take the solutions for the problems that are already solved by client server folks.

3 comments:

  1. Can you please give some details about how to get this session (global variable) on any view. This is very critical issue in SAP. Because we always have some variables that we need application wide. We do not want to make call to database to these on every view. What is the proper solution for that.

    ReplyDelete
  2. You can store the data on to the window object. In my scenario I am storing session data in the window object
    window.session = session;

    In my scenario, I put all the data I want global scope in the session function. Please take a look at the entire code of this session function
    https://github.com/prasannapattam/epos/blob/master/epos/epos/App/services/session.js

    On my application start page I am assigning this session on to the window object in addition to other objects I need global scope. Here is this code:
    https://github.com/prasannapattam/epos/blob/master/epos/epos/App/viewmodels/shell.js

    Finally the entire code is on the GitHub, you can download and check it out
    https://github.com/prasannapattam/epos/tree/master/epos/epos

    ReplyDelete
  3. you definitely don't need to set the session object global nor any other variable, in Durandal you can make use of Singleton for anything that need to be passed around in the application.

    ReplyDelete