Maarten Balliauw {blog}

ASP.NET MVC, Microsoft Azure, PHP, web development ...

NAVIGATION - SEARCH

Creating an external facing Azure Worker Role endpoint

Internet facing Azure Worker Role When Windows Azure was first released, only Web Roles were able to have an externally facing endpoint. Since PDC 2009, Worker Roles can now also have an external facing endpoint, allowing for a custom application server to be hosted in a Worker Role. Another option would be to run your own WCF service and have it hosted in a Worker Role. Features like load balancing, multiple instances of the Worker are all available. Let’s see how you can create a simple TCP service that can display the current date and time.

Here’s what I want to see when I connect to my Azure Worker Role using telnet (“telnet efwr.cloudapp.net 1234”):

Telnet Azure Worker Role

Let’s go ahead and build this thing. Example code can be downloaded here: EchoCloud.zip (9.92 kb)

kick it on DotNetKicks.com

Configuring the external endpoint

Fire up your Visual Studio and create a new Cloud Service, named EchoCloud, with one Worker Role (named EchoWorker). After you complete this, you should have a Windows Azure solution containing one Worker Role. Right-click the worker role and select Properties. Browse to the Endpoints tab and add a new endpoint, like so:

Configuring an external endpoint on a Windows Azure Worker Role

This new endpoint (named EchoEndpoint) listens on an external TCP port with port number 1234. Note that you can also make this an internal endpoint, which is an endpoint that can only be reached within your Windows Azure solution and not from an external PC. This can be useful if you wan to host a custom application server in your project and make it available for other Web and Worker Roles in your solution.

Building the worker role

As you know, a Worker Role (in the WorkerRole.cs file in your newly created solution) consists of 3 methods that can be implemented: OnStart, Run and OnStop. There’s also an event handler RoleEnvironmentChanging available. The method names sort of speak for themselves, but allow me to explain quickly:

  • OnStart() is executed when the Worker Role is starting. Initializations and some checks can be done here.
  • Run() is the method which contains the actual Worker Role logic. The cool stuff goes in here :-)
  • OnStop() can be used to do things that should be done when the Worker Role is stopped.
  • RoleEnvironmentChanging() is the event handler that gets called when the environment changes: configuration changed, extra instances fired, … are possible triggers for this.

Our stuff will go in the Run() method. We’ll be creating a new TcpListener which will sit and accept connections. Whenever a connection is available, it will be dispatched on a second thread that will be communicating with the client. Let’s see how we can start the TcpListener:

[code:c#]

public class WorkerRole : RoleEntryPoint
{
    private AutoResetEvent connectionWaitHandle = new AutoResetEvent(false);

    public override void Run()
    {
        TcpListener listener = null;
        try
        {
            listener = new TcpListener(
                RoleEnvironment.CurrentRoleInstance.InstanceEndpoints["EchoEndpoint"].IPEndpoint);
            listener.ExclusiveAddressUse = false;
            listener.Start();
        }
        catch (SocketException)
        {
            Trace.Write("Echo server could not start.", "Error");
            return;
        }

        while (true)
        {
            IAsyncResult result = listener.BeginAcceptTcpClient(HandleAsyncConnection, listener);
            connectionWaitHandle.WaitOne();
        }
    }
}

[/code]

First thing to notice is that the TcpListener is initialized using the IPEndpoint from the current Worker Role instance:

[code:c#]

listener = new TcpListener(
                RoleEnvironment.CurrentRoleInstance.InstanceEndpoints["EchoEndpoint"].IPEndpoint);

[/code]

We could have started the TcpListener using a static configuration telling it to listen on TCP port 1234, but that would be difficult for the Windows Azure platform. Instead, we start the TcpListener using the current IPEndpoint configuration that we set earlier in this blog post. This allows the application to run on the Windows Azure production environment, as well as on the development environment available from the Windows Azure SDK. Here’s how it would work if we had multiple Worker Roles hosting this application:

Multiple worker roles running a custom TCP server 

Second thing we are doing is starting the infinite loop that accepts connections and dispatches the connection to the HandleAsyncConnection method that will sit on another thread. This allows for having multiple connections into one Worker Role. Let’s have a look at the HandleAsyncConnection method:

[code:c#]

private void HandleAsyncConnection(IAsyncResult result)
{
    // Accept connection
    TcpListener listener = (TcpListener)result.AsyncState;
    TcpClient client = listener.EndAcceptTcpClient(result);
    connectionWaitHandle.Set();

    // Accepted connection
    Guid clientId = Guid.NewGuid();
    Trace.WriteLine("Accepted connection with ID " + clientId.ToString(), "Information");

    // Setup reader/writer
    NetworkStream netStream = client.GetStream();
    StreamReader reader = new StreamReader(netStream);
    StreamWriter writer = new StreamWriter(netStream);
    writer.AutoFlush = true;

    // Show application
    string input = string.Empty;
    while (input != "9")
    {
        // Show menu
        writer.WriteLine("…");

        input = reader.ReadLine();
        writer.WriteLine();

        // Do something
        if (input == "1")
        {
            writer.WriteLine("Current date: " + DateTime.Now.ToShortDateString());
        }
        else if (input == "2")
        {
            writer.WriteLine("Current time: " + DateTime.Now.ToShortTimeString());
        }

        writer.WriteLine();
    }

    // Done!
    client.Close();
}

[/code]

Code speaks for itself, no? One thing that you may find awkward is the connectionWaitHandle.Set();. In the previous code sample, we did connectionWaitHandle.WaitOne();. This means that we are not accepting any new connection until the current one is up and running. connectionWaitHandle.Set(); signals the original thread to start accepting new connections again.

Running the worker role

When running the application using the development fabric, you can fire up multiple instances. I fired up 4 Worker Roles that provide the simple TCP service that we just created. This means that my application will be load balanced, and every incoming connection will be distributed over these 4 Worker Role instances. Nifty!

Here’s a screenshot of my development fabric with two Worker Roles that I crashed intentionally. The service is still available, thanks to the fabric controller dispatching connections only to available Worker Role instances.

Development fabric with crashed worker roles

Example code

Example code can be downloaded here: EchoCloud.zip (9.92 kb)

Just a quick note: the approach described here can also be used to run a custom WCF host that has other bindings than for example basicHttpBinding.

kick it on DotNetKicks.com 

Ordering fields in ASP.NET MVC 2 templated helpers

Ever worked with the templated helpers provided by ASP.NET MVC 2? Templated helpers provide a way to automatically build UI based on a data model that is marked with attributes defined in the System.ComponentModel.DataAnnotations namespace. For example, a property in the model can be decorated with the attribute [DisplayFormat(DataFormatString = "{0:c}")], and the templated helpers will always render this field formatted as currency.

If you have worked with templated helpers, you must agree: they can be useful! There’s one thing which is impossible in the current version: ordering fields.

kick it on DotNetKicks.com

Take the following class and the rendered form using templated helpers:

ASP.NET MVC EditorForModel()

[code:c#]

public class Person
{
    public string Email { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

[/code]

Nice, but I would rather have the field “Email” displayed third. It would be nice if the field order could be applied using the same approach as with the System.ComponentModel.DataAnnotations namespace: let’s build us an attribute for it!

Building the OrderAttribute

Assuming you have already built an attribute once in your life, let’s go over this quickly:

[code:c#]

[global::System.AttributeUsage(AttributeTargets.Property, Inherited = true, AllowMultiple = false)]
public sealed class OrderAttribute : Attribute
{
    readonly int order;

    public OrderAttribute(int order)
    {
        this.order = order;
    }

    public int Order
    {
        get { return order; }
    }
}

[/code]

The OrderAttribute can be applied to any property of a model, and needs exactly one parameter: order. This order will be used to sort the fields being rendered. Here’s how our Person class may look like after applying the OrderAttribute:

[code:c#]

public class Person
{
    [Order(3)]
    public string Email { get; set; }

    [Order(1)]
    public string FirstName { get; set; }

    [Order(2)]
    public string LastName { get; set; }
}

[/code]

Speaks for itself, no? Now, before you stop reading: this will not work yet. The reason is that the default ModelMetadataProvider from the ASP.NET MVC framework, which provides the templated helpers all information they need about the model, does not know about this OrderAttribute. Let’s see what we can do about that…

Building the OrderedDataAnnotationsModelMetadataProvider

In order for the ASP.NET MVC framework to know and use the OrderAttribute created previously, we’re going to extend the default DataAnnotationsModelMetadataProvider provided with ASP.NET MVC 2. Here’s the code:

[code:c#]

public class OrderedDataAnnotationsModelMetadataProvider : DataAnnotationsModelMetadataProvider
{
    public override IEnumerable<ModelMetadata> GetMetadataForProperties(
        object container, Type containerType)
    {
        SortedDictionary<int, ModelMetadata> returnValue =
            new SortedDictionary<int, ModelMetadata>();

        int key = 20000; // sort order for "unordered" keys

        IEnumerable<ModelMetadata> metadataForProperties =
            base.GetMetadataForProperties(container, containerType);

        foreach (ModelMetadata metadataForProperty in metadataForProperties)
        {
            PropertyInfo property = metadataForProperty.ContainerType.GetProperty(
                metadataForProperty.PropertyName);

            object[] propertyAttributes = property.GetCustomAttributes(
                typeof(OrderAttribute), true);

            if (propertyAttributes.Length > 0)
            {
                OrderAttribute orderAttribute = propertyAttributes[0] as OrderAttribute;
                returnValue.Add(orderAttribute.Order, metadataForProperty);
            }
            else
            {
                returnValue.Add(key++, metadataForProperty);
            }
        }

        return returnValue.Values.AsEnumerable();
    }
}

[/code]

By overriding the GetMetadataForProperties, we’re hooking into the DataAnnotationsModelMetadataProvider’s moment of truth, the method where all properties of the model are returned as ModelMetadata. First of all, we’re using the ModelMetadata the base class provdes. Next, we use a little bit of reflection to get to the OrderAttribute (if specified) and use it to build a SortedDictionary of ModelMetadata. Easy!

One small caveat: non-decorated properties will always come last in the rendered output.

One thing left…

One thing left: registering the OrderedDataAnnotationsModelMetadataProvider with the ModelMetadataProviders infrastructure offered by ASP.NET MVC. Here’s how:

[code:c#]

protected void Application_Start()
{
    AreaRegistration.RegisterAllAreas();

    RegisterRoutes(RouteTable.Routes);

    ModelMetadataProviders.Current = new OrderedDataAnnotationsModelMetadataProvider();
}

[/code]

I guess you know this one goes into Global.asax.cs. If all works according to plan, your rendered view should now look like the following, with the e-mail field third:

image

kick it on DotNetKicks.com

Vote to help me speak at the MIX 2010 conference!

Everybody knows the Microsoft MIX event, right? The one in Las Vegas? The one with all the fancy web-related stuff? Rings a bell? Ok, great. In the beginning of December 2009, Microsoft did an open call for speakers, which I answered with some session proposals. Who doesn’t want to go to Vegas, right?

The open call proposals have been processed (150+ sessions submitted, wow!) and a voting has started. Yes, you hear me coming: please go ahead and vote for a session I submitted. Voting ends January 15th, 2010.

Since I could not decide which color of the voting banner matched best with my blog’s theme, I decided to put them all three online:

image

Thanks in advance!

Maarten

PS: There's also Elijah Manor, Justin Etheredge, K. Scott Allen, and many others who submitted good looking sessions.

kick it on DotNetKicks.com

Byebye 2009, welcome 2010!

Fireworks!

A year just ended, a new has begun. Congratulations! Happy newyear 2010! And welcome in the next decennium. It’s time for a 2009 wrap-up post. And perhaps, even the time for some things I want to do in 2010. First things first: the top 5 blog posts of 2009.

Top 5 blog posts of 2009

1. More ASP.NET MVC Best Practices – A blog post gathering best practices from different sources and adds some more of my own.

2. Code based ASP.NET MVC GridView (2008: 4th) – This post gives a shot at a gridview for the ASP.NET MVC framework, built using expressions.

3. Code performance analysis in Visual Studio 2008 (2008: 2nd) – Visual Studio developer, did you know you have a great performance analysis (profiling) tool at your fingertips?

4. Building an ASP.NET MVC sitemap provider with security trimming (2008: 5th) – Building an ASP.NET MVC sitemap provider that can be used with standard ASP.NET sitemap controls.

5. ASP.NET load balancing and ASP.NET state server (aspnet_state) (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.

I did a similar list last year, and you can see that I actually can stop blogging. 4 posts are in the top 5 again, with one newcomer on the 1st place.

Open-source in 2009

What should I say about this one… I did a lot of that :-) I continued to work on PHPExcel, PHPLinq and PHPPowerPoint, started work (with Microsoft) on the Windows Azure SDK for PHP, released the ASP.NET MVC SiteMap Provider, released TwitterMatic on CodePlex and did some contributions to Zend Framework. Then there’s also my port of MEF to PHP, which I will be releasing somewhere in Q1 2010.

That’s a lot! And I really hope to keep the same pace going in 2010. I’m constructing a house though, which also takes some time… Luckily: no windows yet, so I can consider it open-source as well :-)

Presentations in 2009

Let’s see what we have there… A lot! And I hope to do the same amount (or more) in 2010. TechDays Belgium, TechDays Finland and PHPBenelux conference have been confirmed already, a good start. Anyway: here’s the 2009 list. Note that there’s also some more at various schools in Belgium, and internal sessions for RealDolmen.

Cloud computing and the Windows Azure Services Platform

This session covers the basics of the Windows Azure Services Platform and drills into some architectural challenges. Learn what components the Windows Azure Services Platform is built of and how they can be leveraged in building a scalable and reliable application.

KU Leuven, December 7, 2009

Slides: http://www.slideshare.net/maartenba/cloud-computing-and-the-windows-azure-services-platform-ku-leuven

MSDN - Converting an existing ASP.NET application to Windows Azure

Put your stuff in the cloud! Windows Azure allows you to take advantage of cloud computing infranstructure for hosting, computing, and storage of your applications. In this demo filled session we take an existing ASP.Net Application and move it to be hosted in Windows Azure, while taking advantage of Windows Azure storage.

MSDN Live Meeting for MSDN Belgium, November 24, 2009

Slides: http://www.slideshare.net/maartenba/msdn-converting-an-existing-aspnet-application-to-windows-azure
Demo code: MSDN - Converting an existing ASP.NET application to Windows Azure.zip (2.01 mb)
Live recording: http://www.microsoft.com/belux/MSDN/fr/chopsticks/default.aspx?id=1491

ASP.NET MVC Wisdom

Building a Twitter clone in 60 minutes, featuring what's new in ASP.NET MVC 2 preview 1 and focusing on some of the core ASP.NET MVC features like security and routing.

Remix Belgium 2009, Brussels, September 29, 2009

Slides: http://www.slideshare.net/maartenba/aspnet-mvc-wisdom
Demo code: ASP.NET MVC Wisdom - ReMix.zip (8.91 mb)
Live recording: http://blog.maartenballiauw.be/post/2009/10/23/Recording-of-my-session-at-Remix-2009-ASPNET-MVC.aspx

PHP and Silverlight

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.

DevDays 2009, The Hague, May 29, 2009  -  May 29, 2009
Dutch PHP Conference, Amsterdam, June 12, 2009  -  June 12, 2009

Slides: http://www.slideshare.net/maartenba/php-and-silverlight-devdays-session?type=powerpoint
Demo code: PHP and Silverlight - DevDays.zip (1.00 mb)
Live recording (audio): http://techportal.ibuildings.com/2009/12/21/introduction-to-silverlight-for-php-developers/

PHPPowerPoint – More OpenXML from PHP

Session on the newly released open source project PHPPowerPoint, which enables you to build PPTX files from PHP. This session will provide you a general view of PHPPowerPoint and some architectural insights into the API.

DII Workshop, London, May 18, 2009  -  May 18, 2009

Mocking

This session provides an introduction to mocking and shows how test-driven development and the use of mocking frameworks such as Moq can speed up application development.

VISUG Belgium, May 7, 2009  -  May 7, 2009

Slides: http://www.slideshare.net/maartenba/mocking-visug-session?type=powerpoint
Demo code: MockingDemoCode.zip (1.64 mb)

ASP.NET MVC (model-view-controller)

This session provides an introduction to the ASP.NET MVC framework. Starting with a short intro to the model-view-controller pattern and Microsoft's vision on implementing this pattern for ASP.NET, over some of the key differences between ASP.NET Webforms and ASP.NET MVC to doing some more advanced things like scaffolding and action filters.

MSDN Belgium, April 23, 2009  -  April 23, 2009

Slides: http://www.slideshare.net/maartenba/msdn-aspnet-mvc?type=powerpoint

Azure User Group Belgium

image Together with Kurt Claeys and Yves Goeleven, we did a first session with the new Azure User Group Belgium. AZUG.BE is a Belgian user group with focus on development and architecture of the Windows Azure Platform. Our goal is to share knowledge and experiences with the .NET community on Windows Azure, .NET Services and SQL Azure.

Expect more activity and sessions in 2010!

I wrote a book!

image That’s correct: I did write a book. My first one, but probably not the last one. Don’t know when and on what, but I’ll probably find the energy to do this effort again. Here’s a quite from my announcement post:

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

Most valuable professional

image In July 2009, I became an MVP ASP.NET. Let’s see if we can repeat this for 2010 :-)

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

Traveling

Some traveling in 2009 as well. I went on a ski vacation and a summer vacation, but next to that I did some traveling for work as well:

If only I knew that these last two would provide me a lot of airmiles… Subscribed at www.milesandmore.com for possible traveling in 2010 :-)

Thank you!

I do take credit for all that I did in 2009, 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. Really appreciated guys!

Now is also a great moment to thank my family for not whining too much and also giving me the room to do all of this, often taking time out of family life. Thanks for letting me do all this!

Summary and look ahead

It’s been a relaxing year. No, seriously: I’ve been busy, and I expect the same for 2010… Not sure if I can do 79 blog posts again, but I will sure try. And in order to do that, I need some input from you:

  • What topics would you like to see covered?
  • Is there anything you want to learn more about?
  • A great conceptual idea, no time to work on it? Shoot! Maybe I will work on it.
  • Any other feedback for me?

Enjoy 2010! I will.

Hoping they will learn… Usability!

How about ending the year 2009 with a blog post on something annoying I see on the Internet, as well as some others? I’m talking about automatic localization… Please, go ahead and read some tweets by @KvdM and @patrickv. And then, there’s my own annoyance on Windows Mobile Marketplace. The base for al this frustrated year-end whining has to do with the fact that there are assumptions being made about the location of a user, rather than about a user itself…

On every request my browser makes, my preferred language is being sent out. Where I am, that would be “nl-BE” (Dutch, in Belgium). At my customer’s location, that would be “nl-NL” (Dutch, in the Netherlands). If everything works according to plan, both of these should be telling the website that I want to display it in Dutch. However, some websites out there like Twitter, Facebook, … look at the second part, serving me a “Belgian” version of the site in the first case and a “Netherlands” version in the second case. According to Wikipedia, a site that actually does the above trick in the correct fashion, Belgium has three official languages: Dutch, French and German. Since history however linked the French language to Belgium, most websites think that the default language for Belgium should be French. While I actually do send out my preferences on every request my browser makes.

No problem, I do speak (a little) French, so I am able to find the language switch on most websites in no time. It would be a bit nicer though if my preference was respected or switched to English if no Dutch version is available. The Internet is mostly English, I’m fine with that. Don’t get me wrong, I’m not one of those Flemish nationalists saying French is bad and the Walloon part of Belgium is bad. No, all I’m saying is that some websites are making wrong assumptions, forcing me to add an extra click (switching the language) to some of the sites I’m visiting. Not the ideal situation in an era where usability is something being focused on more and more.

Things do get worse sometimes. In the above situation, there was still a language switch. And then, there’s Windows Mobile Marketplace… The website does recognize I’m “nl-BE” and displays in Dutch. After installing the software on my cell phone and linking my Windows Live ID, it seems that the only market I can download software in is… Belgium – French! No problem, the software listed is the same as the one in the “Belgium – Dutch” market so I can download what I want, and I do speak enough French to find my way around. However: no language switch… Marketplace is something great, but there’s a small usability catch…

Someone pointed out that there’s something available which can switch the language for Marketplace, but it’s an extra tool I have to download and install. Usability? And for the other situation: I have “en-US” (English, USA) registered as the default language my browser sends out:

Default culture settings in Internet Explorer

This does fix a lot of usability frustration, but I think it’s not the way all of this was meant to be. So, when planning a new web application in 2010, do make use of all the information clients provide you. Don’t make assumptions, default to English if you don’t have the requested language available. And while you are thinking: also make use of OpenID or something like that for doing account registration. Small things can make a website much more usable!

That being said: enjoy the last days of 2009, enjoy the time-warp to 2010!

Cloud computing and the Windows Azure Services Platform (KU Leuven)

It was a fun session yesterday at KU Leuven university! I did a session on cloud computing and Windows Azure there for the IEEE Student Branch Leuven.

Abstract: "This session covers the basics of the Windows Azure Services Platform and drills into some architectural challenges. Learn what components the Windows Azure Services Platform is built of and how they can be leveraged in building a scalable and reliable application."

If you want more info about Windows Azure and how to develop, architect or benefit from the platform as a whole, register freely at the Azure User Group Belgium.

Thank you for attending!

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!

PHP Managed Extensibility Framework – PHPMEF

image While flying sitting in the airplane to the Microsoft Web Developer Summit in Seattle, I was watching some PDC09 sessions on my laptop. During the MEF session, an idea popped up: there is no MEF for PHP! 3500 kilometers after that moment, PHP got its own MEF…

What is MEF about?

MEF is a .NET library, targeting extensibility of projects. It allows you to declaratively extend your application instead of requiring you to do a lot of plumbing. All this is done with three concepts in mind: export, import and compose. (Glenn, I stole the previous sentence from your blog). “PHPMEF” uses the same concepts in order to provide this extensibility features.

Let’s start with a story… Imagine you are building a Calculator. Yes, shoot me, this is not a sexy sample. Remember I wrote this one a plane with snoring people next to me…The Calculator is built of zero or more ICalculationFunction instances. Think command pattern. Here’s how such an interface can look like:

[code:c#]

interface ICalculationFunction
{
    public function execute($a, $b);
}

[/code]

Nothing special yet. Now let’s implement an instance which does sums:

[code:c#]

class Sum implements ICalculationFunction
{
    public function execute($a, $b)
    {
        return $a + $b;
    }
}

[/code]

Now how would you go about using this in the following Calculator class:

[code:c#]

class Calculator
{
    public $CalculationFunctions;
}

[/code]

Yes, you would do plumbing. Either instantiating the Sum object and adding it into the Calculator constructor, or something similar. Imagine you also have a Division object. And other calculation functions. How would you go about building this in a maintainable and extensible way? Easy: use exports…

Export

Exports are one of the three fundaments of PHPMEF. Basically, you can specify that you want class X to be “ exported”  for extensibility. Let’s export Sum:

[code:c#]

/**
  * @export ICalculationFunction
  */
class Sum implements ICalculationFunction
{
    public function execute($a, $b)
    {
        return $a + $b;
    }
}

[/code]

Sum is exported as Sum by default, but in this case I want PHPMEF to know that it is also exported as ICalculationFunction. Let’s see why this is in the import part…

Import

Import is a concept required for PHPMEF to know where to instantiate specific objects. Here’s an example:

[code:c#]

class Calculator
{
    /**
      * @import ICalculationFunction
      */
    public $SomeFunction;
}

[/code]

In this case, PHPMEF will simply instantiate the first ICalculationFunction instance it can find and assign it to the Calculator::SomeFunction variable. Now think of our first example: we want different calculation functions in our calculator! Here’s how:

[code:c#]

class Calculator
{
    /**
      *  @import-many ICalculationFunction
      */
    public $CalculationFunctions;
}

[/code]

Easy, no? PHPMEF will ensure that all possible ICalculationFunction instances are added to the Calculator::CalculationFunctions array. Now how is all this being plumbed together? It’s not plumbed! It’s composed!

Compose

Composing matches all exports and imports in a specific application path. How? Easy! Use the PartInitializer!

[code:c#]

// Create new Calculator instance
$calculator = new Calculator();

// Satisfy dynamic imports
$partInitializer = new Microsoft_MEF_PartInitializer();
$partInitializer->satisfyImports($calculator);

[/code]

Easy, no? Ask the PartInitializer to satisfy all imports and you are done!

Advanced usage scenarios

The above sample was used to demonstrate what PHPMEF is all about. I’m sure you can imagine more complex scenarios. Here are some other possibilities…

Single instance exports

By default, PHPMEF instantiates a new object every time an import has to be satisfied. However, imagine you want our Sum class to be re-used. You want PHPMEF to assign the same instance over and over again, no matter where and how much it is being imported. Again, no plumbing. Just add a declarative comment:

[code:c#]

/**
  * @export ICalculationFunction
  * @export-metadata singleinstance
  */
class Sum implements ICalculationFunction
{
    public function execute($a, $b)
    {
        return $a + $b;
    }
}

[/code]

Export/import metadata

Imagine you want to work with interfaces like mentioned above, but want to use a specific implementation that has certain metadata defined. Again: easy and no plumbing!

My calculator might look like the following:

[code:c#]

class Calculator
{
    /**
      *  @import-many ICalculationFunction
      */
    public $CalculationFunctions;

    /**
      *  @import ICalculationFunction
      *  @import-metadata CanDoSums
      */
    public $SomethingThatCanDoSums;
}

[/code]

Calculator::SomeThingThatCanDoSums is now constrained: I only want to import something that has the metadata “CanDoSums” attached. Here’s how to create such an export:

[code:c#]

/**
  * @export ICalculationFunction
  * @export-metadata CanDoSums
  */
class Sum implements ICalculationFunction
{
    public function execute($a, $b)
    {
        return $a + $b;
    }
}

[/code]

Here’s an answer to a question you may have: yes, multiple metadata definitions are possible and will be used to determine if an export matches an import.

One small note left: you can also ask the PartInitializer for the metadata defined on a class.

[code:c#]

// Create new Calculator instance
$calculator = new Calculator();

// Satisfy dynamic imports
$partInitializer = new Microsoft_MEF_PartInitializer();
$partInitializer->satisfyImports($calculator);

// Get metadata
$metadata = $partInitializer->getMetadataForClass('Sum');

[/code]

Can I get the source?

No, not yet. For a number of reasons. I first want to make this thing a bit more stable, as well as deciding if all MEF features should be ported. Also, I’m looking for an appropriate name/library to put this in. You may have noticed the Microsoft_* naming, a small hint to the Interop team in incorporating this as another Microsoft library in the PHP world. Yes Vijay, talking to you :-)

Supporting multiple submit buttons on an ASP.NET MVC view

Multiple buttons on an ASP.NET MVC view A while ago, I was asked for advice on how to support multiple submit buttons in an ASP.NET MVC application, preferably without using any JavaScript. The idea was that a form could contain more than one submit button issuing a form post to a different controller action.

The above situation can be solved in many ways, one a bit cleaner than the other. For example, one could post the form back to one action method and determine which method should be called from that action method. Good solution, however: not standardized within a project and just not that maintainable… A better solution in this case was to create an ActionNameSelectorAttribute.

Whenever you decorate an action method in a controller with the ActionNameSelectorAttribute (or a subclass), ASP.NET MVC will use this attribute to determine which action method to call. For example, one of the ASP.NET MVC ActionNameSelectorAttribute subclasses is the ActionNameAttribute. Guess what the action name for the following code snippet will be for ASP.NET MVC:

[code:c#]

public class HomeController : Controller
{
    [ActionName("Index")]
    public ActionResult Abcdefghij()
    {
        return View();
    }
}

[/code]

That’s correct: this action method will be called Index instead of Abcdefghij. What happens at runtime is that ASP.NET MVC checks the ActionNameAttribute and asks if it applies for a specific request. Now let’s see if we can use this behavior for our multiple submit button scenario.

kick it on DotNetKicks.com

The view

Since our view should not be aware of the server-side plumbing, we can simply create a view that looks like this.

[code:c#]

<%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage<MvcMultiButton.Models.Person>" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title>Create person</title>
    <script src="<%=Url.Content("~/Scripts/MicrosoftAjax.js")%>" type="text/javascript"></script>
    <script src="<%=Url.Content("~/Scripts/MicrosoftMvcAjax.js")%>" type="text/javascript"></script>
</head>
<body>

    <% Html.EnableClientValidation(); %>
    <% using (Html.BeginForm()) {%>

        <fieldset>
            <legend>Create person</legend>
            <p>
                <%= Html.LabelFor(model => model.Name) %>
                <%= Html.TextBoxFor(model => model.Name) %>
                <%= Html.ValidationMessageFor(model => model.Name) %>
            </p>
            <p>
                <%= Html.LabelFor(model => model.Email) %>
                <%= Html.TextBoxFor(model => model.Email) %>
                <%= Html.ValidationMessageFor(model => model.Email) %>
            </p>
            <p>
                <input type="submit" value="Cancel" name="action" />
                <input type="submit" value="Create" name="action" />
            </p>
        </fieldset>

    <% } %>

    <div>
        <%=Html.ActionLink("Back to List", "Index") %>
    </div>

</body>
</html>

[/code]

Note the two submit buttons (namely “Cancel” and “Create”), both named “action” but with a different value attribute.

The controller

Our controller should also not contain too much logic for determining the correct action method to be called. Here’s what I propose:

[code:c#]

public class HomeController : Controller
{
    public ActionResult Index()
    {
        return View(new Person());
    }

    [HttpPost]
    [MultiButton(MatchFormKey="action", MatchFormValue="Cancel")]
    public ActionResult Cancel()
    {
        return Content("Cancel clicked");
    }

    [HttpPost]
    [MultiButton(MatchFormKey = "action", MatchFormValue = "Create")]
    public ActionResult Create(Person person)
    {
        return Content("Create clicked");
    }
}

[/code]

Some things to note:

  • There’s the Index action method which just renders the view described previously.
  • There’s a Cancel action method which will trigger when clicking the Cancel button.
  • There’s a Create action method which will trigger when clicking the Create button.

Now how do these last two work… You may also have noticed the MultiButtonAttribute being applied. We’ll see the implementation in a minute. In short, this is a subclass for the ActionNameSelectorAttribute, triggering on the parameters MatchFormKey and MatchFormValues. Now let’s see how the MultiButtonAttribute class is built…

The MultiButtonAttribute class

Now do be surprised of the amount of code that is coming…

[code:c#]

[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public class MultiButtonAttribute : ActionNameSelectorAttribute
{
    public string MatchFormKey { get; set; }
    public string MatchFormValue { get; set; }

    public override bool IsValidName(ControllerContext controllerContext, string actionName, MethodInfo methodInfo)
    {
        return controllerContext.HttpContext.Request[MatchFormKey] != null &&
            controllerContext.HttpContext.Request[MatchFormKey] == MatchFormValue;
    }
}

[/code]

When applying the MultiButtonAttribute to an action method, ASP.NET MVC will come and call the IsValidName method. Next, we just check if the MatchFormKey value is one of the request keys, and the MatchFormValue matches the value in the request. Simple, straightforward and re-usable.

kick it on DotNetKicks.com

Book review: Zend Framework 1.8 Web Application Development

Zend Framework 1.8 Web Application Development My book shelf is starting to look a lot like the warehouse of Packt Publishing: I’ve received yet another book from them. Different from all previous reviews I did: this one is a PHP book, titled “Zend Framework 1.8 Web Application Development” by Keith Pope.

A chapter overview:

  • Chapter 1: Creating a Basic MVC Application
  • Chapter 2: The Zend Framework MVC Architecture
  • Chapter 3: Storefront Basic Setup
  • Chapter 4: Storefront Models (great chapter!)
  • Chapter 5: Implementing the Catalog
  • Chapter 6: Implementing User Accounts
  • Chapter 7: The Shopping Cart
  • Chapter 8: Authentication and Authorization
  • Chapter 9: The Administration Area
  • Chapter 10: Storefront Roundup
  • Chapter 11: Storefront Optimization
  • Chapter 12: Testing the Storefront

Let’s also state the obvious: Zend Framework evolves much faster than publishers. The framework is now at 1.9.6, while the book covers 1.8.0. Do not let this stop you from reading this book! Let me explain why…

  1. The book covers all concepts and components in the Zend Framework in a full-blown application that is built up from scratch.
  2. Next to that, Keith Pope focuses a lot on the application design, using interfaces, unit testing, mocking, dependency injection, … Want to learn a lot about good application design? Then this is the number one reason to read this book!

These 2 points actually summarize the whole book. Great read, great content and a must-read for everyone who is not completely sure about his application design skills. Congratulations, Keith!