Maarten Balliauw {blog}

ASP.NET, ASP.NET MVC, Windows Azure, PHP, ...

NAVIGATION - SEARCH

Using SignalR to broadcast a slide deck

imageLast week, I’ve discussed Techniques for real-time client-server communication on the web (SignalR to the rescue). We’ve seen that when building web applications, you often face the fact that HTTP, the foundation of the web, is a request/response protocol. A client issues a request, a server handles this request and sends back a response. All the time, with no relation between the first request and subsequent requests. Also, since it’s request-based, there is no way to send messages from the server to the client without having the client create a request first.

We’ve had a look at how to tackle this problem: using Ajax polling, Long polling an WebSockets. the conclusion was that each of these solutions has it pros and cons. SignalR, an open source project led by some Microsoft developers, is an ASP.NET library which leverages the three techniques described before to create a seamless experience between client and server.

The main idea of SignalR is that the boundary between client and server should become easier to tackle. In this blog post, I will go deeper into how you can use SignalR to achieve real-time communication between client and server over HTTP.

Meet DeckCast

DeckCast is a small sample which I’ve created for this blog post series on SignalR. You can download the source code here: DeckCast.zip (291.58 kb)

The general idea of DeckCast is that a presenter can navigate to http://example.org/Deck/Present/SomeDeck and he can navigate through the slide deck with the arrow keys on his keyboard. One or more clients can then navigate to http://example.org/Deck/View/SomeDeck and view the “presentation”. Note the idea is not to create something you can use to present slide decks over HTTP, instead I’m just showing how to use SignalR to communicate between client and server.

The presenter and viewers will navigate to their URLs:SignalR presentation JavaScript Slide

The presenter will then navigate to a different slide using the arrow keys on his keyboard. All viewers will automatically navigate to the exact same slide at the same time. How much more real-time can it get?

SignalR presentation JavaScript Slide

And just for fun… Wouldn’t it be great if one of these clients was a console application?

SignalR.Client console application

Try doing this today on the web. Chances are you’ll get stuck in a maze of HTML, JavaScript and insanity. We’ll use SignalR to achieve this in a non-complex way, as well as Deck.JS to create nice HTML 5 slides without me having to code too much. Fair deal.

Connections and Hubs

SignalR is built around Connections and Hubs. A Connection is a persistent connection between a client and the server. It represents a communication channel between client and server (and vice-versa, of course). Hubs on the other hand offer an additional abstraction layer and can be used to provide “multicast” connections where multiple clients communicate with the Hub and the Hub can distribute data back to just one specific client or to a group of clients. Or to all, for that matter.

DeckCast would be a perfect example to create a SignalR Hub: clients will connect to the Hub, select the slide deck they want to view and receive slide contents and navigational actions for just that slide deck. The Hub will know which clients are viewing which slide deck and communicate changes and movements to only the intended group of clients.

One additional note: a Connection or a Hub are “transport agnostic”. This means that the SignalR framework will decide which transport is best for each client and server combination. Ajax polling? Long polling? Websockets? A hidden iframe? You don’t have to care about that. The raw connection details are abstracted by SignalR and you get to work with a nice Connection or Hub class. Which we’ll do: let’s create the server side using a Hub.

Creating the server side

First of all: make sure you have NuGet installed and install the SignalR package. Install-Package SignalR will bring down two additional packages: SignalR.Server, the server implementation, and SignalR.Js, the JavaScript libraries for communicating with the server. If your server implementation will not host the JavaScript client as well, installing SignalR.Server will do as well.

We will make use of a SignalR Hub to distribute data between clients and server. A Hub has a type (the class that you create for it), a name (which is, by default, the same as the type) and inherits SignalR’s Hub class. The wireframe for our presentation Hub would look like this:

1 [HubName("presentation")] 2 public class PresentationHub 3 : Hub 4 { 5 }

SignalR’s Hub class will do the heavy lifting for us. It will expose all public methods to any client connecting to the Hub, whether it’s a JavaScript, Console or Silverlight or even Windows Phone client. I see 4 methods for the PresentationHub class: Join, GotoSlide, GotoCurrentSlide and GetDeckContents. The first one serves as the starting point to identify a client is watching a specific slide deck. GotoSlide will be used by the presenter to navigate to slide 0, 1, 2 and so on. GotoCurrentSlide is one used by the viewer to go to the current slide selected by the presenter. GetDeckContents is one which returns the presentation structure to the client: the Title, all slides and their bullets. Let’s translate that to some C#:

1 [HubName("presentation")] 2 public class PresentationHub 3 : Hub 4 { 5 static ConcurrentDictionary<string, int> CurrentSlide { get; set; } 6 7 public void Join(string deckId) 8 { 9 } 10 11 public void GotoSlide(int slideId) 12 { 13 } 14 15 public void GotoCurrentSlide() 16 { 17 } 18 19 public Deck GetDeckContents(string id) 20 { 21 } 22 }

The concurrent dictionary will be used to store which slide is currently being viewed for a specific presentation. All the rest are just standard C# methods. Let’s implement them.

1 [HubName("presentation")] 2 public class PresentationHub 3 : Hub 4 { 5 static ConcurrentDictionary<string, int> DeckLocation { get; set; } 6 7 static PresentationHub() 8 { 9 DeckLocation = new ConcurrentDictionary<string, int>(); 10 } 11 12 public void Join(string deckId) 13 { 14 Caller.DeckId = deckId; 15 16 AddToGroup(deckId); 17 } 18 19 public void GotoSlide(int slideId) 20 { 21 string deckId = Caller.DeckId; 22 DeckLocation.AddOrUpdate(deckId, (k) => slideId, (k, v) => slideId); 23 24 Clients[deckId].showSlide(slideId); 25 } 26 27 public void GotoCurrentSlide() 28 { 29 int slideId = 0; 30 DeckLocation.TryGetValue(Caller.DeckId, out slideId); 31 Caller.showSlide(slideId); 32 } 33 34 public Deck GetDeckContents(string id) 35 { 36 var deckRepository = new DeckRepository(); 37 return deckRepository.GetDeck(id); 38 } 39 }

The code should be pretty straightforward, although there are some things I would like to mention about SignalR Hubs:

  • The Join method does two things: it sets a property on the client calling into this method. That’s right: the server tells the client to set a specific property at the client side. It also adds the client to a group identified by the slide deck id. Reason for this is that we want to group clients based on the slide deck id so that we can broadcast to a group of clients instead of having to broadcast messages to all.
  • The GotoSlide method will be called by the presenter to advance the slide deck. It calls into Clients[deckId]. Remember the grouping we just did? Well, this method returns me the group of clients viewing slide deck deckId. We’re calling the method showSlide n his group. showSlide? That’s a method we will define on the client side! Again, the server is calling the client(s) here.
  • GotoCurrentSlide calls into one client’s showSlide method.
  • GetDeckContents just fetches the Deck from a database and returns the complete object tree to the client.

Let’s continue with the web client side!

Creating the web client side

Assuming you have installed SignalR.JS and that you have already referenced jQuery, add the following two script references to your view:

1 <script type="text/javascript" src="@Url.Content("~/Scripts/jquery.signalR.min.js")"></script> 2 <script type="text/javascript" src="/signalr/hubs"></script>

That first reference is just the SignalR client library. The second reference is a reference to SignalR’s metadata endpoint: it contains information about available Hubs on the server side. The client library will use that metadata to connect to a Hub and maintain the persistent connection between client and server.

The viewer of a presentation will then have to connect to the Hub on the server side. This is probably the easiest piece of code you’ve ever seen (next to Hello World):

1 <script type="text/javascript"> 2 $(function () { 3 // SignalR hub initialization 4 var presentation = $.connection.presentation; 5 $.connection.hub.start(); 6 }); 7 </script>

We’ve just established a connection with the PresentationHub on the server side. We also start the hub connection (one call, even if you are connecting to multiple hubs at once). Of course, the code above will not do a lot. Let’s add some more body.

1 <script type="text/javascript"> 2 $(function () { 3 // SignalR hub initialization 4 var presentation = $.connection.presentation; 5 presentation.showSlide = function (slideId) { 6 $.deck('go', slideId); 7 }; 8 }); 9 </script>

Remember the showSlide method we were calling from the server? This is the one. We’re allowing SignalR to call into the JavaScript method showSlide from the server side. This will call into Deck.JS and advance the presentation. The only thing left to do is tell the server which slide deck we are interested in. We do this immediately after the connection to the hub has been established using a callback function:

1 <script type="text/javascript"> 2 $(function () { 3 // SignalR hub initialization 4 var presentation = $.connection.presentation; 5 presentation.showSlide = function (slideId) { 6 $.deck('go', slideId); 7 }; 8 $.connection.hub.start(function () { 9 // Deck initialization 10 $.extend(true, $.deck.defaults, { 11 keys: { 12 next: 0, 13 previous: 0, 14 goto: 0 15 } 16 }); 17 $.deck('.slide'); 18 19 // Join presentation 20 presentation.join('@Model.DeckId', function () { 21 presentation.gotoCurrentSlide(); 22 }); 23 }); 24 }); 25 </script>

Cool, no? The presenter side of things is very similar, except that it also calls into the server’s GotoSlide method.

Let’s see if we can convert this JavaScript code into come C#as well.  I promised to add a Console application to the mix to show you SignalR is not just about web. It’s also about desktop apps, Silverlight apps and Windows Phone apps. And since it’s open source, I also expect someone to contribute client libraries for Android or iPhone. David, if you are reading this: you have work to do ;-)

Creating the console client side

Install the NuGet package SignalR.Client. This will add the required client library for the console application. If you’re creating a Windows Phone client, SignalR.WP71 will do (Mango).

The first thing to do would be connecting to SignalR’s Hub metadata and creating a proxy for the presentation Hub. Note that I am using the root URL this time (which is enough) and the full type name for the Hub (important!).

1 var connection = new HubConnection("http://localhost:56285/"); 2 var presentationHub = connection.CreateProxy("DeckCast.Hubs.PresentationHub"); 3 dynamic presentation = presentationHub;

Note that I’m also using a dynamic representation of this proxy. It may facilitate the rest of my code later.

Next up: connecting our client to the server. SignalR makes extensive use of the Task Parallel Library (TPL) and there’s no escaping there for you. Start the connection and if something fails, let’s show the client:

1 connection.Start() 2 .ContinueWith(task => 3 { 4 if (task.IsFaulted) 5 { 6 System.Console.ForegroundColor = ConsoleColor.Red; 7 System.Console.WriteLine("There was an error connecting to the DeckCast presentation hub."); 8 } 9 });

Just like with the JavaScript client, we have to join the presentation of our choice. Again, the TPL is used here but I’m explicitly telling it to Wait for the result before continuing my code.

1 presentationHub.Invoke("Join", deckId).Wait();

Because the console does not have any notion about the Deck class and its Slide objects, let’s fetch the slide contents into a dynamic object again. Here’s how:

1 var getDeckContents = presentationHub.Invoke<dynamic>("GetDeckContents", deckId); 2 getDeckContents.Wait(); 3 4 var deck = getDeckContents.Result;

We also want to respond to the showSlide method. Since there’s no means of defining that method on the client in C#in the same fashion as we did it on the JavaScript side, let’s simply use the On method exposed by the hub proxy. It subscribes to a server-side event (such as showSlide) and takes action whenever that occurs. Here’s the code:

1 presentationHub.On<int>("showSlide", slideId => 2 { 3 System.Console.Clear(); 4 System.Console.ForegroundColor = ConsoleColor.White; 5 System.Console.WriteLine(""); 6 System.Console.WriteLine(deck.Slides[slideId].Title); 7 System.Console.WriteLine(""); 8 9 if (deck.Slides[slideId].Bullets != null) 10 { 11 foreach (var bullet in deck.Slides[slideId].Bullets) 12 { 13 System.Console.WriteLine(" * {0}", bullet); 14 System.Console.WriteLine(""); 15 } 16 } 17 18 if (deck.Slides[slideId].Quote != null) 19 { 20 System.Console.WriteLine(" \"{0}\"", deck.Slides[slideId].Quote); 21 } 22 });

We also want to move to the current slide:

1 presentationHub.Invoke("GotoCurrentSlide").Wait();

There we go. The presenter can now switch between slides and all clients, both web and console will be informed and updated accordingly.

SignalR Console Client

Conclusion

SignalR offers a relatively easy to use abstraction over various bidirectional connection paradigms introduced on the web. The fact that its open source and features clients for JavaScript, .NET, Silverlight and Windows Phone in my opinion makes it a viable alternative for applications where you typically use polling or a bidirectional WCF communication channel. Even WCF RIA Services should be a little bit afraid of SignalR as it’s lean and mean!

[edit] There's the Objective-C client: https://github.com/DyKnow/SignalR-ObjC

The sample code for this blog post can be downloaded here: DeckCast.zip (291.58 kb)

Remix 2010 slides and sample code

As promised during my session on Remix 10 yesterday in Belgium, here's the slide deck and sample code.

Building for the cloud: integrating an application on Windows Azure

Abstract: “It’s time to take advantage of the cloud! In this session Maarten builds further on the application created during Gill Cleeren’s Silverlight session. The campaign website that was developed in Silverlight 4 still needs a home. Because the campaign will only run for a short period of time, the company chose for cloud computing on the Windows Azure platform. Learn how to leverage flexible hosting with automated scaling on Windows Azure, combined with the power of a cloud hosted SQL Azure database to create a cost-effective and responsive web application.”

Thanks for joining and bearing with me during this tough session with very sparse bandwidth!

Source code used in the session: TDD.ChristmasCreator.zip (686.86 kb)

TechDays 2010 Portugal slides and demo code

First of all: thank you for attending the sessions Kevin Dockx and I gave at TechDays 2010 Portugal! A wonder we made it there with all the ash clouds and volcanic interference based in Iceland.

Just Another Wordpress Weblog, But More Cloudy

Abstract: “While working together with Microsoft on the Windows Azure SDK for PHP, we found that we needed an popular example application hosted on Microsoft’s Windows Azure. Wordpress was an obvious choice, but not an obvious task. Learn more about Windows Azure, the PHP SDK that we developed, SQL Azure and about the problems we faced porting an existing PHP application to Windows Azure.”

I can not disclose demo code at this time, sorry. Here’s a list of good resources to get you started though:

PHP and Silverlight

Abstract: “So you have an existing PHP application and would like to spice it up with a rich and attractive front-end. Next to Adobe Flex, you can also choose Silverlight as a solution. This session shows you around in Silverlight and shows that PHP and Silverlight can go together easily.”

Demo code: PHP and Silverlight - DevDays.zip (1.00 mb) (based on Silverlight 2, bug Kevin for a recent version :-))

Microsoft Web Development Summit 2009

PHP at Microsoft Being in the US for 2 times in a month (PDC09 and Web Development Summit) is fun, tiring and rewarding. The WDS09 was an invite-only event organized by Microsoft, focusing on interaction between Microsoft and the PHP community. I must say: the event has been helpful and interesting for both parties!

  • The Heathman Hotel in Kirkland is a nice hotel!
  • Traveling towards the US is far more productive than flying back: I did PHPMEF traveling westbound, I crashed (half sleep/half awake) on the eastbound flight…
  • If you just traveled over 26 hours: do NOT go shopping immediately when you arrive home! It’s really frustrating and tiring.
  • Did a session on Windows Azure SDK for PHP, PHPExcel and PHPLinq.
  • Did an interview for the Connected Show
  • Met a lot of people I knew from Twitter and e-mail, and met a lot of new people, both Microsoft and PHP community. Nice to meet you all!
  • Event focus was on feedback between Microsoft and PHP community, overall I think the dialogue was respectful and open and helpful to both parties.

Standing at the Microsoft logo

This was actually my first time at the WDS which has been around for 5 years already. The Interop team invited me there, and I want to thank them for doing that: it was a great trip, a great event and I got the chance to meet lots of new people.

Attendees were mostly people from the PHP community, like Cal Evans, Rafael Doms, Chris Cornutt, Romain Bourdon (WAMP server anyone?), Alison “snipe” Gianotto, … Next to that, lots of Microsoft people came by during various sessions. Some of them even reserved the whole week and were attending all sessions to make sure they were in the feedback loop all the time.

We’ve seen Microsoft sessions on IIS, Web Platform Installer, Silverlight, SQL Server, Bing, Powershell (sorry, Scott Hanselman, for disturbing your presentation with a tweet :-)). Interesting sessions with some info I did not know. PHP community sessions were also available: Wordpress, Joomla, Drupal, the PHP community perspective, feedback sessions, PHPLinq, PHPExcel, interoperability bridges, … A good mix of content with knowledgeable speakers and good communication between speakers, product groups and audience. Well done!

Microsoft PDC09 day 2 keynote highlights

Happiness, pure happiness!

Day 2 keynote at Microsoft PDC 2009 was quite exciting. To sum things up: Silverlight 4 went beta, IE9 features were previewed, and we got an external hard disk, nicely fitted in a tablet-pc format case. How thoughtful!

Here’s some of the novelties:

Silverlight 4 Beta

This was a good starter… It’s really incredibly feature packed! In my opinion, I think WCF can now be called obsolete as well, but no announcements on that :-) Anyway, here’s a list of new features: webcam access, multicast streaming, offline DRM and output protection, printing, clipboard support, out-of-browser and out-of-sandbox support, drag and drop, implicit styling, a HTML control, rich-text editing, breathe, ability to share assemblies with .NET 4, data binding improvements, udp multicast, REST enhancements, TCP channel support, …

Also check Tim Heuer’s blog post over at http://timheuer.com/blog/archive/2009/11/18/whats-new-in-silverlight-4-complete-guide-new-features.aspx.

IE9

Yes, IE9 was announced. Running JavaScript lots faster, passing more of the ACID3 test (still not all), and the coolest part: Direct3D rendering of all graphic content. This was demoed and approved by the audience: everything is so muh faster and smoother!

WCF RIA Services

Check out Brad Abrams’ blog for this: http://blogs.msdn.com/brada/archive/2009/11/18/welcome-to-wcf-ria-services-beta.aspx

Basically a rename of RIA services, and converted to run on top of WCF rather than an own transport layer implementation in previous versions.

Overall: a great PDC09 day two!

PHP and Silverlight - DevDays session

I just returned from The Hague where Kevin and I delivered a session on PHP and Silverlight. As promised, we are putting our slides and demos online. Download the demo code from here: PHP and Silverlight - DevDays.zip (1.00 mb)

Abstract:

"So you have an existing PHP application and would like to spice it up with a rich and attractive front-end. Next to Adobe Flex, you can also choose Silverlight as a solution. This session shows you around in Silverlight and shows that PHP and Silverlight can go together easily."

We really enjoyed DevDays and want to thank everyone who was there (and was in our session while beer drinking seemed more appropriate that time of day).

Creating an ASP.NET MVC application with Google Gears

Offline web applications… This term really sounds like 2 different things: offline, no network, and web application, online. Maarten, you speak in riddles man! Let me explain the term…

You probably have been working with Gmail or Google Docs. One of the features with those web applications is that they provide an “offline mode”, which allows you to access your e-mail and documents locally, when an Internet connection is not available. When a connection is available, those items are synchronized between your PC and the application server. This offline functionality is built using JavaScript and a Google product called Google Gears.

In this blog post, I will be building a simple notebook application using the ASP.NET MVC framework, and afterwards make it available to be used offline.

What is this Gears-thingy?

According to the Google Gears website: Gears is an open source project that enables more powerful web applications, by adding new features to your web browser:

  • Let web applications interact naturally with your desktop
  • Store data locally in a fully-searchable database
  • Run JavaScript in the background to improve performance

Sounds like a good thing. I always wanted to make a web application that I could use offline, too. After reading the tutorial on Google Gears, I learned some things. Google Gears consists of an offline JavaScript extension framework, installed on your PC, together with a SQLite database. Second, there are some different components built on this client side installation:

  • Factory – An object which enables access to all of the following bullets.
  • Blob – Blob storage, the ability to store anything on the client PC.
  • Database – Yes, a database! Running on the local PC and supporting SQL syntax. Cool!
  • Desktop – Interaction with the client PC’s desktop: you can add a shortcut to your application to the desktop and start menu.
  • Geolocation – Locate the physical position of the client’s PC, based on either GPS, Wifi, GSM or IP address location.
  • HttpRequest – Can be used to simulate AJAX calls to the local client PC.
  • LocalServer – A local web server, which can be used to cache certain pages and make them available offline.
  • Timer – A timer.
  • WorkerPool – A class that can be used to execute asynchronous tasks. Think "threading for JavaScript".

Picking some components to work with…

Choices for Google Gears and ASP.NET MVC Have a look at the list of components for Google Gears I listed… Those are a lot of options! I can make an ASP.NET MVC notebook application, and make things available offline in several manners:

  • Read-only offline access: I can use the LocalServer to simply cache all rendered pages for my notes and display these cached pages locally.
  • Synchronized offline access: I can use the Database component of Google Gears to create a local database containing notes and which I can synchronize with the ASP.NET MVC web application.

Note: Also check the architecture page on Google Gears documentation. It covers some strategies on the latter option.

Choices… But which to choose? Let’s not decide yet and first build the “online only” version of the application.

Building the ASP.NET MVC application

Not too many details, the application is pretty straightforward. It’s a simple ASP.NET MVC web application built on top of a SQL Server database using LINQ to SQL. I’ve used a repository pattern to access this data using a defined interface, so I can easily mock my data context when writing tests (which I will NOT for this blog post, but you know you should).

The data model is easy: ASP.NET membership tables (aspnet_Users) linked to a table Note, containing title, body and timestamp of last change.

On the ASP.NET MVC side, I’ve used this repository pattern and LINQ to SQL generated classes using the Add view… menu a lot (check ScottGu’s post on this to see the magic…). Here’s a screenshot of the application:

image

Feel free to download the source code of the ASP.NET MVC – only application: GearsForMvcDemo - MVC only.zip (4.12 mb)

Next steps: deciding the road to follow and implementing it in the ASP.NET MVC application…

Adding Google Gears support (“go offline”) – Read-only offline access

Refer to the choices I listed: “I can use the LocalServer to simply cache all rendered pages for my notes and display these cached pages locally.” Let’s try this one!

The tutorial on Google Gears’ LocalServer states we need a manifest.json file, containing all info related to which pages should be made available offline. Great, but I don’t really want to maintain this. On top of that, offline access will need different files for each user since every user has different notes and so on. Let’s create some helper logic for that!

Autogenerating the manifest.json class

Let’s add a new Controller: the GearsController. We will generate a list of urls to cache in here and disguise it as a manifest.json file. Here’s the disguise (to be added in your route table):

[code:c#]

routes.MapRoute(
    "GearsManifest",
    "manifest.json",
    new { controller = "Gears", action = "Index" }
);

[/code]

And here’s (a real short snippet of) the controller, automatically adding a lot of URL’s that I want to be accessible offline. Make sure to download the example code (see further in this post) to view the complete GearsController class.

[code:c#]

List<object> urls = new List<object>();

// … add urls …

// Create manifest
return Json(new
{
    betaManifestVersion = 1,
    version = "GearsForMvcDemo_0_1_0",
    entries = urls
});

[/code]

The goodness of ASP.NET MVC! A manifest is built using JSON, and ASP.NET MVC plays along returning that from an object tree.

Going offline…

Next step: going offline! The tutorial I mentioned before contains some example files on how to do this. We need gears_init.js to set up the Google Gears environment. Check! We also need a JavaScript file setting up the local instance, caching data. Some development and… here it is: demo_offline.js.

This demo_offline.js script is built using jQuery and Google Gears code. Let’s step trough a small part, make sure to download the example code (see further in this post) to view the complete file contents.

[code:c#]

// Bootstrapper (page load)
$(function() {
    // Check for Google Gears. If it is not present,
    // remove the "Go offline" link.
    if (!window.google || !google.gears) {
        // Google Gears not present...
        $("#goOffline").hide();
    } else {
        // Initialize Google Gears
        if (google.gears.factory.hasPermission)
            initGears();

        // Offline cache available?
        if (!google.gears.factory.hasPermission || (store != null && !store.currentVersion)) {
            // Wire up Google Gears
            $("#goOffline").click(function(e) {
                // Create store
                initGears();
                createStore();

                // Prevent default behaviour
                e.preventDefault();
            });
        } else {
            // Check if we are online...
            checkOnline(function(isOnline) {
                if (isOnline) {
                    // Refresh data!
                    updateStore();
                } else {
                    // Make sure "Edit" and "Create" are disabled
                    $("a").each(function(index, item) {
                        if ($(item).text() == "Edit" || $(item).text() == "Create New") {
                            $(item).attr('disabled', true);
                            $(item).click(function(e) {
                                e.preventDefault();
                            });
                        }
                    });
                }
            });

            // Provide "Clear cache" function
            $("#goOffline").text("Clear offline cache...").click(function(e) {
                // Remove store
                removeStore();
                window.location.reload();

                // Prevent default behaviour
                e.preventDefault();
            });
        }
    }
});

[/code]

What we are doing here is checking if Google gears has permisison to store data from this site on the local PC. If so, it is initialized. Next, we check if we already have something cached. If not, we wire up some code for the “Go offline” link, which will trigger the creation of a local cache on click. If we already have a cache, let’s do things different…

First, we call a simple method on the GearsController class (abstarcted in the checkOnline JavaScript function), checking if we can reach the server. If so, we assume we are online and ask Google Gears to check for updated contents. We always want the latest notes available! However, if this function says we are offline, we look for al links stating “Edit” or “Create New” on the current page and disable them. Read-only we said, so we are not caching “Edit” pages anyway. This is just cosmetics to make sure users will not see browser errors when clicking “Edit”.

 Going offline!

Conlusion for this approach

This approach is quite easy. It’s actually instructing Google Gears to cache some stuff periodically, backed up by an “is online” checker in the ASP.NET MVC application. This approach does feel cheap… I’m just creating local copies of all my rendered pages, probably consuming too much disk space and probably putting too much load on the server in the update checks.

Want to download and play? Here it is: GearsForMvcDemo - Offline copy.zip (4.11 mb)

Adding Google Gears support (“go offline”) – Synchronized offline access

In the first approach, I concluded that I was consuming too much resources, both on client and server, to check for updates. Not good! Let’s try the second approach: “I can use the Database component of Google Gears to create a local database containing notes and which I can synchronize with the ASP.NET MVC web application.”

What needs to be done:

  • Keep the approach described above: we will still have to download some files to the local client PC. The UI will have to be available. Not that we will have to download all note details pages, but we want the UI to be available locally.
  • Add some more JavaScript: we should be able to access all data using JSON (as an extra alternative to just providing web-based views that the user can work with).
  • The above JavaScript should be extended: we need offline copies of that data, preferably stored in the Google Gears local database.
  • And yet: more JavaScript: a synchronization should occur between the local database and the data on the application server.

Ideally, this should look like the following, having a JavaScript based data layer available:

Google Gears Reference Architecture

Due to a lack of time, I will not be implementing this version currently. But hey, here's a nice blog post that should help you with this option: .NET on Gears: A Tutorial

Conlusion for this approach

The concept of this approach is still easy, but requires you to write a lot of JavaScript. However, due to the fact that you are only synchronizing some basic UI stuff and JSON data, local and server resources are utilized far less than in the first approach I took.

Conclusion

The concept of Google Gears is great! But I seriously think this kind of stuff should be available in EVERY browser, natively, and with the same API across different browsers. Storing data locally may bring more speed to your application, due to more advanced caching of UI elements as well as data. The fact that it also enables you to access your application offline makes it ideal for building web applications where connectivity is not always guaranteed. Think mobile workers, sales people, ..., all traveling with a local web application. Not to forget: Gears is currently also available for Windows Mobile 5 and 6, which means that ultra-mobile people can run your web application offline on their handheld device! No need for specific software for them!

By the way, also check this: .NET on Gears: A Tutorial. Interested in Silverlight on Gears? It has been done!

kick it on DotNetKicks.com

CarTrackr - Sample ASP.NET MVC application

CarTrackr - Sample ASP.NET MVC application Some people may have already noticed the link in my VISUG session blog post, but for those who didn't... I've released my sample application CarTrackr on CodePlex.

CarTrackr is a sample application for the ASP.NET MVC framework using the repository pattern and dependency injection using the Unity application block. It was written for various demos in presentations done by Maarten Balliauw.

CarTrackr is an online software application designed to help you understand and track your fuel usage and kilometers driven.

You will have a record on when you filled up on fuel, how many kilometers you got in a given tank, how much you spent and how much liters of fuel you are using per 100 kilometer.

CarTrackr will enable you to improve your fuel economy and save money as well as conserve fuel. Fuel economy and conservation is becoming an important way to control your finances with the current high price.

Go get the source code for CarTrackr on CodePlex! (note that it has been updated for ASP.NET MVC beta 1)

Technologies and techniques used

Here's a list of technologies and techniques used:

  • CarTrackr uses the Unity application block to provide dependency injection
  • The repository design pattern is used for building a flexible data layer
  • Controllers are instantiated by using a custom ASP.NET MVC ControllerBuilder, which uses Unity for dependency resolving
  • The testing project makes use of Moq to mock out parts of the ASP.NET runtime
  • Form validation is included on most forms, leveraging the ViewData.ModelState class
  • It is possible to sign in using OpenID, for which the ASP.NET MVC Membership starter kit was used
  • LinqToSQL is used as the persistence layer
  • CarTrackr uses my ASP.NET MVC sitemap provider
  • Configuration Section Designer was used to create a custom configuration section
  • Extension methods are created for including Silverlight charts (rendered with Visifire)
  • Web 2.0 logo creator was used to generate a classy logo

kick it on DotNetKicks.com

Heroes happen here - Microsoft TechDays 2008 in Belgium

Microsoft TechDays 2008

Dolmen polo Just to inform you: together with a numer of colleagues from Dolmen, I'll be attending the Microsoft TechDays 2008 in Ghent, Belgium on 12 and 13 March 2008. Want to spot me, Joris, Jeroen, Danny, ... and meet in person? Search for one of the guys in a Dolmen shirt!

Update 17/03/2008: Jeroen posted an overview of the inspiring sessions on his blog.