public override DataCollection Serialize(object obj, ITypeSerializer handler)
        {
            //serialise as normal
            DataCollection data = base.Serialize(obj, handler);

            AspNetAppProject proj = obj as AspNetAppProject;

            if (proj == null)
            {
                return(data);
            }

            //for the old format we need to make sure each Content file that's a web type and is NOT set
            //to copy actually gets changed to the FileCopy build target
            DataItem files = data ["Contents"] as DataItem;

            if (files == null || !files.HasItemData)
            {
                return(data);
            }

            foreach (object f in files.ItemData)
            {
                DataItem file = f as DataItem;
                if (file == null || !file.HasItemData)                // || file.Name != "File")
                {
                    continue;
                }

                DataValue ctod = file ["copyToOutputDirectory"] as DataValue;
                if (ctod != null && ctod.Value == "Never")
                {
                    DataValue action = file ["buildaction"] as DataValue;
                    DataValue name   = file ["name"] as DataValue;
                    if (action != null && name != null && action.Value == "Content")
                    {
                        WebSubtype type = AspNetAppProject.DetermineWebSubtype(name.Value);
                        if (type != WebSubtype.None && type != WebSubtype.Code)
                        {
                            file.Extract("copyToOutputDirectory");
                            int index = file.ItemData.IndexOf(action);
                            file.ItemData.Remove(action);
                            file.ItemData.Insert(index, new DataValue("buildaction", "FileCopy"));
                        }
                    }
                }
            }

            return(data);
        }
        static void ApplyOverlay(DataItem baseline, DataItem diffNode)
        {
            DataValue rem = diffNode.Extract("__removed") as DataValue;

            if (rem != null)
            {
                // Remove items marked as removed in the diff
                List <DataNode> toRemove = new List <DataNode> ();
                foreach (string removed in rem.Value.Split(' '))
                {
                    if (removed [0] == '@')
                    {
                        string   aname = removed.Substring(1);
                        DataNode n     = baseline.ItemData [aname];
                        if (n != null)
                        {
                            toRemove.Add(n);
                        }
                    }
                    else
                    {
                        int n = int.Parse(removed);
                        if (n < baseline.ItemData.Count)
                        {
                            toRemove.Add(baseline.ItemData [n]);
                        }
                    }
                }
                foreach (var nod in toRemove)
                {
                    baseline.ItemData.Remove(nod);
                }
            }

            List <DataNode>    toAdd   = new List <DataNode> ();
            HashSet <DataNode> applied = new HashSet <DataNode> ();

            foreach (DataNode node in diffNode.ItemData)
            {
                DataNode baselineNode = null;
                if (node is DataItem)
                {
                    DataItem  item  = (DataItem)node;
                    DataValue added = item.ItemData.Extract("__added") as DataValue;
                    if (added != null)
                    {
                        DataNode  newNode = node;
                        DataValue val     = item.ItemData.Extract("__value") as DataValue;
                        if (val != null)
                        {
                            newNode = new DataValue(node.Name, val.Value);
                        }
                        int pos = int.Parse(added.Value);
                        if (pos > baseline.ItemData.Count)
                        {
                            pos = baseline.ItemData.Count;
                        }
                        baseline.ItemData.Insert(pos, newNode);
                        continue;
                    }
                    DataValue index = item.ItemData.Extract("__index") as DataValue;
                    if (index != null)
                    {
                        int n = int.Parse(index.Value);
                        baselineNode = baseline.ItemData [n];
                        DataValue val = item.ItemData.Extract("__value") as DataValue;
                        if (val != null)
                        {
                            baseline.ItemData [n] = new DataValue(node.Name, val.Value);
                            continue;
                        }
                    }
                }

                if (baselineNode == null)
                {
                    baselineNode = baseline[node.Name];
                }

                if (baselineNode != null && !applied.Add(baselineNode))
                {
                    baselineNode = null;
                }

                if (baselineNode == null)
                {
                    // New node
                    toAdd.Add(node);
                    continue;
                }

                if (baselineNode is DataValue)
                {
                    int i = baseline.ItemData.IndexOf(baselineNode);
                    baseline.ItemData [i] = node;
                }
                else
                {
                    ApplyOverlay((DataItem)baselineNode, (DataItem)node);
                }
            }
        }