Logo

Maarten Balliauw {blog}

ASP.NET, ASP.NET MVC, Azure, PHP, OpenXML, VSTS, ...

About the author

Maarten Balliauw is currently employed as .NET Technical Consultant at RealDolmen. His interests are mainly web applications developed in ASP.NET (C#) or PHP and the Windows Azure cloud platform.
More about me More about me
Send mail E-mail me


ASP.NET MVC Quickly Subscribe to my RSS feed Follow me on Twitter! View Maarten Balliauw's profile on LinkedIn
View Maarten Balliauw's MVP profile

Search

Latest Twitter

    Follow me on Twitter...

    My projects

    Disclaimer

    The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.

    © Copyright Maarten Balliauw 2010

    Slides of our VISUG session

    As promised, here are the slides of the VISUG session me and Kris van der Mast did yesterday.

    Being a pimp without Silverlight!

    Abstract: “Don't tell us you're jealous of those Silverlight fanboys! We'll show you that applications with bling can be developed using ASP.NET MVC and jQuery. We're talking MVC, template helpers, AJAX, JSON, transitions, live bindings, ...”


    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!


    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):

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

    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.

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

    // … add urls …

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

    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.

    // 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();
                });
            }
        }
    });

    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


    Categories: ASP.NET | C# | General | jQuery | MVC | SilverLight | Software

    Announcing my book: ASP.NET MVC 1.0 Quickly

    ASP.NET MVC 1.0 Quickly It’s been quite a job, but there it is: Packt just announced my very first book on their site. It is titled “ASP.NET MVC 1.0 Quickly”, covering all aspects ASP.NET MVC offers in a to-the-point manner with hands-on examples. The book walks through the main concepts of the MVC framework to help existing ASP.NET developers to move on to a higher level. It includes clear instructions and lots of code examples. It takes a simple approach, thereby allowing you to work with all facets of web application development. Some keywords: Model-view-controller, ASP.NET MVC architecture and components, unit testing, mocking, AJAX using MS Ajax and jQuery, reference application and resources.

    That’s it for the marketing part: let’s do a retrospective on the writing process itself. Oh and yes, those are my glasses on the cover. Photo was taken on the beach near Bray-Dunes (France).

    When did you have the idea of writing a book?

    I'm not sure about that. I've been blogging a lot on ASP.NET MVC last year, wrote an article for .NET magazine, did some presentations, ... It occurred to me that I had a lot of material which I could bundle. Together with that, my project manager jokingly said something like: "When will you write your first book? With all that blogging." So I did start bundling stories. First of all, I overlooked the whole ASP.NET MVC technology (preview 2 at that moment) and decided there were enough topics to talk about. A draft table of contents was built quite quick, but I gave up on writing. Too much information, not enough time, ...

    A few weeks later, it must have been around the beginning of May, 2008, I did start writing a first chapter, thinking I'ld see how the writing itself would turn out, if it fit in my schedule, ... It worked out quite well, each 10-20 days gave me a new chapter. I also started looking for a publisher when I was finished with chapter 6 or so. Having reviewed some books for Packt, I contacted them with a proposal for my book.

    After having a look at the other 6 upcoming books (here and here), we decided we could go for it, focusing on a hands-on book which rapidly guides you into the wonderful world of ASP.NET MVC.

    How was your experience of writing your book?

    Looking back, it was an interesting experience. I decided to write in English, which is not my native language. That was actually quite a hard one: writing in English is no problem, but writing a good, solid and interesting piece of text is just not that easy when writing longer texts than the average blog post. Another thing is that I tortured myself writing about a product that was not even beta yet! I started writing with ASP.NET MVC preview 3, updated it all to preview 4, 5, beta, release candidate, ... Lots of changes in the ASP.NET MVC API or concepts meant lots of changes to make in chapters I already wrote. Luckily, I survived :-)

    I only contacted a publisher when I had finished 60% of my book. If you are considering writing: don't do this! Contact a publisher at a very early stage: they normally give you lots of advice upfront, which I only received after contacting them. Advice earlier along the way is always better, so that's something I would definately do different.

    Speaking of advice: when writing was done, the book entered review phase. Different people received the draft version and could provide comments and suggestions. Thanks Stefan, Troy, Vivek, Jerry, Joydip and people at Packt for your time in reviewing my draft version! Reviewer comments really made the book better and required me to do some small rewrites, elaborate more on certain topics.

    What tools did you use for writing?

    There are some tools that you really need when writing a technical book. One of them is a text editor, in my case Microsoft Word 2007. Together with that, Visual Studio 2008 and regularly updated ASP.NET MVC versions were required. Being scared of losing data, I decided to also use a source control system for sample code ánd for my Word documents. All of these files were stored in a Subversion repository located on my server, being backed up every day to different locations. Doug Mahugh laughed at me when I said I was using Subversion, but it did a great job!

    Other tools I used were Paint.NET and MwSnap, both for creating screenshots in my virtual PC running Windows Vista and Visual Studio 2008. I also used Achievo for time tracking purposes, since I was curious how much time this book writing would actually cost me.

    How much time did you spend writing?

    First of all, this is not going to be 100% accurate. I did track writing and development time during writing, but I already had a lot of material to work with. But here's an overview (numbers in hours):

    image

    That is right: writing a book consumes only a little more than 100 hours! But still, I already had lots of material. I'd say to double the number for an accurate timeframe.

    Now I hear the next question coming... Here's the answer already: Yes, I have a girlfriend. We are working on our home (planning phase is done, searching a contractor at the moment), visiting family, doing daily stuff, blogging, work, ... It al worked out to fit together, but still: there have been some busy moments on evenings and weekends. Thanks, people around me, for being patient and caring during these busy moments!

    Are you getting rich out of this?

    Of course, I can grab a couple of beers (for a couple of times), but don't think writing a book will buy you a car... I just felt that I had lots of valuable information that I had to share, and writing a book seemed like the best option to do that. Creating a "to read"-list? Make sure to add ASP.NET MVC 1.0 Quickly to it.

    kick it on DotNetKicks.com


    Checking username availability with jQuery (screencast)

    A new screencast has just been uploaded to the MSDN Belgium Chopsticks page. Don't forget to rate the video!

    Checking username availability with jQuery

    Abstract: "This screencast explains how to use jQuery and the ASP.NET MVC framework to quickly add a username availability checker to a user registration page."

    kick it on DotNetKicks.com


    ASP.NET MVC XForms released on CodePlex

    Just noticed there's a new project on CodePlex related to the ASP.NET MVC framework: MVC XForms. MVC XForms is a simple UI framework for ASP.NET MVC based on the W3C XForms specification. It provides a set of form controls that allow updating of complex model objects.

    Picked these project goals from Jon Curtis' blog:

    • To allow automatic form population, deserialization and validation based on the (arbitrarily complex) model.
    • To produce semantic HTML forms using the logic of XForms.
    • To output clean, terse HTML.
    • No javascript, unless necessary and always optional and unobtrusive.
    • To enable clean, terse view code.
    • To make the framework as extensible and customisable as possible without compromising simplicity or the above goals.
    • Use convention over configuration and a fluent API.

    Great story, but how does it work?

    I haven't gone into any advanced scenario's, but have instead used a simple case to demonstrate some of the MVC XForms basics. First of all, I've created a Person class with an Id (int), Name (string) and BirthDate (DateTime). This class is used by a specific view in my application, of which the view markup looks like this:

    <% Html.XForm(ViewData.Model).Form(form => { %>
      <%=form.Input(p => p.Name).Label("Name") %>
      <%=form.Input(p => p.BirthDate).Label("Birth date") %>
    <% }); %>

    This is all there is to creating an MVC XForm. Note that I'm creating a XForm based on my model, and that I want an input field for the Name and BirthDate properties, each with a label supplied.

    On to rendering: the HTML generated by MVC XForm looks like the following:

    <form action="" method="post" class="xf xform">
      <div class="xf input text">
        <label for="Name">Name</label>
        <input id="Name" type="text" name="Name" value="Maarten Balliauw"/>
      </div>
      <div class="xf input date">
        <label for="BirthDate">Birth date</label>
        <input id="BirthDate" type="text" name="BirthDate" value="21-12-1983"/>
      </div>
    </form>
    <script type="text/javascript">
      $(document).ready(function(){mvc.xforms.init({"id":"","cons":[]})});
    </script>

    That's actually nice, clean HTML markup! Note the CSS classes that are applied on certain fields. For example, the div element for BirthDate has a CSS class "date", which can be used by, for example, jQuery to enable a date picker on that field.

    More information

    In the CodePlex download (http://www.codeplex.com/mvcxforms), there is a sample project which makes use of all simple and advanced ideas in MVC XForms. You can also check out Jon Curtis' blog posts on MVC XForms to read some more samples.

    kick it on DotNetKicks.com


    Partial page updates with ASP.NET MVC and jQuery (and action filters)

    When building an ASP.NET MVC application, chances are that you are using master pages. After working on the application for a while, it's time to spice up some views with jQuery and partial updates.

    Let's start with an example application which does not have any Ajax / jQuery. Our company's website shows a list of all employees and provides a link to a details page containing a bio for that employee. In the current situation, this link is referring to a custom action method which is rendered on a separate page.

    Example application

    Spicing things up with jQuery

    The company website could be made a little sexier... What about fetching the employee details using an Ajax call and rendering the details in the employee list? Yes, that's actually what classic ASP.NET's UpdatePanel does. Let's do that with jQuery instead.

    The employees list is decorated with a CSS class "employees", which I can use to query my DOM using jQuery:

    $(function() {
        $("ul.employees > li > a").each(function(index, element) {
            $(element).click(function(e) {
                $("<div />").load( $(element).attr('href') )
                            .appendTo( $(element).parent() );
                e.preventDefault();
            })
        });
    });

    What's this? Well, the above code instructs jQuery to add some behaviour to all links in a list item from a list decorated with the employees css class. This behaviour is a click() event, which loads the link's href using Ajax and appends it to the list.

    Now note there's a small problem... The whole site layout is messed up, because the details page actually renders itself using a master page.

    Messed-up employees list after performing an Ajax call

    Creating a jQueryPartial action filter

    The solution to this broken page is simple. Let's first create a new, empty master page, named "Empty.Master". This master page should have as many content placeholder regions as the original master page, and no other content. For example:

    <%@ Master Language="C#" AutoEventWireup="true" CodeBehind="Empty.Master.cs" Inherits="jQueryPartialUpdates.Views.Shared.Empty" %>

    <asp:ContentPlaceHolder ID="MainContent" runat="server" />

    We can now apply this master page to the details action method whenever an Ajax call is done. You can implement this behaviour by creating a custom action filter: jQueryPartial.

    public class jQueryPartial : ActionFilterAttribute
    {
        public string MasterPage { get; set; }

        public override void OnResultExecuting(ResultExecutingContext filterContext)
        {
            // Verify if a XMLHttpRequest is fired.
            // This can be done by checking the X-Requested-With
            // HTTP header.
            if (filterContext.HttpContext.Request.Headers["X-Requested-With"] != null
                && filterContext.HttpContext.Request.Headers["X-Requested-With"] == "XMLHttpRequest")
            {
                ViewResult viewResult = filterContext.Result as ViewResult;
                if (viewResult != null)
                {
                    viewResult.MasterName = MasterPage;
                }
            }
        }
    }

    This action filter checks for the precense of the X-Requested-With HTTP header, which is provided by jQuery when firing an asynchronous web request. When the X-Requested-With header is present, the view being rendered is instructed to use the empty master page instead of the original one.

    One thing left though: the action filter should be applied to the details action method:

    [jQueryPartial(MasterPage = "Empty")]
    public ActionResult Details(int id)
    {
        Employee employee =
            Employees.Where(e => e.Id == id).SingleOrDefault();

        ViewData["Title"] = "Details for " +
            employee.LastName + ", " + employee.FirstName;
        return View(employee);
    }

    When running the previous application, everything should render quite nicely now.

    Working example

    Want the sample code?

    You can download the sample code here: jQueryPartialUpdates.zip (134.10 kb)

    kick it on DotNetKicks.com


    Categories: ASP.NET | C# | General | MVC | jQuery