No more waiting for Azure tokens

While looking into Azure today, I couldn’t resist telling you that since today, you don’t need to wait for the confirmation to get your Azure development token! Great news.

Read more about it here.

Silverlight and StarGate

Like many geeks, I am a fan of many SF-series, such like StarTrek, StarGate, FarScape, etc… MGM, the creators of StarGate have built a fan site for StarGate using Flash. But recently they’ve added a whole new section (check the Explore button!!!) to the site using Silverlight and PhotoSyntch to allow you to walk the corridors of the ship in the latest installment of the SG series. To be honest, I’m still waiting for this installment to be aired here in Belgium, but it looks great!

If you’re also interested in the making of, here is a link to the case study by Microsoft. And hey, it also includes a link to the Silverlight Advertising Creation Kit.

Setting the default namespace just once for your (data) contracts in WCF

While browsing around the WCF REST starter toolkit I found this attribute:

[assembly: ContractNamespace()]

So what does it do? Well, normally if you don’t specify an explicit namespace in your datacontract, the DataContractSerializer uses its own default, namely generated from the CLR namespace. For example this datacontract:

namespace U2U.DataContracts {   [DataContract]   public class Person   {     [DataMember]     public string Name { get; set; }      [DataMember]     public Job Occupation { get; set; }   }    [DataContract]   public class Job   {     [DataMember]     public string Description { get; set; }   } }

will be serialized like this:

<Person xmlns="http://schemas.datacontract.org/2004/07/U2U.DataContracts"          xmlns:i="http://www.w3.org/2001/XMLSchema-instance">   <Name>Jefke</Name>   <Occupation>     <Description>Developer</Description>   </Occupation> </Person>

But if you use the ContractNamespace attribute:

[assembly: ContractNamespace("http://www.u2u.be/samples/wcf/2009", ClrNamespace = "U2U.DataContracts")]  namespace U2U.DataContracts {   [DataContract]   public class Person   { … }    [DataContract]   public class Job   { … } }

The output now looks like this:

<Person xmlns="http://www.u2u.be/samples/wcf/2009"          xmlns:i="http://www.w3.org/2001/XMLSchema-instance">   <Name>Jefke</Name>   <Occupation>     <Description>Developer</Description>   </Occupation> </Person>

The attribute requires two things, the first is the default namespace to use, the second is the CLR namespace of your datacontract. If you have multiple CLR namespaces for your  data contracts, you will need to repeat this attribute for each namespace. For example:

[assembly: ContractNamespace("http://www.u2u.be/samples/wcf/2009", ClrNamespace = "U2U.DataContracts")] [assembly: ContractNamespace("http://www.u2u.be/samples/wcf/2009", ClrNamespace = "U2U.Jobs")]  namespace U2U.DataContracts {   [DataContract]   public class Person   {     [DataMember]     public string Name { get; set; }      [DataMember]     public Job Occupation { get; set; }   } }  namespace U2U.Jobs {   [DataContract]   public class Job   {     [DataMember]     public string Description { get; set; }   } }
will give you the same output as the previous example.

Serializing Cyclic Graphs of objects with WCF

Abstract

In this blog post I will be discussing how the serialize cyclic graphs of objects using WCF, including data contracts and POCO’s ( Plain Old CLR Objects).

Introduction

WCF allows you to serialize any number of objects over the network or to disk using the DataContractSerializer class. However, some issues can arise when you have cycles in your object graph, and especially when you want some shared objects to stay shared!

Serializing cyclic objects

Let’s look at this with a couple of examples. First I want some datacontracts with possible cycles:

  [DataContract(Namespace=Namespaces.U2U, Name="address", IsReference=false)]   public class Address   {     [DataMember(Name="street", Order=1)]     public string Street { get; set; }     [DataMember(Name="city", Order=2)]     public string City { get; set; }   }    [DataContract(Namespace = Namespaces.U2U, Name = "person", IsReference = false)]   public class Person   {     [DataMember(Name="name", Order=1)]     public string Name { get; set; }     [DataMember(Name="age", Order=2)]     public int Age { get; set; }     [DataMember(Name="partner",Order=3)]     public Person Partner { get; set; }     [DataMember(Name = "address", Order = 4)]     public Address Address { get; set; }   } 

 

I’ll create a person object with a reference to another person. Since they are partners, they will point to each other.

image

DataContractSerializer ser = new DataContractSerializer(typeof(Person)); string path = Path.Combine( Environment.CurrentDirectory, "cartoon.xml" ); using (FileStream ms = File.Open(path, FileMode.Create, FileAccess.Write)) {   Address home = new Address { Street = "ToonLane", City = "ToonTown" };   Person tom = new Person { Name = "Tom", Age = 4, Address = home };   Person jerry = new Person { Name = "Jerry", Age = 2, Address = home };   tom.Partner = jerry;   jerry.Partner = tom;   ser.WriteObject(ms, tom); }

So what happens when you try this? You’ll get an exception:

image

[NOTE: By the way, this is much better then in .NET 1.0 with the XmlSerializer, it would serialize the first object, then follow the link to the second, then back the to first, then back to the second, until your disk ran out of space :) Now XmlSerializer will also throw an exception if you try to serialize cycles.]

Using IsReference

To make the exception go away, you add IsReference=true to the Person’s DataContract:

The result now looks like this:

<person z:Id="i1" 
xmlns="urn://www.u2u.be/samples/wcf/2009"
xmlns:i=http://www.w3.org/2001/XMLSchema-instance
xmlns:z="http://schemas.microsoft.com/2003/10/Serialization/"> <name>Tom</name> <age>4</age> <partner z:Id="i2"> <name>Jerry</name> <age>2</age> <partner z:Ref="i1"/> <address> <street>ToonLane</street> <city>ToonTown</city> </address> </partner> <address> <street>ToonLane</street> <city>ToonTown</city> </address> </person>

Look how Jerry refers back to Tom using the z:Ref! Now you can easily send objects with cycles. But wait! Both point to the same address, but now Tom and Jerry both have an address, although identical.

image

Again we can change this by changing the IsReference to true in the Address DataContract. Now the result looks like this:

<person z:Id="i1" xmlns="urn://www.u2u.be/samples/wcf/2009" xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns:z="http://schemas.microsoft.com/2003/10/Serialization/">   <name>Tom</name>   <age>4</age>   <partner z:Id="i2">     <name>Jerry</name>     <age>2</age>     <partner z:Ref="i1"/>     <address z:Id="i3">       <street>ToonLane</street>       <city>ToonTown</city>     </address>   </partner>   <address z:Ref="i3"/> </person>

Please note that now both Tom and Jerry use the same address instance, not clones.

Serializing cyclic POCO’s with WCF

“And what about POCO’s? (Plain Old Clr Objects) I hear you say. Well in that case you cannot attach the DataContract attribute of course, so you‘ll need to use another variant of the DataContractSerializer constructor:

new DataContractSerializer(typeof(PocoPerson), null, int.MaxValue, false                           , /* preserveObjectReferences */ true, null, null); 

So, using this constructor the previous example looks like this:

  public class PocoPerson   {     public string Name { get; set; }     public int Age { get; set; }     public PocoPerson Partner { get; set; }     public PocoAddress Address { get; set; }   }    public class PocoAddress   {     public string Street { get; set; }     public string City { get; set; }   }
  DataContractSerializer ser =      new DataContractSerializer(typeof(PocoPerson), null, int.MaxValue, false                               , /* preserveObjectReferences */ true, null, null);   string path = Path.Combine(Environment.CurrentDirectory, "cartoon2.xml");   using (FileStream ms = File.Open(path, FileMode.Create, FileAccess.Write))   {     PocoAddress home = new PocoAddress { Street = "ToonLane", City = "ToonTown" };     PocoPerson tom = new PocoPerson { Name = "Tom", Age = 4, Address = home };     PocoPerson jerry = new PocoPerson { Name = "Jerry", Age = 2, Address = home };     tom.Partner = jerry;     jerry.Partner = tom;     ser.WriteObject(ms, tom);
}

Running this will result in following Xml:

<PocoPerson z:Id="1"              xmlns="http://schemas.datacontract.org/2004/07/ReferenceSerialization"              xmlns:i="http://www.w3.org/2001/XMLSchema-instance"              xmlns:z="http://schemas.microsoft.com/2003/10/Serialization/">   <Address z:Id="2">     <City z:Id="3">ToonTown</City>     <Street z:Id="4">ToonLane</Street>   </Address>   <Age>4</Age>   <Name z:Id="5">Tom</Name>   <Partner z:Id="6">     <Address z:Ref="2" i:nil="true"/>     <Age>2</Age>     <Name z:Id="7">Jerry</Name>     <Partner z:Ref="1" i:nil="true"/>   </Partner> </PocoPerson>

Using a custom behavior

Of course it is not that easy to use this contructor inside a real service, because you’re not in charge of creating the serializer. But hey, WCF is very extensible right? So to plug the hole, you need to build your own Behavior, specifically a DataContractSerializerOperationBehavior.

public class CyclicSerializationBehavior : DataContractSerializerOperationBehavior {   public CyclicSerializationBehavior(OperationDescription od)     : base(od)   { }    private const bool preserveObjectReferences = true;    public override XmlObjectSerializer CreateSerializer(
Type type, XmlDictionaryString name, XmlDictionaryString ns, IList<Type> knownTypes) { return new DataContractSerializer(type, name, ns, knownTypes,
this.MaxItemsInObjectGraph, this.IgnoreExtensionDataObject,
preserveObjectReferences, this.DataContractSurrogate); } public override XmlObjectSerializer CreateSerializer(
Type type, string name, string ns, IList<Type> knownTypes) { return new DataContractSerializer(type, name, ns, knownTypes,
this.MaxItemsInObjectGraph, this.IgnoreExtensionDataObject,
preserveObjectReferences, this.DataContractSurrogate); } }

To get this behavior installed you need to write some code to add it the the operation’s behavior, or even better is to use an IContractBehavior:

  [AttributeUsage(AttributeTargets.All)]   public class CyclicSerializationAttribute : Attribute, IContractBehavior   {     public void AddBindingParameters(ContractDescription contractDescription, 
ServiceEndpoint endpoint, BindingParameterCollection bindingParameters) { } public void ApplyClientBehavior(ContractDescription contractDescription,
ServiceEndpoint endpoint, ClientRuntime clientRuntime) { ReplaceDataContractSerializerOperationBehavior(contractDescription); } public void ApplyDispatchBehavior(ContractDescription contractDescription,
ServiceEndpoint endpoint, DispatchRuntime dispatchRuntime) { ReplaceDataContractSerializerOperationBehavior(contractDescription); } private void ReplaceDataContractSerializerOperationBehavior(ContractDescription contractDescription) { foreach (OperationDescription operation in contractDescription.Operations) { DataContractSerializerOperationBehavior beh =
operation.Behaviors.Find<DataContractSerializerOperationBehavior>(); if (beh != null) { operation.Behaviors.Remove(beh); operation.Behaviors.Add(new CyclicSerializationBehavior(operation)); } } } public void Validate(ContractDescription contractDescription, ServiceEndpoint endpoint) { } }

I made this class into an attribute so you can apply it to your service contract or service class, and when WCF loads it it replaces the default DataContractSerialerOperationBehavior. At first I simply added it to the collection of behaviors, but then I got all kinds of strange things :)

So, to use this now you apply the attribute to the service contract:

  [ServiceContract]   [CyclicSerializationAttribute]   public interface ICyclicSerializationService   {     [OperationContract]     PocoPerson GetPocoPerson();   }

Don’t forget, you should add this to both the server en client side.

Changing the generated code namespace when adding a Service Reference

In my previous post I described how to change the default xml namespace used for serialization. But how can you change the generated namespace in your code? This is actually quite simple in Visual Studio. After adding the Service Reference, click on the Show All Files button in Solution explorer and look for the .svcmap file. In it you’ll find a <NamespaceMapping> section. Simply add the xml namespace and required Clr namespace to it:

    <NamespaceMappings>       <NamespaceMapping TargetNamespace="http://www.u2u.be/samples/wcf/2009"                         ClrNamespace="U2U.Samples"/>     </NamespaceMappings>

Customizing the Visual Studio 2010 Start screen

Visual Studio 2010 is completely written in WPF (well, probably except some dialogs …) so this means you can tweak VS in all kinds of ways using the simple power of XAML. One of the simplest things to customize is the start screen. Just for fun I’ve tried this and here is the result (WARNING: may contain advertising :))

image

To try this yourself, first create a folder called StartPages in your Documents/Visual Studio 10 folder.

Then copy the files you find in the Microsoft Visual Studio 10.0\Common7\IDE\StartPages folder.

Open the project with VS10 and you can start to edit away!

The root of the start screen is a grid with three rows, the first row contains the visual studio logo, and the third one contains an RSS feed control. All the action is in the middle row. Warning: this middle row contains a custom VS control, which will be replaced later so prepare to customize again in the next beta!

The grid uses a border control to paint the background. What I’ve done is to change the background to be more U2U orangy:

<Border Grid.RowSpan="3" Grid.ColumnSpan="3" Height="800" VerticalAlignment="Top" 
Style="{DynamicResource {x:Static vs:StartPageResourceKeys.OuterBorderStyleKey}}"> <Border.Background> <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0"> <GradientStop Color="#FFC3874B" Offset="0" /> <GradientStop Color="#FFDD9914" Offset="1" /> </LinearGradientBrush> </Border.Background> </Border>

I’ve also added an extra link button to the U2U website. To do this add another TrayGroupItem inside the TrayGroup:

<vs:TrayGroupItem Content="About U2U"                   ImageSource="C:\Users\Peter\Documents\Visual Studio 10\StartPages\U2U.jpg"                   Command="{x:Static vs:VSCommands.Browse}"                   CommandParameter="{StaticResource Links.AboutU2U}"                   x:Uid="AboutU2U_Item" />

And to represent the uri I’ve added another resource to the root:

<Grid.Resources>   <!-- Welcome tab links -->   <sys:String x:Key="Links.WhatsNew">http://go.microsoft.com/fwlink/?LinkId=123638</sys:String>   <sys:String x:Key="Links.Walkthroughs">http://go.microsoft.com/fwlink/?LinkId=147108</sys:String>   <sys:String x:Key="Links.Feedback">http://go.microsoft.com/fwlink/?LinkId=147445</sys:String>   <sys:String x:Key="Links.Customize">http://go.microsoft.com/fwlink/?LinkId=123641</sys:String>   <sys:String x:Key="Links.AboutU2U">http://www.u2u.be</sys:String>    <!-- Visual Studio tab links –>
</Grid.Resources>

And then I changed the welcome message a little:

<vs:TrayGroupItem Content="Welcome"                   ImageSource="pack://application:,,,/Microsoft.VisualStudio.Shell.UI;component/Images/StartPage/01_whatsnew.png"                   x:Uid="Welcome_Item">   <vs:TrayGroupItem.InnerContent>     <StackPanel>       <TextBlock FontSize="18pt" Foreground="#E8E8E8" Margin="15" x:Uid="Welcome_Text">Welcome to U2U</TextBlock>       <TextBlock Foreground="#E8E8E8" Margin="15" TextWrapping="Wrap" x:Uid="Welcome_Paragraph" >          Welcome to your training!       </TextBlock>       <Button Content="More Information"               HorizontalAlignment="Left"               Margin="15"               Style="{DynamicResource {x:Static vs:StartPageResourceKeys.WelcomeButtonStyleKey}}"               Command="{x:Static vs:VSCommands.Browse}"               CommandParameter="{StaticResource Links.WhatsNew}"               x:Uid="Welcome_Button"         />     </StackPanel>   </vs:TrayGroupItem.InnerContent> </vs:TrayGroupItem>