Click here to Skip to main content
15,867,568 members
Articles / Web Development / HTML5

Developing Web 2.0 User Interface for Self Hosted WCF Services using HTML5, CSS3 and JQuery

Rate me:
Please Sign up or sign in to vote.
4.08/5 (8 votes)
24 Jul 2011MIT5 min read 68.2K   684   26   25
Devloping Web 2.0 user interface for self hosted WCF services using HTML5, CSS3 and JQuery
WCFWebApp Image - maximum width is 600 pixels

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 become 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 platform with HTML5, CSS3 and backed by powerful JavaScript engines is a very promising option for self hosted WCF services.

Background

Initial versions of WCF could only work with SOAP messages. With bindings like WebHttpBinding from .NET 3.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 the 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 the 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 extended 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 JSON.Net is used to format json objects.

Using the Code

Download and build the 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 a different port. And you need admin privileges.
  2. When server is running, open any browser with JavaScript support and navigate to "http:/<machinename>:<port>/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 persisted.
  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.

C#
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.

C#
[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 intended for self hosted WCF services, singleton instance with concurrent threads is good enough. Consider sessions as applicable. But unlike IIS hosted services, self hosted services would normally serve limited users and thus default concurrency is good enough. And on functional line constructor is just loading data onto local member.

C#
[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 the 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 referred in index.htm in head section like JQuery. And in 'Files' method, different types of files are picked up from separate folders based on extension. Switch cases can be extended based types of files.

C#
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 separate 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.

C#
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 the 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.

C#
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', the following method would be invoked. This parses state id and update class member variable and returns updated list back to client.

C#
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 invoke the following method:

C#
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 separate folder by name 'web'. At the root of this folder, all static HTM files are placed. And separate sub-folders are included for images, JavaScript and stylesheets. These are referred 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:

JavaScript
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 about Jquery, JavaScript and Ajax concepts which are well explained on the 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.

History

  • 2011-07-22: First version
  • 2011-07-23: Article updated

License

This article, along with any associated source code and files, is licensed under The MIT License


Written By
Architect
India India
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionHow to use multi-part host names? Pin
Win32nipuh23-Jan-15 0:27
professionalWin32nipuh23-Jan-15 0:27 
QuestionNice Pin
Member 102859691-Jan-15 5:30
professionalMember 102859691-Jan-15 5:30 
QuestionWeb server & sql server Pin
Lopezd24-Sep-13 11:31
Lopezd24-Sep-13 11:31 
QuestionHow to assume /index.htm ? Pin
Jeremy Bradshaw9-Mar-13 2:23
Jeremy Bradshaw9-Mar-13 2:23 
AnswerRe: How to assume /index.htm ? Pin
Sriharsha Vardhan19-Mar-13 7:44
Sriharsha Vardhan19-Mar-13 7:44 
QuestionUpdating the data directly to the json file Pin
Nazha Harb8-Nov-12 5:06
Nazha Harb8-Nov-12 5:06 
AnswerRe: Updating the data directly to the json file Pin
Sriharsha Vardhan19-Mar-13 7:48
Sriharsha Vardhan19-Mar-13 7:48 
QuestionPath for download link moved by codeproject Pin
Sriharsha Vardhan20-Sep-12 6:25
Sriharsha Vardhan20-Sep-12 6:25 
GeneralMy vote of 5 Pin
bukwa78-Aug-12 0:18
bukwa78-Aug-12 0:18 
Thank you so much! It's just what I needed!
QuestionAttached source code link broken Pin
bspengr14-Jun-12 6:27
professionalbspengr14-Jun-12 6:27 
AnswerRe: Attached source code link broken Pin
bukwa78-Aug-12 0:21
bukwa78-Aug-12 0:21 
GeneralRe: Attached source code link broken Pin
Sriharsha Vardhan20-Sep-12 6:22
Sriharsha Vardhan20-Sep-12 6:22 
GeneralRe: Attached source code link broken Pin
Sriharsha Vardhan30-Jan-17 5:56
Sriharsha Vardhan30-Jan-17 5:56 
QuestionFile Not Found Pin
Farhan Ghumra6-Jun-12 2:11
professionalFarhan Ghumra6-Jun-12 2:11 
GeneralMy vote of 4 Pin
DeadlyEmbrace22-Feb-12 19:00
DeadlyEmbrace22-Feb-12 19:00 
QuestionWindows Authentication Pin
rmbrunet25-Jul-11 7:58
rmbrunet25-Jul-11 7:58 
QuestionHow to handle deeper pathing? Pin
kgoulding25-Jul-11 4:06
kgoulding25-Jul-11 4:06 
AnswerRe: How to handle deeper pathing? Pin
Sriharsha Vardhan26-Jul-11 20:46
Sriharsha Vardhan26-Jul-11 20:46 
QuestionAddressAccessDeniedException was Unheled Pin
krishna_goluguri24-Jul-11 23:46
krishna_goluguri24-Jul-11 23:46 
AnswerRe: AddressAccessDeniedException was Unheled Pin
kgoulding25-Jul-11 11:52
kgoulding25-Jul-11 11:52 
GeneralRe: AddressAccessDeniedException was Unheled Pin
Sriharsha Vardhan26-Jul-11 20:18
Sriharsha Vardhan26-Jul-11 20:18 
GeneralRe: AddressAccessDeniedException was Unheled Pin
Jeremy Bradshaw8-Mar-13 23:27
Jeremy Bradshaw8-Mar-13 23:27 
GeneralRe: AddressAccessDeniedException was Unheled Pin
Sriharsha Vardhan19-Mar-13 8:00
Sriharsha Vardhan19-Mar-13 8:00 
QuestionMore to follow? Pin
Skif21-Jul-11 13:06
Skif21-Jul-11 13:06 
AnswerRe: More to follow? Pin
Sriharsha Vardhan21-Jul-11 15:54
Sriharsha Vardhan21-Jul-11 15:54 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.