Showing posts with label User Experience. Show all posts
Showing posts with label User Experience. Show all posts

Friday, July 22, 2011

Devloping web2.0 user interface for self hosted WCF services using HTML5, CSS3 and JQuery

WCFWebApp Image - maximum width is 600 pixels


Link to article

Introduction


This article describes a method to utilize WCF self hosted services to be able to serve web 2.0 user interface as well as web services.

By using this method tools or applications can be built using web 2.0 technologies like HTML5, CSS3 with self hosted WCF service as backend business layer. Thus developers can benefit from advanced javascript libraries like JQuery or Underscore etc.. to build user interface. This eliminates need to install .Net framework on client machines.

Traditionally self hosted WCF services has user interface built using WinForms and WPF technologies. And to be able to use browser as UI platform ASP.Net and IIS becomes hard dependencies. For tools and applications which typically are executed out of a single machine or intranet with limited users, IIS is considered as an overkill. Thus browser as a UI plarform with HTML5, CSS3 and backed by powerful javascript engines is very promising option for self hosted WCF services.


Background


Intial versions of WCF could only work with SOAP messages. With bindings like WebHttpBinding from .Net3.5 onwards WCF could offer direct support to consume web services from ajax calls from javascript. However consuming dataformats like JSON is still not so much so an out of box experience. Effort to write DataContracts for every argument and return types is quite high. And with other data formats like XML, client end couldn't directly benefit from javascript libraries due to extra step involved to convert from XML to JSON.


This method considers 'Stream' as input and out type for UI interfacing operations. It also supports basic authentication which can be extented for advanced usage. And no customization is done at any layer and just works based on out of box features of WCF in .Net 3.5. This can also be used with .Net 4.0. However for JSON.Net is used to format json objects.


Using the code


Download and build source. You can use Visual Studio 2010 or VS command line. (Code is built for .Net 4.0 but can be used with .Net 3.5 also)

  1. Start WCFWebApp.exe. If port 2011 is not free, change to different port. And you need admin previleges
  2. When server is running, open any browser with javascript support and navigate to "http:/:/index.htm"
  3. Enter username # 'user' and password # 'pass' and click on login. You will login and an about page is loaded
  4. Click on States link
  5. Check on visited option for any state and click on Update
  6. Change page to About and come back to States and observe that last selection is perisisted.
  7. Click on 'Logout' on right top corner.

All these operations are run out of a self hosted WCF service. And this demonstrated features like authentication, fetching static files, getting as well as setting and data. Following sections walk through code.


Server code


Main class just starts a WCF service using WebHttpBinding and WebServiceHost.

class Program
  {
    static void Main(string[] args)
    {            
      string baseAddress = "http://" + Environment.MachineName + ":2011/";
      using (WebServiceHost host = new WebServiceHost(typeof(WebApp), new Uri(baseAddress)))
      {
        WebHttpBinding binding = new WebHttpBinding();
        host.AddServiceEndpoint(typeof(IWCFWebApp01), binding, "").Behaviors.Add(new WebHttpBehavior());
        host.Open();
        ... other lines left for brevity
      }
    }
  }

Service contract defines a method 'Files' to serve all static html files, another method 'Links' serves all linked files like javascript, stylesheets and data. Other resources like login. logout, States and State are service operations. Observable point here is 'Stream' data type for input as well as output.

[ServiceContract]
    public interface IWCFWebApp01
    {
      [OperationContract, WebGet(UriTemplate = "/{resource}.{extension}")]
        Stream Files(string resource, string extension);

      [OperationContract, WebGet(UriTemplate = "/{path}/{resource}.{extension}")]
        Stream Links(string path, string resource, string extension);

      [OperationContract, WebInvoke(Method = "POST", UriTemplate = "/login")]
        Stream Login(Stream request);

      [OperationContract, WebInvoke(Method = "POST", UriTemplate = "/logout")]
        Stream Logout(Stream request);

      [OperationContract, WebGet(UriTemplate = "/states")]
        Stream States();

      [OperationContract, WebInvoke(Method = "POST", UriTemplate = "/state")]
        Stream State(Stream request);
    }

Now coming to service implementation. As this method is primarily intented for self hoseted WCF services, singleton isntance with concurrent threads is good enough. Consider sessions as applicable. But unlike IIS hosted services, self hosted services would nomally serve limited users and thus default concurrency is good enough. And on functional line constructor is just loading data onto local member.

[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single,ConcurrencyMode=ConcurrencyMode.Multiple)]
    public class WebApp : IWCFWebApp01
  {
    JObject states;

    public WebApp()
    {
      if (states==null)
        states = JObject.Parse(File.ReadAllText("web\\data\\states.json"));
    }

    ... other lines left for brevity

  }

Now that server is running, when user tries to access for the first time, several htm, css and javascript files are served.
These are handled by methods 'Files' and 'Links'. Links are files refered in index.htm in head section like JQuery. And in 'Files' method different types of files are picked up from seperate folders based on extension. Switch cases can be extended based types of files.

public Stream Links(string path, string resource, string extension)
    {
       ... other lines left for brevity
    }

    public Stream Files(string resource, string extension)
    {
      switch (extension)
      {
        case "htm":
           ... other lines left for brevity
        case "js":
           ... other lines left for brevity
      }
    }

When user makes a login request, basic authentication token is sent in standard header "Authorization".
That is validated in a seperate method 'Authenticate' described later. Also username is sent as JSON object in request stream which is parsed into JSON object using JSON.Net library. Logout method is similar to login

public Stream Login(Stream request)
    {
      if (!Authenticate()) return null;
         ... other lines left for brevity
      JObject o = JObject.Parse(data);
    }

When user clicks on 'States' request reaches following method.
As this resource doesn't have any extension, request will not go through 'Files' method. Here request is authenticated and data is sent from member variable.

public Stream States()
    {
      if (!Authenticate()) return null;

      WebOperationContext.Current.OutgoingResponse.ContentType = "application/json";
      return new MemoryStream(Encoding.ASCII.GetBytes(states.ToString()),false);
    }

When user does a modification and clicks on 'Update', following method would be invoked. This parses state id and update class member variable and returns updated list back to client.

public Stream State(Stream request)
    {
      ... other lines left for brevity
      JObject data = JObject.Parse(new string(buffer));
      int id = ((int)data["id"]) -1;
      states["states"][id]["visited"] = true;

      return States();
    }

Authentication. Methods which require authorization invokes following method.

public bool Authenticate()
    {
      string userName = "user";
      string password = "pass";

      string basicAuthCode = Convert.ToBase64String (Encoding.ASCII.GetBytes (string. Format ("{0}: {1}", userName, password)));
      string token = WebOperationContext.Current.IncomingRequest.Headers["Authorization"];
      if (token.Contains(basicAuthCode))
      {
        return true;
      }
      else
      {
        WebOperationContext.Current.OutgoingResponse.StatusCode = HttpStatusCode.Unauthorized;
        return false;
      }
    }


Client code


Client code is placed in seperate folder by name 'web'. At the root of this folder all static htm files are placed. And seperate sub-folders are included for images, javascript and stylesheets. These are refered from 'Files' method in server code based on extension.


Client follows Single Page Application design. Thus only 'index.htm' is a full html page. Other html files are filled into 'content' division using ajax calls as shown below for states

function StatesPage () {
  this.loadStatesPage = function (data) {
    content = undefined;
    $.each (data, function (index, value) {
      if (data[index]["id"]=="content") {
        content = data[index].innerHTML;
        $("#content")[0].innerHTML = content;
        $("#b_update")[0].onclick = updateStates;
        loadStatesTable();
      }
    });
    if (content == undefined) {alert("Failed to load page: Content missing"); return;} 
  }
      ... other lines left for brevity
}

Authentication: Client side authentication token is in login class. This token is added in header section in 'beforeSend' function of each call after login. Other code in client requires understanding abour Jquery, javascript and ajax concepts which is well explained on web.


Points of Interest


If windows authentication is required, service host can be customized

More structured javascript libraries with MVC architecture can also be used without making any change to server side code.

Consider using JQuery UI plugins for common look and feel

As UI is browser based, extending UI for handheld devices becomes quite easy.



Monday, May 09, 2011

Reusability and user experience

Reusability

Are you finding a phenomenon like use and throw with software applications?

Do you have anything about one time usability of applications? Often I get trickled about usability and reusability. An year back I was advised to emphasize more and more on usability and if at all I could build something reusable in it, it is just out of luck.

With rapid development frameworks and high fidelity needs designing anything for reuse is nothing but being stereotyped. There were times when reusability was discussed at every stage of development life cycle. Tools and technologies of those times asked for it. But we built runtime frameworks like Java, .Net etc. They are offering well tested reusable code for every possible computational need. Now what we are building is, nothing but application specific functional codebase. And there could only be a marginal scope  in it for reusable design. There is still scope but it is significantly low. That raises a question on what should be the strategy with respect to reusability in design. 

Another aspect is rapid prototyping,  dynamic languages, shorter delivery cycles, built-in user accepted mechanisms for application upgrades, well informed user, UX demanding networked systems. 

We are not building isolated apps like calculator and paint anymore. Even configuration, profiling and diagnostic tools are networked. 

And it is UX that matters at the end of the day. Now UX is a subject of taste for same need like hunger. It can't be same dish for breakfast, lunch and dinner. Then where is reusability in application development. Just like food need to be consumed while it remains fresh, app remains fresh for sometime only. 

With this background we need to adopt new strategies. It goes like software offers solutions for several problems surrounding human livelihood; but at the same it solves its own problems by looking at patterns of real world.

How does fabric design industry solve this problem. How does chefs solve and what entertainment industry does. And now the gadgets. 

Apps markets solved one side of this problem. Gone are the days where Microsoft builts one app to suit needs of whole world. Now there are several options for same need like calendar in markets. There is no one size fit for all. Yes there are some mostly downloaded apps. But there are several others too. Each one suits for someones taste. 

With markets gadget builders shielded themselves to great extent. Now they can concentrate on building just the platform. 

Now that leaves other side of the story up for discussion. What is in it for app developer with respect to reuasability.

1) Nurture multiple design options. Don't throw away anything just because it is not the best. More the time you spend time with need of the app the more you would meet expectations of broader userbase. 
Nurture multiple designs thinking that you are rich enough to build against each design. This is what fabric industry do.

Here you reuse understanding about characteristics of product for building against multiple designs rather reusing design.

2) Integrate services not userbase. Calendar app for world cup season is different from calendar app for competitive exams. Now you can build multiple views in same app. But building two distinct apps solves the problem in better way because the intended users are different even though program constructional aspects are same. Same story is told as book, documentary, movie etc..

3) Build reusable software just for multiple versions of same application than new application. Cost of building and maintaining reusable components is not economical anymore. As mentioned earlier there shouldn't be any hour spent specially to build a reusable component for next project. Moreover app development on different design is cheaper than maintenance. Most of the reusable stuff is used in enhancements than new development.  

4) Let users know the makers signature rather than technology. There is nothing called reusability of UX. It's called copyright violation. Tree controls are not looking like traditional tree controls, combo boxes are presented in so many ways where it's difficult to make it out as CB. So spend time to give facelist to your primitive controls for application specific look and feel. Your app should look like what it is meant for rather than Java app or winforms or wpf or PHP. You are not selling app to procurement manager or dealer. So there no one to  market your app. It should market for itself.