Creating a simple custom TFS 2010 build activity

Creating a custom build activity for TFS 2010 is fairly simple, in this post I’ll show you how to create a simple check out activity.

To create a custom build activity you need to inherit from either CodeActivity or CodeActivity<T>, both of which reside in System.Activities. CodeActivity<T> is used to return a value out of the activity where T is the return type.

To get data into your class you need to create your properties using InArgument<T> (InOutArgument<T> and OutArgument<T> are also available). For example, if you need to get a file name into your class you would create a property: public InArgument<string> Filename { get; set; } which will appear as a string property named Filename in the workflow designer.

Use the attribute [RequiredArgument] to specify that a value is required for a property.

Finally you need to override the Execute method, this is the method that will contain the execution code for your build activity. The code activity context will be passed into this method which will allow you to access your properties. Once you have dragged the activity onto your build workflow you simply need to set the Workspace property to Workspace and set the FilePath property to the server path for the file you want to check out.


public sealed class CheckOutFile : CodeActivity
{
  [RequiredArgument]
  public InArgument<Workspace> Workspace { get; set; }

  [RequiredArgument]
  public InArgument<string> FilePath { get; set; }

  protected override void Execute(CodeActivityContext context)
  {
    // Obtain the runtime values
    Workspace workspace = context.GetValue(Workspace);
    String filePath = context.GetValue(FilePath);

    // Get the pending changes to the filePath
    PendingChange[] pendingChanges =
    workspace.GetPendingChanges(filePath, RecursionType.Full);

    // If no pending change for the filePath was found
    // it means the file is can be checked out
    if (pendingChanges.Length == 0)
    {
      // Check out the file
      workspace.PendEdit(filePath, RecursionType.Full);
    }
  }
}

Using a custom crossdomain.xml policy file with Flex 3/4

Recently I needed to use ActionScript’s URLLoader class to retrieve XML from a .NET Web Service, I had no problems until I tried to access the Web Service on a remote machine (i.e. not localhost). When I tried to do this I got the error:

Error #2048: Security sandbox violation: http://localhost/myapplication/main.swf cannot load data from http://remotemachine/webservice.

Not the most useful error message. Searching the web for this error produced a lot of useless results, eventually I discovered that I needed a crossdomain.xml policy file on the remote machine (in the web server root, in this case c:\inetpub\wwwroot) that grants the calling machine access. Where the crossdomain.xml file is in the format shown below (the domain attribute would obviously be replaced with one of the items mentioned in quotes).

<cross-domain-policy>
    <allow-access-from domain="URL" />
    <allow-access-from domain="URL Wildcard" />
    <allow-access-from domain="Specific IP Address" />
</cross-domain-policy>

My web service doesn’t know the URL or IP address of the application that will be calling it so I need to use domain=”*” to allow anyone to connect but if I put this in the cross domain policy file that is in the root it applies that access to everything below it not just my web service which is sitting in /webservice. This is obviously undesirable, so the solution seems simple – place the crossdomain.xml file in the /webservice directory.

In the code you would make the following call before making the request with the URLLoader class:

Security.loadPolicyFile("http://remotemachine/webservice/crossdomain.xml");

This tells the Flash framework to load a custom cross-domain policy file, simple right? No.
Unfortunately this did nothing, using Fiddler2 I could see that the custom cross-domain policy file was being requested at downloaded successfully, but wasn’t working for some reason.

Again, after searching through many useless results on the web claiming to describe how to fix the problem I discovered what to do, and it’s pretty simple (the links that I found are at the end of this article).

You need to create a cross-domain policy file (i.e. crossdomain.xml) in the root of the web server that allows custom cross-domain policy files and then Security.loadPolicyFile() will actually use the custom cross-domain policy file specified in /webservice.

You have a number of options for restricting how custom cross-domain policy files are used, the easiest and least restrictive is to allow all custom cross-domain policy files, to do this you would used the following:

<cross-domain-policy>
	<site-control permitted-cross-domain-policies="all" />
</cross-domain-policy>

The option I went with is to only allow policy files with a specific content-type, the master policy file (in the root of your web server) would contain the following:

<cross-domain-policy>
	<site-control permitted-cross-domain-policies="by-content-type" />
</cross-domain-policy>

Then I set up (in IIS) the extension .policy to have a MIME type of text/x-cross-domain-policy in the directory /webservice on my remote web server and created a file in the /webservice directory called crossdomain.policy with the following XML:

<cross-domain-policy>
    <allow-access-from domain="*" />
</cross-domain-policy>

If this all seems confusing there is the summary of what you need to do:

  • Create a master policy file in the root of the web server allowing custom policy files.
  • Create a custom policy file in the directory you want the policy to apply to.
  • Call Security.loadPolicyFile(YOUR CUSTOM POLICY FILE) before calling urlLoader.load()

Why Adobe’s ActionScript Language Reference documentation for the Security.loadPolicyFile() method does not mention that you need to allow custom policy files in the master policy file is beyond me.

Links:
Cross-domain policy file specification
Policy file changes in Flash Player 9 & 10 – Workflows
Policy file changes in Flash Player 9 & 10 – Meta-Policies
A post on actionscript.org I created regarding my issue

Note: The solution should apply to Flash applications as well, not just Flex Applications, as all the classes mentioned above are actually Flash classes and not Flex classes. (I’m making an assumption here as I’ve never used Flash CSx, but I’m pretty certain it should :))

Adding Intellisense comments to Flex functions

Adding comments to your code in Flex that can be picked up by the IDE’s Intellisense is very easy, it’s not as elegant as .NET’s implementation in my opinion but it’s simple and it works (I haven’t had any issues yet :)).

You just need to add a block comment before your function that starts with two stars, i.e. /** */. Inside this block you can enter your comments about the function, if the function has parameters just include @param then the name of parameter and then the comment about it, and for return values you insert @return and the comment about the return value. See the example below:

public final class Strings
{
    /**
    * Checks if two strings are equal 
    * @param value1 The first string
    * @param value2 The second string
    * @param caseSensitive Should a case sensitive comparision be done, default is &amp;lt;b&amp;gt;false&amp;lt;/b&amp;gt;
    * @return Returns true if the strings are equal otherwise returns false 
    */        
    public static function AreEqual(value1:String, value2:String, caseSensitive:Boolean=false):Boolean
    {
        // Function body here
    }
}

Doing this will display the following information when you navigate through the Intellisense list to the function you added the comment to:
FlexIntellisense

Note you can include HTML tags in your intellisense comments, I’m not sure which tags are supported as I haven’t checked, I assume just the basic font formatting tags.

Also this works on fields, property getters/setters, etc.

Post based on Adobe Flash Builder 4 Beta 2 (I assume it is the same in Adobe Flex Builder 3)

Passing the Browser Query String to a Flex 4 Application

Passing parameters into a Flex 4 (Beta 2) application is slightly different to passing parameters into a Flex 3 application. Previously you would pass a string into the flashvars parameter with the key/value pairs, now you pass in an associative array with the key/value pairs.

In the launcher HTML template file you will see the following javascript:

var swfVersionStr = "${version_major}.${version_minor}.${version_revision}";
var xiSwfUrlStr = "${expressInstallSwf}";
var flashvars = {};
var params = {};
params.quality = "high";
params.bgcolor = "${bgcolor}";
params.allowscriptaccess = "sameDomain";
params.allowfullscreen = "true";
var attributes = {};
attributes.id = "${application}";
attributes.name = "${application}";
attributes.align = "middle";
swfobject.embedSWF(
	"${swf}.swf", "flashContent", 
	"${width}", "${height}", 
	swfVersionStr, xiSwfUrlStr, 
	flashvars, params, attributes);
swfobject.createCSS("#flashContent", "display:block;text-align:left;");

As you can see the flashvars and params are now passed into the Flash object as associative arrays, and the method that is called on the Flash object is no longer AC_FL_RunContent().

To get the query string into the flashvars object is very easy, simply iterate through the query string and add each key/value to the flashvars object.

var swfVersionStr = "${version_major}.${version_minor}.${version_revision}";
var xiSwfUrlStr = "${expressInstallSwf}";
var flashvars = {};

var queryString = window.location.search.substring(1);
if (queryString != null &amp;amp;amp;amp;&amp;amp;amp;amp; queryString.length > 0)
{			
	var keyValuePairs = queryString.split("&amp;amp;amp;amp;");
	for (var i = 0; i < keyValuePairs.length; i++) 
	{
		var keyValuePair = keyValuePairs[i].split("=");
		
		if (keyValuePair.length == 2)
		{
			flashvars[keyValuePair[0]] = keyValuePair[1];
		}
	}
} 

var params = {};
params.quality = "high";
params.bgcolor = "${bgcolor}";
params.allowscriptaccess = "sameDomain";
params.allowfullscreen = "true";

var attributes = {};
attributes.id = "${application}";
attributes.name = "${application}";
attributes.align = "middle";

swfobject.embedSWF(
	"${swf}.swf", "flashContent", 
	"${width}", "${height}", 
	swfVersionStr, xiSwfUrlStr, 
	flashvars, params, attributes);
swfobject.createCSS("#flashContent", "display:block;text-align:left;");

Then to access the parameters inside your Flex application you just need to access the parameters property on the application object.

var someVariable:String = this.parameters["MyQueryStringKey"];
// OR
var someOtherVariable:String = FlexGlobals.topLevelApplication.parameters["MyQueryStringKey"];

That’s it, simple 🙂

Post based on Adobe Flash Builder 4 Beta 2

ActionScript 3 and Flex 4

I recently started working on a project using Flex 4, the project is basically a port of an existing application to Flash 10 (using Flex 4); so that we can have a version of the application that works in any browser. So over the next few months I’ll probably be posting more about Flex 4/ActionScript 3 than on .NET, I’ll still try find some time to do .NET posts though.

This post is basically just an introduction to what Flex and ActionScript are, and some random things I’ve learnt about them.

I have to admit when I was first told that I’d be working on a Flex application I wasn’t particularly happy, I’m not a big fan of Flash or scripting languages; but I have to say after working with it for a while I’m pleasantly surprised – it’s no .NET but for a scripting language it’s pretty good.

Flex is basically a library that sits on top of Flash providing developers an easy way to create Flash applications. For developers like myself the idea of having to create a Flash application with Flash CS4 is absolute hell; frames, movies, timelines and all that nonsense. So Adobe created the Flex library and the Flex IDE for developers like me that want to code in the traditional sense 🙂
I think Adobe have done a pretty good job given the constraints they were under building on top of the Flash framework; it’s not perfect by any means and it’s lacks a lot but much better than I was expecting.

Now I must make a clear distinction, ActionScript is Adobe’s implementation of the ECMAScript specification, so any limitations I mention are limitations of ActionScript and the ECMAScript specification; I’m assuming of course that Adobe has implemented the specification fully :). Also, ActionScript is not a Flex thing, it is part of Flash.

Some random things about ActionScript 3.0:

  • Requires Flash Player 9.0 or higher.
  • There are no abstract classes or abstract methods.
  • Does not have a concept similar to .NET generics or C++ templates
  • Classes and class members can be private, protected, internal, or public.
  • Has static class members but not static classes.
  • No enumerated types.
  • Properties are defined using get/set functions.
  • Has interfaces, yay!
  • Has exceptions and exception handling using try…catch…finally blocks.
  • Anonymous functions are allowed.
  • Has compile time type checking (it can be turned off if you really want it off )
  • If you name your function/field the name as a class (case sensitive) you will need to fully qualify the type declaration.

Some random things about Flex:

  • Collections/lists are weakly typed, i.e. Array and ArrayCollection hold the type Object.
  • Has packages; which are a similar idea to .NET namespaces
  • Internal does not have the same meaning as in .NET, internal in Flex means within the current package, not the current project.
  • All file loading is done asynchronously with callbacks.
  • The “event model” is weird (i.e. not true events), to “raise” events your class needs to inherit from EventDispatcher and classes hook into events on your class using the addEventListener method and specifying the string name of the event to hook into.
  • You cannot define a signature for event handlers.

Just a quick disclaimer, I’m still new to Flex/ActionScript so hopefully everything I’ve mentioned here is correct 🙂

If you think I’m wrong about something, please let me know.