The Ron Burgundy Syndrome

I read a good LinkedIn article today: Just Because You Said it, Doesn’t Make it So
By Jeff Weiner

Copy/paste from the article, one of my projects is soooo struggling with this….

“We all need to be wary of avoiding the Ron Burgundy syndrome: On the surface, looking and sounding the part, but without providing the right discipline, focus, and ongoing context, appearing as nothing more than a talking head.”

The Ron Burgundy Syndrome

Custom List In app.config File

I recently had the need to define a custom list in an application. There are many ways to make this happen but I wanted it in the app config file.

After a few searches, I pieced together the following example.

The app.config below has a custom section, AppConfigCollection.CustomDictionary. This section is declared in the configSections and the type attribute has my handler class and assembly name.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
 
  <configSections>
    <section name="AppConfigCollection.CustomDictionary" type="AppConfigCollection.CustomDictionary, AppConfigCollection"/>
  </configSections>
 
  <AppConfigCollection.CustomDictionary>
 
    <NFL>
      <AFC>
        <AFC_WEST>
          <Item code="DEN" team="Denver Broncos" />
          <Item code="MCI" team="Kansas City Chiefs" />
          <Item code="SAN" team="San Diego Chargers" />
          <Item code="OAK" team="Oakland Raiders" />
        </AFC_WEST>
      </AFC>
 
      <NFC>
        <NFC_EAST>
          <Item code="DFW" team="Dallas Cowboys" />
          <Item code="PHL" team="Philadelphia Eagles" />
          <Item code="EWR" team="New York Giants" />
          <Item code="IAD" team="Washington Redskins" />
        </NFC_EAST>
      </NFC>
    </NFL>
 
  </AppConfigCollection.CustomDictionary>
 
</configuration>

The handler class CustomDictionary inherits from IConfigurationSectionHandler. This interface has been deprecated but it’s still available and easy to implement and make it work.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Xml.Linq;
 
namespace AppConfigCollection
{
 
    class Program
    {
        static void Main(string[] args)
        {
            var teamDictionary = (Dictionary<string, string>)ConfigurationManager.GetSection("AppConfigCollection.CustomDictionary");
 
            Console.WriteLine();
            Console.WriteLine("NFL TEAMS");
            foreach (var key in teamDictionary.Keys)
            {
                Console.WriteLine("{0} : {1}", key, teamDictionary[key]);
            }
 
            Console.WriteLine();
            Console.WriteLine("press any key to continue ...");
            Console.ReadLine();
        }
    }
 
    public class CustomDictionary : IConfigurationSectionHandler
    {
        public object Create(object parent, object configContext, System.Xml.XmlNode section)
        {
            var rList = new Dictionary<string, string>();
 
            var doc = XDocument.Parse(section.OuterXml);
            var root = (XElement)doc.FirstNode;
 
            var rootElement = (XElement)root.FirstNode;
            if (rootElement.Name != "NFL")
                throw new ConfigurationErrorsException(
                    "AppConfigCollection.CustomDictionary section only accepts 'NFL' elements.");
 
            try
            {
                foreach (XElement conference in rootElement.Nodes())
                {
                    Console.WriteLine();
                    Console.WriteLine("Conference : {0}", conference.Name);
 
                    foreach (XElement division in conference.Nodes())
                    {
                        Console.WriteLine("  Division : {0}", division.Name);
 
                        var teamList = from div in division.Elements("Item") select div;
                        foreach (var item in teamList)
                        {
                            var code = item.Attribute("code").Value;
                            var team = item.Attribute("team").Value;
 
                            Console.WriteLine("    Team ({0}) : {1}", code, team);
                            rList.Add(code, team);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                throw new ConfigurationErrorsException(
                    "Error reading element.", ex);
            }
 
            return rList;
        }
    }
 
}

This is the output.
AppConfigCollection

Feel free to download the application solution – experiment and adapt it for your needs.

HTTPS WCF web service web config

Here’s the web config for a WCF web service. I struggled getting it to work under HTTPS. But when all done and working it’s not terrible – I’ll try to highlight the relevant names because that was my primary struggle point. I won’t go into explaining everything, there are tons of posts out there can (and do) explain much better than I can or want to here.

WebConfig

I pieced together several different examples in an attempt to get this working and at first my highlighted names didn’t match – and no luck working. So here are the highlighted sections of the serviceModel element with the names matching up.

See ServiceBehaviorA, wsHttpBinding, and TransportSecurity. These are referenced in the endpoint and must also be referenced in the behaviors and bindings elements.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
  <system.serviceModel>
 
    <services>
      <service name="S2C.API.Service" 
 
               <!-- SEE BELOW in serviceBehaviors -->
               behaviorConfiguration="ServiceBehaviorA">
 
        <endpoint address="" 
 
                  <!-- SEE BELOW in bindings -->
                  binding="wsHttpBinding"
 
                  <!-- SEE BELOW the binding name -->
                  bindingConfiguration="TransportSecurity"
 
                  contract="S2C.API.IService" />
 
        <endpoint address="mex" 
                  binding="mexHttpBinding" 
                  contract="IMetadataExchange" />
      </service>
    </services>
 
    <behaviors>
      <serviceBehaviors>
        <behavior name="ServiceBehaviorA">
 
          <!-- To avoid disclosing metadata information, 
               set the value below to false and remove 
               the metadata endpoint above before deployment -->
          <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
 
          <!-- To receive exception details in faults for debugging purposes, 
               set the value below to true. Set to false before deployment 
               to avoid disclosing exception information -->
          <serviceDebug includeExceptionDetailInFaults="true"/>
 
        </behavior>
      </serviceBehaviors>
    </behaviors>
 
    <bindings>
      <wsHttpBinding>
        <binding name="TransportSecurity">
 
          <security mode="Transport">
            <transport clientCredentialType="None"/>
          </security>
 
        </binding>
      </wsHttpBinding>
    </bindings>
 
    <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
 
  </system.serviceModel>

Dump .NET References

An application that I work on has many (in excess of 50) referenced custom .NET assemblies. Most of the custom assemblies follow the same version number scheme – but not all of them. And at either the beginning or end of a release cycle, the version numbers change and it can be difficult to track and ensure you have the proper assemblies referenced.

Red Gate’s .NET Reflector is a nice tool to examine an assembly but I need a way to plow through my bin folder and log all of my custom assemblies referenced assemblies, including the version numbers.

The code below does that. (Full disclosure, this code is a mixture of a couple of examples I found on the internet made to work for my situation.)

All of my custom assemblies have a distinct naming convention so I call the CollectAndLogReferences method with this regular expression “^(AAA|AAB|AAC)” to filter only my custom dlls and executables. With the filtering like this, I don’t log all of the system dlls and others that I don’t care about.

I paste the output (which is a lot of text) into my text editor. From there, I can easily search, sort, etc. as needed.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
...
CollectAndLogReferences("^(AAA|AAB|AAC)");
 
 
public void CollectAndLogReferences(string sReferenceExpression)
{
	var sRefExp = "^(.)";
	if (sReferenceExpression.Length > 0) 
		sRefExp = sReferenceExpression;
 
	int indent = 0;
	var loggedAssembly = new List<string>();
	var referencedAssembly = new List<string>();
 
	var p = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
	var files = Directory.GetFiles(p, "*.*").Where(f => f.EndsWith(".exe") || f.EndsWith(".dll"));
	foreach (string file in files)
	{
		try
		{
			var assembly = Assembly.LoadFile(file);
			if (!Regex.IsMatch(assembly.FullName, sRefExp))
				continue;
 
			if (!referencedAssembly.Contains(assembly.FullName))
				referencedAssembly.Add(assembly.FullName);
		}
		catch (Exception e) { }
	}
 
	while (referencedAssembly.Count > 0)
	{
		LogAssemblies(indent, sRefExp, loggedAssembly, referencedAssembly);
	}
}
 
 
public void LogAssemblies(int indent, string sRefExp, List<string> logged, List<string> referenced)
{
	Display(indent, "");
	var referencedAssembly2 = new List<string>();
	foreach (var refd in referenced)
	{
		if (logged.Contains(refd)) continue;
		try
		{
			Assembly r = Assembly.Load(refd);
			Display(indent, "Assembly: {0}", r);
			Display(indent, "Referenced assemblies:");
			foreach (AssemblyName an2 in r.GetReferencedAssemblies())
			{
				if (Regex.IsMatch(an2.Name, sRefExp))
				{
					Display(indent + 1, "Name={0}, Version={1}, Culture={2}, PublicKeyToken={3}", 
						an2.Name, an2.Version, an2.CultureInfo.Name, (BitConverter.ToString(an2.GetPublicKeyToken())));
					if (!referencedAssembly2.Contains(an2.FullName))
						referencedAssembly2.Add(an2.FullName);
				}
			}
			logged.Add(r.FullName);
			Display(indent, "");
		}
		catch (Exception e)
		{
			Display(indent, "EXCEPTION DUMP BEGIN * * * *");
			Display(indent, refd);
			Display(indent, e.ToString());
			Display(indent, "EXCEPTION DUMP END * * * * *");
		}
	}
 
	referenced.Clear();
	referenced.AddRange(referencedAssembly2);
}
 
 
public void Display(int indent, string format, params object[] param)
{
	var str = string.Format(format, param);
	//Output.Text += new string(' ', indent * 2);
	//Output.Text += str + Environment.NewLine;
	Console.Write(new string(' ', indent * 2));
	Console.WriteLine(str);
}

Solution for my bad dates

Following up my previous post “I have bad dates“, here’s my solution. I may have to tweak this some at the end of the year but this seems to be working for now.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//
public static DateTime wsGetDate(string badSabreDate, DateTime srcDT)
{
    // force the bad sabre date into a leap year
    var leapYear = "2000-" + badSabreDate;
 
    var year = srcDT.Year;
    DateTime dt = DateTime.Now.AddYears(-1);
    if (DateTime.TryParse(leapYear, out dt))
    {
	if (dt.Month < srcDT.Month)
	{
	    // parsed month is less than srcDT, increment my year
	    year++;
	}
 
	return new DateTime(year, dt.Month, dt.Day, dt.Hour, dt.Minute, dt.Second);
    }
 
    var msg2 = string.Format("Can't parse {0} into a valid DateTime, {1}", badSabreDate, leapYear);
    throw new ApplicationException(msg2);
}
//

And here’s a piece of the car segment parsing code that calls the new method:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
//
if (_Resp.TravelItinerary.ItineraryInfo.ReservationItems[i].Vehicle != null)
{
    #region CAR
    var car = _Resp.TravelItinerary.ItineraryInfo.ReservationItems[i].Vehicle;
    Log.Debug("Car --------------------------------------------------");
    string confID = "";
    if (car.ConfirmationNumber != null) confID = SabreWS.wsString(car.ConfirmationNumber);
 
    int RPHv = SabreWS.wsInt(car.SegmentNumber);
    string statusv = SabreWS.wsString(car.Status);
    string ID = "";
    if (car.POS != null) ID = SabreWS.wsString(car.POS.Source.RequestorID);
 
    Log.Debug(RPHv + statusv.PadLeft(4) + " - " + " requestorID: " + ID);
 
    string PU = SabreWS.wsString(car.VehRentalCore.LocationDetails.LocationCode);
    tmpForeignSts = AirportLookupCache.GetForeignStatus(PU);
    ForeignSts = tmpForeignSts > ForeignSts ? tmpForeignSts : ForeignSts;
 
    DateTime PUDT = wsGetDate(car.VehRentalCore.PickUpDateTime, DateTime.Now);
    Log.Debug("Pickup1: " + PU.PadRight(5) + PUDT.ToString());
 
    string RT = "";
    if (car.VehRentalCore.DropOffLocationDetails != null) RT = SabreWS.wsString(car.VehRentalCore.DropOffLocationDetails.LocationCode);
    if (RT.Length == 0) RT = PU;
    tmpForeignSts = AirportLookupCache.GetForeignStatus(RT);
    ForeignSts = tmpForeignSts > ForeignSts ? tmpForeignSts : ForeignSts;
 
    DateTime RTDT = PUDT;
    try
    {
	RTDT = wsGetDate(car.VehRentalCore.ReturnDateTime, PUDT);
    }
    catch (Exception a)
    {
	a.Message.ToString();
	Log.Error(car.VehRentalCore.ReturnDateTime + " --> error parsing this as the Return DateTime, forcing to PUDT");
    }
...
//

I have bad dates

Some back story … I use Sabre web services to read and extract travel data into a database. The data is used for a suite of travel related products and applications. If you’ve worked on travel applications, you know that it’s some wild west programming – data consistency is awful.

Web services was supposed to fix everything because now it’s structured data, no more screen scraping! Well, it is better than it was in the past but there are still problems.

Sabre web services has an odd bug that only strikes on the last day of the month AND your car/hotel segment starts on that day. See the PickUpDateTime below – it should be 2013 not 2014. (Notice that they have the ReturnDateTime correct.)

1
2
3
4
5
6
7
8
<OTA_TravelItineraryRS Version="2003A.TsabreXML1.15.1">
. . .
    <VehRentalCore PickUpDateTime="2014-07-31T16:30:00" PickUpDay="3" ReturnDateTime="2013-08-02T16:00:00">
      <PickUpLocation LocationCode="ATL" CodeContext="IATA" />
      <ReturnLocation LocationCode="JAX" CodeContext="IATA" />
    </VehRentalCore>
. . .
</OTA_TravelItineraryRS>

Since I’m running an older version of the TravelItinerary web service, thought I’d try the latest and greatest version available to see if the problem is fixed. As you can see below, Sabre’s solution is to drop the year. Nice. Are you kidding me? We went from the wrong date to an invalid ISO format across the board?

1
2
3
4
5
6
7
8
<TravelItineraryReadRS Version="2.2.0">
. . .
    <VehRentalCore PickUpDateTime="07-31T16:30" PickUpDay="3" ReturnDateTime="08-02T16:00">
      <DropOffLocationDetails LocationCode="JAX" />
      <LocationDetails LocationCode="ATL" />
    </VehRentalCore>
. . .
</TravelItineraryReadRS>

…I’d love to hear the reasoning behind that solution hack. Why is there such a lack of quality these days? I have some stories I want to post about this later…

Now I have to write new logic to decode this crap which will replace the old logic I had to fix the original crap.

College Tour Road Trip

My son is going into his senior year of high school. He is interested in visiting potential colleges – and very interested in those that have men’s gymnastic teams.

We started our trip driving to Englewood CO to visit family and friends. I’m from Englewood – went 2 years to Colorado School of Mines in Golden, transferred to and graduated from the University of Colorado in Boulder.


View Larger Map

First visit was Colorado School of Mines in Golden. We only drove around campus, nothing official as it was on a Sunday. Pretty campus, there are several new buildings since my time there … but not much interest by my son, it’s too small and no gymnastics.

Next, we drove up to Boulder from Golden. Nothing official (still Sunday), so we walked around the CU Boulder campus and ate lunch up on the hill. I’m a bit partial since I graduated from CU but this campus is awesome, anything I write wouldn’t do it justice – you have to experience it yourself. My son loved it. The only drawback, no men’s gymnastics. We later learned they might have a college club team so CU is still on the list (but the out of state price tag for Mom and Dad would be painful).

CU

As we were leaving CO, we drove past the DU (Denver University) campus since it’s close by where I grew up. Not any interest in this school but we can say we saw it.

Next stop was Lincoln NE, 8 hour drive from Denver. The University of Nebraska at Lincoln UNL. Interesting setting – right next to downtown, seems like a student could have everything desired within walking distance. The official tour started with a welcome/marketing presentation at the visitor center. Next was a walking tour of campus and a visit of one of the dorms, followed by a meal from one of the dining halls then another sales pitch at the visitor center. Lastly, we met with a physics professor (physics is my son’s current interest). This was awesome – the prof was personable, gave us a guided tour of the labs and class rooms and spoke to the possibilities available to an undergraduate. (This was a great one on one, every university should do this.)

Before leaving town, we drove over and visited the gymnastic center. We got there just as the team was warming up for workout. Met John Robinson, an assistant coach – another great one on one. He toured the facilities for us and answered all questions we threw at him. He is a great representative of the university, my son really likes UNL.

Nice hat... um no.

Nice hat… um no.

UNL2

6 hour drive from Lincoln NE to Minneapolis MN. The University of Minnesota U of M. The visit consisted of a sales/marketing pitch followed by a campus and dorm tour. The campus is really BIG, the buildings are all really impressive and grandiose. The dorm room was a real turn off for my son. It didn’t help that it was hot outside and there was no A/C in the room … and the room was really small and outdated. The overall vibe we got was that UM is a massive institution and not very personable, you are a small fish in a very big ocean. We did not visit the gymnastics facilities, the coach is visiting my son’s club gym this summer to recruit some of his teammates.

About a 5 hour drive to Iowa City IA. The University of Iowa UI. Bigger than Nebraska, smaller than Minnesota, a beautiful campus with the Iowa River splitting campus in half. Same basic visit as U of M, started with a sales pitch followed by a walking tour of campus and a dorm room. The campus has a mix of new and old buildings surrounded by the Iowa City community. Great vibe from the tour and campus, a lot different that the Minnesota experience. We visited the gym but nobody was there.

UI

Long drive back home, rolled in at 230AM – way past my bed time. Some great tours, and great data points for my son to consider for his future.