Archive for June, 2010

Connecting to TFS 2010 with Visual Studio 2008

I got error TF31002 when trying to connect to TFS 2010 with Visual Studio 2008:

TF31002 The Team Foundation Server name, port number or protocol is incorrect The Team Foundation server is offline Password is expired or incorrect.

The basic problem is that in Team Explorer, before Visual Studio Service Pack 1, you can’t enter a valid URL in the Add Team Foundation Server dialog, only a server name or IP address. Unfortunately TFS 2010 changed the URL of the server to this format: http://<servername>:<port>/tfs/, adding a virtual directory that TFS 2008 does not have. Pre sp1 this syntax is not allowed in the dialog box. Just putting in the server name produces the above error, which, in the irritating way that error messages work, is completely correct since the services can’t be found because they now reside in a virtual directory.

To get Visual Studio 2008 to connect to Team Foundation Server 2010, there are definitely some steps you need to follow. I found a bunch of mostly correct information, but nothing exactly right (beta and RC were widely available) so I figured I’d post it here.

To begin with, you need to install the following, in this order to Visual Studio 2008:

  1. Team Explorer for TFS
  2. Visual Studio 2008 sp1
  3. Visual Studio Team System 2008 Service Pack 1 Forward Compatibility Update for Team Foundation Server 2010

If you already installed Service Pack 1 and need install Team Explorer, you will need to re-apply the service pack.

Enter the URL like this:

http://<servername>:<port>/tfs/

Add a TFS Server

Now you should be good to connect to the server.

Using Linq Against a Custom ConfigurationElementCollection

By default, ConfigurationElementCollections don’t implement IEnumerable<T>, so if you are using custom configuration sections you can’t query them with linq. I found a casting solution, but I figured I could do better because the custom configuration classes are under my control, so it would be cleaner to implement the required functionality instead of using the clunky cast in the code consuming the collection. I implemented IEnumerable<T> against the ConfigurationElementCollection. It’s pretty straightforward, just calling the base class BaseGet function and casting the result properly using the As keyword. Now I can execute linq queries against my collection.

using System;

using System.Collections.Generic;

using System.Configuration;

 

namespace Config.Demo

{

    public class MapConfig : ConfigurationSection

    {

        [ConfigurationProperty(“fields”)]

        public MapConfigCollection Fields { get { return this[“fields”] as MapConfigCollection; } }

    }

    public class MapConfigElement : ConfigurationElement

    {

        [ConfigurationProperty(“server”)]

        public string Server { get { return this[“server”] as string; } }

 

        [ConfigurationProperty(“name”)]

        public string Name { get { return this[“name”] as string; } }

 

        [ConfigurationProperty(“id”)]

        public int Id { get { return (int)this[“id”]; } }

    }

    public class MapConfigCollection : ConfigurationElementCollection, IEnumerable<MapConfigElement>

    {

        public MapConfigElement this[int index]

        {

            get { return base.BaseGet(index) as MapConfigElement; }

            set

            {

                if (base.BaseGet(index) != null)

                {

                    base.BaseRemoveAt(index);

                    this.BaseAdd(index, value);

                }

            }

        }

 

        protected override ConfigurationElement CreateNewElement()

        {

            return new MapConfigElement();

        }

 

        protected override object GetElementKey(ConfigurationElement element)

        {

            return ((MapConfigElement)element).Id;

        }

 

        #region IEnumerable<MapConfigElement> Members

 

        public new IEnumerator<MapConfigElement> GetEnumerator()

        {

            int count = base.Count;

            for (int i = 0; i < count; i++)

            {

                yield return base.BaseGet(i) as MapConfigElement;

            }

        }

 

        #endregion

    }

}

Posted on:
Posted in .Net 3.5, Linq | Comments Off on Using Linq Against a Custom ConfigurationElementCollection