Maarten Balliauw {blog}

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

NAVIGATION - SEARCH

Authenticate Orchard users with AppFabric Access Control Service

From the initial release of Orchard, the new .NET CMS, I have been wondering how difficult (or easy) it would be to integrate external (“federated”) authentication like Windows Azure AppFabric Access Control Service with it. After a few attempts, I managed to wrap-up a module for Orchard which does that: Authentication.Federated.

After installing, configuring and enabling this module, Orchard’s logon page is replaced with any SAML 2.0 STS that you configure. To give you a quick idea of what this looks like, here are a few screenshots:

Orchard Log On link is being overriddenOrchard authentication via AppFabricOrchard authenticated via SAML - Username is from the username claim

As you can see from the sequence above, Authentication.Federated does the following:

  • Override the default logon link
  • Redirect to the configured STS issuer URL
  • Use claims like username or nameidentifier to register the external user with Orchard. Optionally, it is also possible to configure roles through claims.

Just as a reference, I’ll show you how to configure the module.

Configuring Authentication.Federated – Windows Azure AppFabric side

In my tests, I’ve been using the AppFabric LABS release, over at https://portal.appfabriclabs.com. From there, create a new namespace and configure Access Control Service with the following settings:

Identity Providers

  • Pick the ones you want… I chose Windows Live ID and Google

Relying Party Applications

Add your application here, using the following settings:

  • Name: pick one :-)
  • Realm: The http(s) root URL for your site. When using a local Orchard CMS installation on localhost, enter a non-localhost URL here, e.g. https://www.examle.org
  • Return URL: The root URL of your site. I chose http://localhost:12758/ here to test my local Orchard CMS installation
  • Error URL: anything you want
  • Token format: SAML 2.0
  • Token encryption: none
  • Token lifetime: anything you want
  • Identity providers: the ones you want
  • Rule groups: Create new rule group
  • Token signing certificate: create a Service Namespace token and upload a certificate for it. This can be self-signed. Ensure you know the certificate thumbprint as we will need this later on.

Edit Rule Group

Edit the newly created rule group. Click “generate” to generate some default rules for the identity providers chosen, so that nameidentifier and email claims are passed to Orchard CMS. Also, if you want to be the site administrator later on, ensure you issue a roles claim for your Google/Windows Live ID, like so:

Add a role claim for your administrator

Configuring Authentication.Federated – Orchard side

In Orchard, download Authentication.Federated from the modules gallery and enable it. After that, you’ll find the configuration settings under the general “Settings” menu item in the Orchard dashboard:

Authentication.Federated configuration

These settings speak for themselves mostly, but I want to give you some pointers:

  • Enable federated authentication? – Enables the module. Ensure you’ve first tested the configuration before enabling it. If you don’t, you may lose access to your Orchard installation unless you do some database fiddling…
  • Translate claims to Orchard user properties? – Will use claims values to enrich user data.
  • Translate claims to Orchard roles? – Will assign Orchard roles based on the Roles claim
  • Prefix for federated usernames (e.g. "federated_") – Just a prefix for federated users.
  • STS issuer URL – The STS issuer URL, most likely the root for your STS, e.g. .accesscontrol.appfabriclabs.com">https://<account>.accesscontrol.appfabriclabs.com
  • STS login page URL – The STS’ login page, e.g. .accesscontrol.appfabriclabs.com:443/v2/wsfederation">https://<account>.accesscontrol.appfabriclabs.com:443/v2/wsfederation
  • Realm – The realm configured in the Windows Azure AppFabric Access Control Service settings
  • Return URL base – The root URL for your website
  • Audience URL – Best to set this identical to the realm URL
  • X509 certificate thumbprint (used for issuer URL token signing) – The token signing certificate thumbprint

Thank you for getting me in Vegas!

I wish to thank everyone who has been voring for getting me in Vegas, speaking at MIX11. Without having expectations, I was really really surprised (and happy!) my session got selected. Thanks a bunch!

MIX11_BB_I'mSpeakingAt_2

Oh and thanks, RealDolmen, for supporting me in doing things like this!

MvcSiteMapProvider 3.0.0 released

Just a quick note to tell that MvcSiteMapProvider 3.0.0 has been released and is available on CodePlex and NuGet. This version is targeted at ASP.NET MVC 3. If you are still using ASP.NET MVC 2, no worries: version 2.3.1 contains the exact same functionality but is targeted at ASP.NET MVC 2.

The changelog:

Enjoy!

ASP.NET MVC and the Managed Extensibility Framewok on NuGet

imageIf you search on my blog, there’s a bunch of posts where I talk about ASP.NET MVC and MEF. And what’s cool: these posts are the ones that are actually being read quite often. I’m not sure about which bloggers actually update their posts like if it was software, but I don’t. Old posts are outdated, that’s the convention when coming to my blog. However I recently received a on of questions if I could do something with ASP.NET MVC 3 and MEF. I did, and I took things seriously.

I’m not sure if you know MefContrib. MefContrib is a community-developed library of extensions to the Managed Extensibility Framework (MEF). I decided to wear my bad-ass shoes and finally got around installing a Windows-friendly Git client and decided to just contribute an ASP.NET MVC + MEF component to MefContrib. And while I was at it, I created some NuGet packages for all MefContrib components.

Let’s see how easy it is to use ASP.NET MVC and MEF…

Here’s the sample code I used: MefMvc.zip (698.58 kb)

Obtaining MefContrib.MVC3 in an ASP.NET MVC application

Here’s the short version of this blog post section for the insiders: Install-Package MefContrib.MVC3

Assuming you have already heard something about NuGet, let’s get straight to business. Right-click your ASP.NET MVC project in Visual Studio and select “Add Library Package Reference…”. Search for “MefContrib.MVC3”. Once found, click the “Install” button.

This action will download and reference the new MefContrib.Web.Mvc assembly I contributed as well as the MefContrib package.

How to get started?

You may notice a new file “AppStart_MefContribMVC3.cs” being added to your project. This one is executed at application start and wires all the MEF-specific components into ASP.NET MVC 3. Need something else than our defaults? Go ahead and customize this file. Are you happy with this code block? Continue reading…

You may know that MEF is cool as ICE and thus works with Import, Compose and Export. This means that you can now start composing your application using [Import] and [Export] attributes, MefContrib will do the rest. In earlier posts I did, this also meant that you should decorate your controllers with an [Export] attribute. Having used this approach on many projects, most developers simply forget to do this at the controller model. Therefore, MefContrib.Web.Mvc  uses the ConventionCatalog from MefContrib to automatically export every controller it can find. Easy!

To prove it works, open your FormsAuthenticationService class and add an ExportAttribute to it. Like so:

1 [Export(typeof(IFormsAuthenticationService))] 2 public class FormsAuthenticationService : IFormsAuthenticationService 3 { 4 // ... 5 }

Do the same for the AccountMembershipService class:

1 [Export(typeof(IMembershipService))] 2 public class AccountMembershipService : IMembershipService 3 { 4 // ... 5 }

Now open up the AccountController and lose the Initialize method. Yes, just delete it! We’ll tell MEF to resolve the IFormsAuthenticationService and IMembershipService. You can even choose how you do it. Option one is to add properties for both and add an ImportAttribute there:

1 public class AccountController : Controller 2 { 3 [Import] 4 public IFormsAuthenticationService FormsService { get; set; } 5 6 [Import] 7 public IMembershipService MembershipService { get; set; } 8 9 // ... 10 }

The other option is to use an ImportingConstructor:

1 public class AccountController : Controller 2 { 3 public IFormsAuthenticationService FormsService { get; set; } 4 public IMembershipService MembershipService { get; set; } 5 6 [ImportingConstructor] 7 public AccountController(IFormsAuthenticationService formsService, IMembershipService membershipService) 8 { 9 FormsService = formsService; 10 MembershipService = membershipService; 11 } 12 }

Now run your application, visit the AccountController and behold: dependencies have been automatically resolved.

Conclusion

There’s two conclusions to make: MEF and ASP.NET MVC3 are now easier than ever and available through NuGet. Second: MefContrib is now also available on NuGet, featuring nifty additions like the ConventionCatalog and AOP-style interception.

Enjoy! Here’s the sample code I used: MefMvc.zip (698.58 kb)

Need domain registration?

Introducing the PHP on Azure Contest

It’s not every day that I get to be in the jury for a contest. It’s not every day that I deliver a training about PHP on Azure. Since this is about a contest where I’m doing both, I thought this is definitely worth telling you:

Download PDF contest flyerThe PHP on Azure Contest is a coding competition run by the PHP Benelux User Group supported by Microsoft. Windows Azure is Microsoft’s Cloud platform with tools and support for PHP.

Participate to win a ticket, airfare and hotel to visit MIX2012 in Las Vegas, a Windows Phone 7 or other great prizes!

The contest runs from February 1st 2011 to May 15th 2011.
Participants must register before February 28th 2011 to enter the contest. During that time you will build your masterpiece and blog regularly about your experiences of using PHP on the Windows Azure Platform (The good, the bad and the ugly). We even have a prize for the top blogger!

The winners will be announced during the Dutch PHP Conference 2011 in Amsterdam, 19-21 May 2011 (http://www.phpconference.nl/).

> More information about the contest
> Contest registration
> Getting started
> Register now for a free PHP on Azure Training on February 22nd 2011

Feel like building a killer application on Microsoft’s cloud platform? Want fame and glory, possibly with a MIX2012 visit? I know I would join this!  Check here for more information about the contest.

Viva, Las Vegas!

Vote your MIX sessionI have asked it last year, and I’ll ask it again. One of my session proposals made it to the “short”list for MIX11. One thing left though: votes are the only currency to get my session proposal in Vegas.

Here’s the session abstract:

Fun with ASP.NET MVC 3 and MEF

So you have a team of developers? And a nice architecture to build on? How about making that architecture easy for everyone and getting developers up to speed quickly? Learn all about integrating the managed extensibility framework and ASP.NET MVC for creating loosely coupled, easy to use architectures that anyone can grasp.

If you think this session deserves a place in Vegas, please cast your vote right here. And while you are at it, feel free to vote for both of my direct colleagues Kevin Dockx and Sandrino Di Mattia as well.

PS: No, I will not steal Mike Tyson’s tiger.

Writing an Orchard widget: LatestTwitter

Last week, Microsoft released Orchard, a new modular CMS system built on ASP.NET MVC and a lot of other, open source libraries available. I will not dive into the CMS itself, but after fiddling around with it I found a lot of things missing: there are only 40 modules and widgets available at the moment and the only way to have a more rich ecosystem of modules is: contributing!

And that’s what I did. Feel the need to add a list of recent tweets by a certain user to your Orchard website? Try my LatestTwitter widget. Here’s a screenshot of the widget in action:

Orchard LatestTwitter widget

And here’s what the admin side looks like:

Orchard LatestTwitter widget admin

It supports:

  • Displaying a number of tweets for a certain user
  • Specifying the number of tweets
  • Caching the tweets for a configurable amount of minutes
  • Specifying if you want to display the avatar image and post time

In this blog post, I’ll give you some pointers on how to create your own widget for Orchard. Download the code if you want to follow step by step: LatestTwitter.zip (1.56 mb)

Setting up your development environment

This one is probably the easy part. Fire up the Web Platform Installer and install WebMatrix and the Orchard CMS to your machine. Why WebMatrix? Well, it’s the new cool kid on the block and you don’t want to load the complete Orchard website in your Visual Studio later on. I think WebMatrix is the way to go for this situation.

That’s it. Your local site should be up and running. It’s best to test the site and do some initial configuration. And another tip: make a backup of this initial site, it’s very easy to screw up later on (if you, like me, start fooling Orchard’s versioning system). In WebMatrix, you’ll find the path to where your site is located:

WebMatrix Orchard

Creating the blueprints for your widget

I’ll be quick on this one, if you need the full-blown details refer to Creating a module on the Orchard website.

Fire up a command prompt. “cd” to the root of your site, e.g. “C:\USB\_werk\Projects\AZUG\Azure User Group Belgium”. Execute the command “bin\orchard.exe”. After a few seconds, you’ll be in the command-line interface for Orchard. First of all, enable the code generation module, by executing the command:

1 feature enable Orchard.CodeGeneration

This module makes it easier to create new modules, widgets and themes. You can do all of that manually, but why go that route if this route allows you to be lazy? Let’s create the blueprints for our module:

1 codegen module LatestTwitter

There’s a new Visual Studio project waiting for you on your file system, in my case at “C:\USB\_werk\Projects\AZUG\Azure User Group Belgium\Modules\LatestTwitter”. Easy, no?

Building the widget

In order to build a widget, you need:

  • A model for your widget “part”
  • A record in which this can be stored
  • A database table in which the record can be stored

Let’s start top down: model first. The model that I’m talking about is not an ASP.NET MVC “View Model”, it’s really the domain object you are working with in the rest of your widget’s back-end. I will be doing something bad here: I’ll just expose the domain model to the ASP.NET MVC view later on, for sake of simplicity and because it’s only one small class I’m using. Here’s how my TwitterWidgetPart model is coded:

1 public class TwitterWidgetPart : ContentPart<TwitterWidgetRecord> 2 { 3 [Required] 4 public string Username 5 { 6 get { return Record.Username; } 7 set { Record.Username = value; } 8 } 9 10 [Required] 11 [DefaultValue("5")] 12 [DisplayName("Number of Tweets to display")] 13 public int Count 14 { 15 get { return Record.Count; } 16 set { Record.Count = value; } 17 } 18 19 [Required] 20 [DefaultValue("5")] 21 [DisplayName("Time to cache Tweets (in minutes)")] 22 public int CacheMinutes 23 { 24 get { return Record.CacheMinutes; } 25 set { Record.CacheMinutes = value; } 26 } 27 28 public bool ShowAvatars 29 { 30 get { return Record.ShowAvatars; } 31 set { Record.ShowAvatars = value; } 32 } 33 34 public bool ShowTimestamps 35 { 36 get { return Record.ShowTimestamps; } 37 set { Record.ShowTimestamps = value; } 38 } 39 }

Just some properties that represent my widget’s settings. Do note that these all depend on a TwitterWidgetRecord, which is the persistency class used by Orchard. I’ll give you the code for that one as well:

1 public class TwitterWidgetRecord : ContentPartRecord 2 { 3 public virtual string Username { get; set; } 4 public virtual int Count { get; set; } 5 public virtual int CacheMinutes { get; set; } 6 public virtual bool ShowAvatars { get; set; } 7 public virtual bool ShowTimestamps { get; set; } 8 }

See these “virtual” properties everywere? Ever worked with NHibernate and have a feeling that this *may* just be similar? Well, it is! Orchard uses NHibernate below the covers. Reason for these virtuals is that a proxy for your class instance will be created on the fly, overriding your properties with persistence specific actions.

The last thing we need is a database table. This is done in a “migration” class, a class that is responsible for telling Orchard what your widget needs in terms of storage, content types and such. Return to your command prompt and run the following:

1 codegen datamigration LatestTwitter

A file called “Migrations.cs” will be created in your module’s directory. Just add it to your solution and have a look at it. The Create() method you see is called initially when your module is installed. It creates a database table to hold your TwitterWidgetRecord.

Note that once you have an install base of your widget, never tamper with this code again or people may get stuck upgrading your widget over time. Been there, done that during development and it’s no fun at all…

Because I started small, my Migrations.cs file looks a bit different:

1 public class Migrations : DataMigrationImpl { 2 public int Create() { 3 // Creating table TwitterWidgetRecord 4 SchemaBuilder.CreateTable("TwitterWidgetRecord", table => table 5 .ContentPartRecord() 6 .Column("Username", DbType.String) 7 .Column("Count", DbType.Int32) 8 ); 9 10 ContentDefinitionManager.AlterPartDefinition(typeof(TwitterWidgetPart).Name, 11 builder => builder.Attachable()); 12 13 return 1; 14 } 15 16 public int UpdateFrom1() 17 { 18 ContentDefinitionManager.AlterTypeDefinition("TwitterWidget", cfg => cfg 19 .WithPart("TwitterWidgetPart") 20 .WithPart("WidgetPart") 21 .WithPart("CommonPart") 22 .WithSetting("Stereotype", "Widget")); 23 24 return 2; 25 } 26 27 public int UpdateFrom2() 28 { 29 SchemaBuilder.AlterTable("TwitterWidgetRecord", table => table 30 .AddColumn("CacheMinutes", DbType.Int32) 31 ); 32 33 return 3; 34 } 35 36 public int UpdateFrom3() 37 { 38 SchemaBuilder.AlterTable("TwitterWidgetRecord", table => table 39 .AddColumn("ShowAvatars", DbType.Boolean) 40 ); 41 SchemaBuilder.AlterTable("TwitterWidgetRecord", table => table 42 .AddColumn("ShowTimestamps", DbType.Boolean) 43 ); 44 45 return 4; 46 } 47 }

You see these UpdateFromX() methods? These are “upgrades” to your module. Whenever ou deploy a new version to the Orchard Gallery and someone updates the widget in their Orchard site, these methods will be used to upgrade the database schema and other things, if needed. Because I started small, I have some upgrades there already…

The UpdateFrom1() is actually a required one (although I could have done this in the Create() method as well): I’m telling Orchard that my TwitterWidget is a new content type, that it contains a TwitterWidgetPart, is a WidgetPart and can be typed as a Widget. A lot of text, but basically I’m just telling Orchard to treat my TwitterWidgetPart as a widget rather than anything else.

Drivers and handlers

We need a handler. It is a type comparable with ASP.NET MVC’s filters and is executed whenever content containing your widget is requested. Why do we need a handler? Easy: we need to tell Orchard that we’re actually making use of a persitence store for our widget. Here’s the code:

1 public class TwitterWidgetRecordHandler : ContentHandler 2 { 3 public TwitterWidgetRecordHandler(IRepository<TwitterWidgetRecord> repository) 4 { 5 Filters.Add(StorageFilter.For(repository)); 6 } 7 }

There’s really no magic to this: it’s just telling Orchard to use a repository fo accessing TwitterWidgetRecord data.

Next, we need a driver. This is something that you can compare with an ASP.NET MVC controller. It’s used by Orchard to render administrative views, handle posts from the admin interface, … Here’s the code:

1 public class TwitterWidgetDriver 2 : ContentPartDriver<TwitterWidgetPart> 3 { 4 protected ITweetRetrievalService TweetRetrievalService { get; private set; } 5 6 public TwitterWidgetDriver(ITweetRetrievalService tweetRetrievalService) 7 { 8 this.TweetRetrievalService = tweetRetrievalService; 9 } 10 11 // GET 12 protected override DriverResult Display( 13 TwitterWidgetPart part, string displayType, dynamic shapeHelper) 14 { 15 return ContentShape("Parts_TwitterWidget", 16 () => shapeHelper.Parts_TwitterWidget( 17 Username: part.Username ?? "", 18 Tweets: TweetRetrievalService.GetTweetsFor(part), 19 ShowAvatars: part.ShowAvatars, 20 ShowTimestamps: part.ShowTimestamps)); 21 } 22 23 // GET 24 protected override DriverResult Editor(TwitterWidgetPart part, dynamic shapeHelper) 25 { 26 return ContentShape("Parts_TwitterWidget_Edit", 27 () => shapeHelper.EditorTemplate( 28 TemplateName: "Parts/TwitterWidget", 29 Model: part, 30 Prefix: Prefix)); 31 } 32 33 // POST 34 protected override DriverResult Editor( 35 TwitterWidgetPart part, IUpdateModel updater, dynamic shapeHelper) 36 { 37 updater.TryUpdateModel(part, Prefix, null, null); 38 return Editor(part, shapeHelper); 39 } 40 }

What you see is a Display() method, used for really rendering my widget on the Orchard based website. What I do there is building a dynamic model consisting of the username, the list of tweets and some of the options that I have configured. There’s a view for this one as well, located in Views/Parts/TwitterWidget.cshtml:

1 <ul class="latest-twitter-list"> 2 @foreach (var tweet in Model.Tweets) { 3 <text><!-- ... --></text> 4 } 5 </ul>

The above is the actual view rendered on the page where you place the LatestTwitter widget. Note: don’t specify the @model here or it will crash. Simple because the model passed in to this view is nothing you’d expect: it’s a dynamic object.

Next, there’s the two Editor() implementations, one to render the “settings” and one to persist them. Prettyu standard code which you can just duplicate from any tutorial on Orchard modules. The view for this one is in Views/EditorTemplates/Parts/TwitterWidget.cshtml:

1 @model LatestTwitter.Models.TwitterWidgetPart 2 3 <fieldset> 4 <legend>Latest Twitter</legend> 5 6 <div class="editor-label"> 7 @T("Twitter username"): 8 </div> 9 <div class="editor-field"> 10 @@@Html.TextBoxFor(model => model.Username) 11 @Html.ValidationMessageFor(model => model.Username) 12 </div> 13 14 <!-- ... --> 15 </fieldset> 16

Done! Or not? Wel, there’s still some logic left: querying Twitter and making sure we don’t whistle for the fail whale to come over by querying it too often.

Implementing ITweetRetrievalService

Being prepared for change is injecting dependencies rather than hard-coding them. I’ve created a ITweetRetrievalService interface responsible for querying Twitter. The implementation will be injected by Orchard’s dependency injection infrastructure later on. Here’s the code:

1 public interface ITweetRetrievalService 2 : IDependency 3 { 4 List<TweetModel> GetTweetsFor(TwitterWidgetPart part); 5 }

See the IDependency interface I’m inheriting? That’s the way to tell Orchard to look for an implementation of this interface at runtime. Who said dependency injection was hard?

Next, the implementation. Let’s first look at the code:

1 [UsedImplicitly] 2 public class CachedTweetRetrievalService 3 : ITweetRetrievalService 4 { 5 protected readonly string CacheKeyPrefix = "B74EDE32-86E4-4A58-850B-016E6F595CF9_"; 6 7 protected ICacheManager CacheManager { get; private set; } 8 protected ISignals Signals { get; private set; } 9 protected Timer Timer { get; private set; } 10 11 public CachedTweetRetrievalService(ICacheManager cacheManager, ISignals signals) 12 { 13 this.CacheManager = cacheManager; 14 this.Signals = signals; 15 } 16 17 public List<TweetModel> GetTweetsFor(TwitterWidgetPart part) 18 { 19 // Build cache key 20 var cacheKey = CacheKeyPrefix + part.Username; 21 22 return CacheManager.Get(cacheKey, ctx => 23 { 24 ctx.Monitor(Signals.When(cacheKey)); 25 Timer = new Timer(t => Signals.Trigger(cacheKey), part, TimeSpan.FromMinutes(part.CacheMinutes), TimeSpan.FromMilliseconds(-1)); 26 return RetrieveTweetsFromTwitterFor(part); 27 }); 28 } 29 30 protected List<TweetModel> RetrieveTweetsFromTwitterFor(TwitterWidgetPart part) 31 { 32 // ... query Twitter here ... 33 } 34 35 protected string ToFriendlyDate(DateTime sourcedate) 36 { 37 // ... convert DateTime to "1 hour ago" ... 38 } 39 }

I’ll leave the part wher I actually query Twitter for you to discover. I only want to focus on two little things here: caching and signaling. The constructor of the CachedTweetRetrievalService is accepting two parameters that will be injected at runtime: an ICacheManager used for caching the tweet list for a certain amount of time, and an ISignals which is used to fire messages through Orchard. In order to cache the list of tweets, I will have to combine both. Here’s the caching part:

1 // Build cache key 2 var cacheKey = CacheKeyPrefix + part.Username; 3 4 return CacheManager.Get(cacheKey, ctx => 5 { 6 ctx.Monitor(Signals.When(cacheKey)); 7 Timer = new Timer(t => Signals.Trigger(cacheKey), part, TimeSpan.FromMinutes(part.CacheMinutes), TimeSpan.FromMilliseconds(-1)); 8 return RetrieveTweetsFromTwitterFor(part); 9 });

First, I’m building a cache key to uniquely identify the data for this particular widget’s Twitter stream by just basing it on the Twitter username. Next, I’m asking the cachemanager to get the data with that particular cacheKey. No data available? Well, in that case our lambda will be executed: a monitor is added for a signal with my cache key. Sounds complicated? I’m just telling Orchard to monitor for a particular message that can be triggered, and once it’s triggered, the cache will automatically expire.

I’m also starting a new timer thread, which I just ask to send a signal through the application at a specific point in time: the moment where I want my cache to expire. And last but not least: data is returned.

Conclusion

To be honest: I have had to read quite some tutorials to get this up and running. But once you get the architecture and how components interact, Orchard is pretty sweet to develop against. And all I’m asking you now: go write some modules and widgets, and make Orchard a rich platform with a rich module ecosystem.

Want to explore my code? Here’s the download: LatestTwitter.zip (1.56 mb)
Want to install the widget in your app? Just look for “LatestTwitter” in the modules.

ASP.NET MVC and jQuery Mobile

jQuery MobileWith the release of Windows Phone 7 last year, I’m really interested in mobile applications. Why? Well, developing for Windows Phone 7 did not require me to learn new things. I can use my current skill set and build cool apps for that platform. But what about the other platforms? If you look at all platforms from a web developer perspective, there’s one library that also allows you to use your existing skill set: jQuery Mobile.

Know HTML? Know jQuery? Know *any* web development language like PHP, RoR or ASP.NET (MVC)? Go ahead and build great looking mobile web apps!

I’ll give you a very short tutorial, just enough to sparkle some interest. After that, it’s up to you.

Getting jQuery Mobile running in ASP.NET MVC

This one is easy. Start a new project and strip out anything you don’t need. After that, modify your master page to something like this:

1 <%@ Master Language="C#" Inherits="System.Web.Mvc.ViewMasterPage" %> 2 3 <!DOCTYPE html> 4 <html> 5 <head runat="server"> 6 <title><asp:ContentPlaceHolder ID="TitleContent" runat="server" /></title> 7 <link href="../../Content/Site.css" rel="stylesheet" type="text/css" /> 8 9 <link rel="stylesheet" href="http://code.jquery.com/mobile/1.0a2/jquery.mobile-1.0a2.min.css" /> 10 <script src="http://code.jquery.com/jquery-1.4.4.min.js"></script> 11 <script src="http://code.jquery.com/mobile/1.0a2/jquery.mobile-1.0a2.min.js"></script> 12 </head> 13 14 <body> 15 <asp:ContentPlaceHolder ID="MainContent" runat="server" /> 16 </body> 17 </html> 18

That’s it: you download all resources from jQuery’s CDN. Optionally, you can also download and host jQuery Mobile on your own server.

Creating a first page

Pages have their own specifics. If you look at the docs, a page typically consists of a div element with a HTML5 data attribute “data-role” “page”. These data attributes are used for anything you would like to accomplish, which means your PC or device needs a HTML5 compatible browser to render jQuery Mobile content. Here’s a simple page (using ASP.NET MVC):

1 <%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<RealDolmenMobile.Web.Models.ListPostsModel>" %> 2 3 <asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server"> 4 Page title 5 </asp:Content> 6 7 <asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server"> 8 <div data-role="page"> 9 10 <div data-role="header"> 11 <h1>Title here</h1> 12 </div> 13 14 <div data-role="content"> 15 <p>Contents here</p> 16 </div> 17 18 <div data-role="footer"> 19 <h4>Footer here</h4> 20 </div> 21 </div> 22 </asp:Content>

Building a RSS reader

I’ve been working on a simple sample which formats our RealDolmen blogs into jQuery Mobile UI. Using Argotic as the RSS back-end, this was quite easy to do. First of all, here’s a HomeController that creates a list of posts in a view model. MVC like you’re used to work with:

1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Web; 5 using System.Web.Mvc; 6 using Argotic.Syndication; 7 using RealDolmenMobile.Web.Models; 8 using System.Web.Caching; 9 10 namespace RealDolmenMobile.Web.Controllers 11 { 12 [HandleError] 13 public class HomeController : Controller 14 { 15 private static readonly Uri Feed = new Uri("http://microsoft.realdolmenblogs.com/Syndication.axd"); 16 17 public ActionResult Index() 18 { 19 // Create model 20 var model = new ListPostsModel(); 21 22 GenericSyndicationFeed feed = GenericSyndicationFeed.Create(Feed); 23 foreach (GenericSyndicationItem item in feed.Items) 24 { 25 model.Posts.Add(new PostModel 26 { 27 Title = item.Title, 28 Body = item.Summary, 29 PublishedOn = item.PublishedOn 30 }); 31 } 32 33 return View(model); 34 } 35 }

Next, we need to render this. Again, pure HTML goodness that you’re used working with:

1 <%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<RealDolmenMobile.Web.Models.ListPostsModel>" %> 2 3 <asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server"> 4 RealDolmen Blogs 5 </asp:Content> 6 7 <asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server"> 8 <div data-role="page"> 9 10 <div data-role="header"> 11 <h1>RealDolmen Blogs</h1> 12 </div> 13 14 <div data-role="content"> 15 <ul data-role="listview"> 16 <li data-role="list-divider">Posts by employees<span class="ui-li-count"><%:Model.Posts.Count()%></span></li> 17 <% 18 foreach (var post in Model.Posts) 19 { 20 %> 21 <li> 22 <h3><%:Html.ActionLink(post.Title, "Post", new { title = post.Title })%></h3> 23 <p class="ui-li-aside">Published: <%:post.PublishedOn.ToString()%></p> 24 </li> 25 <% 26 } 27 %> 28 </ul> 29 </div> 30 31 <div data-role="footer"> 32 <h4>&nbsp;</h4> 33 </div> 34 </div> 35 </asp:Content>

The result? Not very stunning when looked at with IE8… But fire up Chrome or any other HTML5 capable browser, and here’s what you get:

RealDolmen Blogs Mobile

I’ve asked some people to check http://rd.cloudapp.net (may be offline by the time you read this), and I’ve received confirmation that it looks good on iSomething-devices, a Nokia and some Opera Mobile versions. Nice!

Goodies

The above example may not be that spectacular. The framework does hold some spectacular things! Think dialogs, forms, gestures, animations and a full-blown navigation framework that replaces any form or hyperlink with an AJAX call that is executed in the back-end, displays a nice “loading” screen and automatically generates a “back” button for you.

More examples? Check the manual itself over at http://jquerymobile.com/demos/1.0a2/docs/: this has been built using jQuery Mobile and looks nice!

Conclusion

It’s great! Really, I can just go ahead and build cool mobile web sites / web apps. Unfortunately, the WIndows-market of devices has bad support (due to a lack of HTML 5 support on their devices). This should get fixed in a coming upgrade, but untill then you will not have any luck running these apps on Windows Phone 7… For a complete list of compatible browsers and platforms, check the compatibility matrix.

For those interested, I’ve uploaded my small test app here: RealDolmenMobile.zip (420.38 kb) (note that I've built this as a Windows Azure solution)

Tools for the lazy: Templify and NuGet

In this blog post, I will cover two interesting tools that, when combined, can bring great value and speed at the beginning of any new software project that has to meet standards that are to be re-used for every project. The tools? Templify and NuGet.

You know the drill. Starting off with a new project usually consists of boring, repetitive tasks, often enforced by (good!) practices defined by the company you work for (or by yourself for that company). To give you an example of a project I’ve recently done:

  1. Create a new ASP.NET MVC application in Visual Studio
  2. Add 2 new projects: <project>.ViewModels and <project>.Controllers
  3. Do some juggling by moving classes into the right project and setting up the correct references between these projects

Maybe you are planning to use jQuery UI?

  1. Add the required JavaScript and CSS files to the project.

Oh right and what was that class you needed to work with MEF inside ASP.NET MVC? Let’s add that one as well:

  • Add the class for that
  • Add a reference to System.ComponentModel.Composition to the project

Admit it: these tasks are boring, time consuming and boring. Oh and time consuming. And boring. What if there were tools to automate a lot of this? And when I say a lot, I mean a LOT! Meet Templify and NuGet.

Introduction to Templify and NuGet

Well, let me leave this part to others. Let’s just do the following as an introduction: Templify is a tool that automates solution setup for Visual Studio in a super simple manner. It does not give you a lot of options, but that’s OK. Too much options are always bad. Want to read more on Templify? Check Howard van Rooijen’s introductory post.

NuGet (the package manager formerly known as NuPack) is a package manager for Visual Studio. It’s simple and powerful. Check Scott Hanselman’s excellent introduction post on this.

Scenario

Let’s go with the scenario I started my blog post with. You want to automate the boring tasks that are required at every project start. Here’s a simple one, usually it’s even more.

  1. Create a new ASP.NET MVC application in Visual Studio
  2. Add 2 new projects: <project>.ViewModels and <project>.Controllers
  3. Do some juggling by moving classes into the right project and setting up the correct references between these projects

Oh right and what was that class you needed to work with MEF inside ASP.NET MVC? Let’s add that one as well:

  • Add the class for that
  • Add a reference to System.ComponentModel.Composition to the project

Let’s automate the first part using Templify and the second part using NuGet.

Creating the Templify package

I have some bad news for you: you’ll have to take all project setup steps one more time! Create a new solution with a common name, e.g. “templateproject”. Add project references, library references, anything you need for this project to be the ideal base solution for any new project. Here’s an overview of what I am talking about:

Create new Templify project

Next, close Visual Studio and browse to the solution’s root folder location. After installing Templify, a new contect-menu item will be available: “Templify this folder”. Click it!

Templify this folder

After clicking it, a simple screen will be presented, asking you for 4 simple things: Name, Token, Author and Version. Easy! Name is the name for the package. Token is the part of the project name / namespace name / whatever you want to have replace with the next project’s common name. In my case, this will be “templateproject”. Author and version are easy as well.

Templify main screen

Click “Templify”, and behold! Nothing seems to have happened! Except for a small notification in your systray area. But don’t fear: a package has been created for your project and you can now execute the first steps of the scenario described above.

Templify package created

That’s basically it. If you want to redistribute your Templify package, check the C:\Users\%USERNAME%\AppData\Roaming\Endjin\Templify\repo  folder for that.

Creating a NuGet package

For starters, you will need the nuget.exe command-line utility. If that prerequisite is on your machine, you are already half-way. And to be honest: if you read the documentation over at the NuGet CodePlex project page you are there all the way! But I’ll give you a short how-to. First, create a folder structure like this:

  • content (optional)
  • lib (optional)
  • <your package name>.nuspec

In the content folder, simply put anything you would like to add into the project. ASP.NET MVC Views, source code, anything. In the lib folder, add all assembly references tatshould be added.

Next, edit the <your package name>.nuspec file and add relevant details for your package:

1 <?xml version="1.0"?> 2 <package xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 3 xmlns:xsd="http://www.w3.org/2001/XMLSchema"> 4 <metadata xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd"> 5 <id>MefDependencyResolver</id> 6 <version>0.0.1</version> 7 <authors>Maarten Balliauw</authors> 8 <requireLicenseAcceptance>false</requireLicenseAcceptance> 9 <description>MefDependencyResolver</description> 10 <summary>MefDependencyResolver</summary> 11 <language>en-US</language> 12 </metadata> 13 </package>

Once that’s done, simply call nuget.exe like so: nuget pack MefDependencyResolver\mefdependencyresolver.nuspec
Note that this can also be done using an MSBUILD command in any project.

If NuGet is finished, a new package should be available, in my above situation the MefDependencyResolver.0.0.1.nupkg file is generated.

Creating a NuGet feed

This one’s easy. You can use an OData feed (see here and here), but what’s even easier: just copy all packages to a folder or network share and point Visual Studio there. Fire up those Visual Studio settings, find the Package Manager node and add your local or network package folder:

Creating a NuGet feed

Done!

Behold! A new project!

So you took all the effort in creating a Templify and NuGet package. Good! Here’s how you can benefit. Whenever a new project should be started, open op an Explorer window, create a new folder, right-click it and select “Templify here”. Fill out the name of the new project (I chose “ProjectCool” because that implies I’m working on a cool project and cool projects are fun!). Select the template to deploy. Next, click “Deploy template”.

Templify Deploy Template

Open up the folder you just created and behold: “ProjectCool” has been created and my first 3 boring tasks are now gone. If I don’t tell my boss I have this tool, I can actually sleep for the rest of the day and pretend I have done this manually!

ProjectCool has been Templified!

Next, open up “ProjectCool” in Visual Studio. Right-click the ASP.NET MVC project and select “Add library package reference…”.

Add library package reference

Select the feed you just created and simply pick the packages to install into this application. Need a specific set of DiaplayTemplates? Create a package for those. Need the company CSS styles for complex web applications? Create a package for that! Need jQuery UI? Create a package for that!

Install NuGet package

Conclusion

I’m totally going for this approach! It speeds up initial project creation without the overhead of maintaining automation packages and such. Using simple tooling that is easy to understand, anyone on your project team can take this approach, both for company-wide Templify and NuGet packages, as well as individual packages.

Personally, I would like to see these two products combined into one, in the scenario outlined here. However I would already be happy if I could also create a company-wide “Templify” feed, ideally integrated with the NuGet tooling.

For fun and leasure, I packaged everything I created in this blog post: TemplifyNuGet.zip (508.23 kb)

Byebye 2010, welcome 2011!

fireworks

Happy New Year 2011! I wish you all the best in your career and personal life. And I know it’s a classic one: I wish you a good health! Some family members have had some serious issues on that part and really, health is the most imprtant thing you need. All the rest depends on that. If you’re healthy, you will do something, that something will earn you money, and money buys you things. An Indian taxi driver in Redmond, Seattle, WA told me this exact lesson this year. I was a bit fuzzy at that time after a long flight from Belgium, Europe, but he is right. Sandeep, happy new year to you to although you may probably not read my blog.

In this kind of posts, just like in 2008 and 2009, I’ll start with looking at the top blog posts.

Top 5 blog posts of 2010

  1. Code performance analysis in Visual Studio 2008 (2009: 3rd; 2008: 2nd) – Visual Studio developer, did you know you have a great performance analysis (profiling) tool at your fingertips?
  2. ASP.NET load balancing and ASP.NET state server (aspnet_state) (2009: 5th; 2008: 3rd) – A how-to on load balancing with ASP.NET. Also related to ASP.NET Session State Partitioning and ASP.NET Session State Partitioning using State Server Load Balancing.
  3. Code based ASP.NET MVC GridView (2009: 2nd; 2008: 4th) – This post gives a shot at a gridview for the ASP.NET MVC framework, built using expressions.
  4. Building an ASP.NET MVC sitemap provider with security trimming (2009: 4th; 2008: 5th) – Building an ASP.NET MVC sitemap provider that can be used with standard ASP.NET sitemap controls.
  5. ASP.NET MVC and the Managed Extensibility Framework (MEF) (newcomer!) – Showing some integration points of the managed extensibility framework with ASP.NET MVC.

It’s stunning to see there’s only one newcomer in this list, ASP.NET MVC and the Managed Extensibility Framework (MEF). All other top posts are from 2008 (!), cover older technology but are still of value. Is this because these posts rank higher in search engines? Is it because people use older technology more then cutting edge technology? I’m really interested in this, as I may shift focus to cover a bit more of the “older” technologies for 2011 if this is indeed the case.

Open-source in 2010

I continued to work on PHPExcel, PHPLinq, PHPPowerPoint, the Windows Azure SDK for PHP (with Microsoft), ASP.NET MVC SiteMap Provider, some contributions to Zend Framework, my port of MEF to PHP and that’s about it I guess.

I’m very happy with the contributors to PHPExcel and the fact that this library is being used so widely. Really great to see! Also, I’ve received some financial support for the other projects and that really helped in getting things forward. I would also like to thank Microsoft and my employer, RealDolmen, for providing much needed development time on these projects.

Presentations in 2010

Ok, presentations. This kind of exploded in 2010. I wanted to do “some” more in 2010, it actually were around 17 on large events and some more at smaller events, our AZUG user group and internal sessions at RealDolmen.

The best thing: out of these 17 large-event sessions, I did 11 abroad throughout Europe. That’s not glamourous life, but it’s great to meet peers from all around the world. I’m absolutely wanting to do more of this in 2011.

The list of sessions can be found on my talks and presentations page. If you want me to speak at your conference, feel free to shoot me an e-mail. I'll be happy to provide you with session proposals. That’s in bold because it’s a hint for all you conference organizers out there :-)

Most valuable professional

image In July 2009, I became an MVP ASP.NET. And in July 2010, this title got renewed. I’m very happy for that, it’s a great honour and a great door-opener for other things I do.

My focus was still on ASP.NET MVC in 2010, but also more and more on Windows Azure. These two make a great combination, and will be the main topics for my blog in 2011 as well.

Traveling in 2010

A lot of traveling in 2010… A lot! I went on a ski vacation and a summer vacation, but next to that I did some traveling for work and conferences as well:

  • Lisbon, Portugal (2 times)
  • London, UK
  • Vienna, Austria. A beautiful city!
  • Helsinki, Finland (2 times). Cold but warm people!
  • Poznan, Poland. Great wodka, cheap wodka and great people!
  • Copenhagen, Denmark
  • Seattle, US

A lot of airmiles this year, too bad they are on separate frequent flyer programs. This year I also discovered www.tripit.com, a great site for tracking everything related to your trip!

Thank you!

I do take credit for all that I did in 2010, but I would also like to thank my company RealDolmen for providing enough room to do some of this during work hours, as well as for challenging me in this. Recruiters often offer great salaries, but this is what I find important. And as far as I know, this is also quite unique in Belgium for a company to do. Thanks guys, really!

My family is also great, especially my wife. I’m often out of the house at evenings to various local events, writing blog posts, traveling abroad or just toying with technology. Thanks for letting me do this, I owe all of you big time!

Next, thank YOU too! For reading my blog, following me on Twitter and providing me insights and inspiration to do what I love to do. Feel free to ask me questions and to challenge me.

Summary and look ahead

All traveling and presentations weighed a bit on my blogging habits. Down from 79 posts to 48. It’s been a busy year, both for professional and community work. I hope to be able to invest even more in the latter, but we’ll see.

Oh right, I did some articles for PHP architect, .NET magazine, Technet, the WIndows Azure website, … I also became a cloud leader apparently, even though I’m just a technology enthousiast with an opinion. For 2011, I will probably do a little less articles but that’s in favour of writing a book with some other guys. It’ll be great, I promise. But more on that later.

Enjoy 2011, I definitely will! Oh and Sandeep, if I’m in Redmond again I definitely want you as my taxi driver.