Tuesday, 17 January 2012

Big thanks to Ganesan and the rest of DC DNUG for having me present tonight.  They asked great questions and even provided a speaker gift!  

And Metro delivered me on time and got me safely home on a surprisingly pleasant January night.

Tuesday, 17 January 2012 22:02:33 (Eastern Standard Time, UTC-05:00)   #     Comments [0]  | 
Wednesday, 15 June 2011

I have been doing more with LINQ and extension methods of late and thought I should delve a (little) more deeply into the somewhat mysterious => operator.  So I did a little reading, a little coding and little PowerPoint presentation and did a n00b presentation at RockNUG this month.

.NET | Lambda
Wednesday, 15 June 2011 20:23:49 (Eastern Standard Time, UTC-05:00)   #     Comments [0]  | 
Tuesday, 10 June 2008

The Resharper cult members already know this, but for those who haven't joined yet, version 4.0 released today with VS 2008 support -- huzzah,  huzzah.  No longer able to resist the chanting and promises of eternal coolness I donned my robe and installed my free copy.

I clearly should have joined sooner.  Resharper has already changed my life.  First it pointed that I had redundant overrides  in the control I was working on, which I had really meant to delete.

Then it reminded me about the new implicit type declaration keyword var, so this...

XmlDocument SomeDoc = new XmlDocument();

becomes...

var SomeDoc = new XmlDocument();

Granted, that's not too exciting, but if your type declaration is something like...

Dictionary<SomeStrangeType,ANamespace.AnotherLongType> SomeDictionary = new Dictionary<SomeStrangeType,ANamespace.AnotherLongType>();

with var it becomes...

var SomeDictionary = new Dictionary<SomeStrangeType,ANamespace.AnotherLongType>();

Then Resharper pointed out something I didn't realize was available in C#, the object intializer?? VB.NET has long had something similar with the With statement (now with object initializer goodness too).  What's nice about this is that it saves repeating the instance name in front of the properties.  So this...

var MenuBinding = new MenuItemBinding();
MenuBinding.DataMember = MenuItemElementName;
MenuBinding.TextField = DisplayTextAttribute;
MenuBinding.NavigateUrlField = NavigationUrlAttribute;
MenuBinding.Depth = Depth;

becomes...

var MenuBinding = new MenuItemBinding
  {
     DataMember = MenuItemElementName,
     TextField = DisplayTextAttribute,
     NavigateUrlField = NavigationUrlAttribute,
     Depth = Depth
  };

I was staring at this new construct when I realized that -- it shouldn't work. The project I was working on was a Framework 2.0 project and these things were in 3.0 syntax.  But the darn thing compiles and works.  Not even a single warning.  WTF?  It turns out that since 3.0 and 3.5 are based on 2.0, these are simply compiler tricks -- there is nothing fundamentally different about the types.  Here's a blog post that explores in more detail what is happening under the covers.

Not bad for 15 minutes of tooling around.  Guess I am an official member. Where's the Koolaid?

.NET | 2.0 | 3.0 | 3.5 | Resharper
Tuesday, 10 June 2008 22:24:01 (Eastern Standard Time, UTC-05:00)   #     Comments [0]  | 
Saturday, 17 May 2008
Nothing like a code camp to get jazzed about all the stuff I could be working on. It is like a revival meeting; everything is new and exciting and possible.

I took in sessions about making DotNetNuke modules and the new ASP.NET Dynamic Data extensions. Very interesting stuff.  The Dynamic Data stuff appears to be a great way to bang out admin pages with minimal effort.

I also presented my little talk about the new Peer-to-Peer Networking goodies in the .NET 3.5 framework.  This is stuff that's been possible to do with the Windows API for a long time, but has finally been exposed through the managed classes for access by mere mortals.  Here is yet another chat application that demonstrates how it all works.

The real exciting namespace is its child the PeerToPeer.Collaboration namespace.  It is a framework for building p2p apps.  Didn't have the time to delve into it fully, as it is only supported in Vista. But it did provide the first compelling reason to upgrade, so I finally succumbed.

Just need to invent the 50 hour day to get to try out all the things I'd like to.

.NET | 3.5 | p2p
Saturday, 17 May 2008 20:30:07 (Eastern Standard Time, UTC-05:00)   #     Comments [0]  | 
Thursday, 20 December 2007
I went on vacation at the end of July and returned in early August. Life restarted in fits and starts.  But somehow I neglected to get this blog started again. Now that five months have passed, I think it is time to begin again.  So without further ado...

Had a question on a forum today about how to access the top master page if you are using nested master pages.  Seemed like a good time to break out some recursion. 

protected MasterPage UltimateMaster(Page ThePage)
{
      if (ThePage.Master == null)
      {
         //no master
         return null;
      }
      else
      {
         return UltimateMaster(ThePage.Master);
      }
}

//this will call itself until it runs out of Master Pages
protected MasterPage UltimateMaster(MasterPage ThePage)
{
      MasterPage TheMaster;

      if (ThePage.Master == null)
      {
           TheMaster = ThePage;
      }
      else
      {
           TheMaster = UltimateMaster(ThePage.Master);

      }
      return TheMaster;
}
I'd add these methods to a base web page class, so I can access them from all my pages.  Then it is easy to access the ultimate master page at any time...
MasterPage TheUltimateMaster = UltimateMaster(this);
To access any custom properties or methods that have been exposed, the master page needs to be cast to its strong type...
MyUltimateMasterPageType MyMaster = (MyUltimateMasterPageType) TheUltimateMaster;
Then the ultimate master page is ready to be used...
MyMaster.AUsefulMethod("SomethingSomehting");
I haven't had the occasion to use nested master pages, but I thought I'd offer this as an early Christmas present to anyone who does.

Happy Holidays.  Merry Christmas!

.NET | 2.0
Thursday, 20 December 2007 21:15:38 (Eastern Standard Time, UTC-05:00)   #     Comments [3]  | 
Monday, 16 April 2007
Spent Saturday getting my geek on at the NOVA (Nothern Virigina to those of you outside of the greater Washington DC area) Code Camp.  The camp was pulled together by Jeffrey Schoolcraft who marshalled a host of volunteers, speakers and contributors to make it a great success.  If you didn't learn at least 10 things you probably slept through all the sessions. Heck, I learned a bunch of things chatting between sessions. Here's a smattering of what I learned.

  • It's time to start learning about WCF (Windows Communication Foundation).  This is going to be the way to build distributed applications going forward, and it seems to get away from some of the headaches of remoting and web services.  Definitely a great plumbing platform that should make it easier to develop apps that span systems.
  •  WPF (Windows Presentation Foundation) is going to be very interesting eventually and even has some cool implementations, but the design tools aren't ahem, mature yet. But WPF will further erode the line between desktop and web apps. Fortunately, XAML should be very familiar to anyone who has been doing ASP.NET development.
  • I really need to get a copy of Resharper for my daily refactoring.
  • There's a better way to search for useful .NET information without having to wade through unrelated results in Google or other search engines. 
  • I was introduced to ELMAH, the library I need to use to replace the hand-rolled exception code I've been lugging around.
  • When ordering pizza for an event the ratio of pepperoni pizzas to cheese pizzas should be between 2:1 and 3:1. Not enough people actually like cheese pizza to make 1:1 a viable ratio.
Also got to meet a lot of people I had only known by name or online.  Not a bad way to spend a Saturday.

.NET | 3.0
Monday, 16 April 2007 09:32:13 (Eastern Standard Time, UTC-05:00)   #     Comments [0]  | 
Friday, 30 March 2007

There are four (development) life annoyances that I can do without:

  1. Recruiters who only use the state abbreviation to describe a job location. "Urgent need for Senior .NET Developer, Location: CA"
  2. Forum posters who demand code for entire applications. "Please send me chat server code -- urgent."
  3. Repeated requests for Interview Questions.  I've covered this elsewhere.
  4. Lazy gits who can't be bothered to learn how to read either C# or VB.NET. "Thanks for the answer, but my project is in VB.NET, I don't understand C#."
At least once a week, I'll answer a question on forum somewhere with a code example and get a "Thank you, but" response.  Often accompanied by a request to rewrite the code in their language of choice.  With perfectly named variables and smilies in the comments.

This burns my toast.  It takes enormous willpower not to simply respond "find another job you lazy git".

A) We're never talking more than 50 lines of code, usually it is around 20. 
B) 3/4 of the friggin' code is manipulating .NET Framework objects using .NET Framework methods and .NET Framework properties -- which are -- wait for it...

THE SAME FOR BOTH C# and VB.NET!


So this post is a (no longer) quick and dirty guide for figuring out how to translate C# into VB.NET (and vice versa, but frankly 92.6% of the time its a VB coder who complains).  It will become my standard response for all the future lazy gits.

Let's start at the top (of the class file that is)...

Need to reference a namespace...
ala C#: using System.Data.SqlClient;
ala VB: Imports System.Data.SqlClient

Note the ubiquitous semicolon (;).  C# statements can span pages like a sentence in Ulysses.  They don't end until the ; appears. VB statements get one line to do their business, unless they are ended with the awkward _ line continuation (underscore) which allows them to continue one more line unless they are ended with the awkward _, repeat.

A class...
ala C#: public class TheClassINeverHad
           {
             //fields, methods and properties -- oh my!
            }
ala VB: Public Class TheClassINeverHad
             'fields, methods and properties -- oh my!
          End Class
Ooooh no, C# does everything in lower case! (and its compiler is very strict about keeping it that way)
VB Capitalizes! (not that its compiler cares)

In C#, all code blocks are marked with with brackets{}.
In VB, code blocks usually go until a line that starts with End followed by the type of code block, which iin this case is Class.

Fancier class declarations...
ala C#: public abstract class TheClassINeverHad
ala VB: Public MustInherit Class TheClassINeverHad
ala C#: public sealed class TheClassINeverHad
ala VB: Public NotInheritable Class TheClassINeverHad
Why VB.NET couldn't use the more common OOP vernacular is beyond me.

Interface declarations...
ala C#: public interface IPractical
ala VB: Public Interface IPractical
Hooray, that should be clear even to the laziest git.

Extending a class...
ala C#: public class TheClassINeverHad: APracticalClass
ala VB: Public Class TheClassINeverHad
             Inherits APracticalClass
The humble colon does a lot here in C#.  The VB syntax leaves nothing to doubt.

Implementing an interface...
ala C#: public class TheClassINeverHad: IPractical
ala VB: Public Class TheClassINeverHad
             Implements IPractical
or interfaces...
ala C#: public class TheClassINeverHad: IPractical, IRidiculous
ala VB: Public Class TheClassINeverHad
             Implements IPractical
             Implements IRidiculous
The colon does everything! 

Extending and implementing...
ala C#: public class TheClassINeverHad: APracticalClass, IPractical, IRidiculous
ala VB: Public Class TheClassINeverHad
             Inherits APracticalClass
             Implements IPractical
             Implements IRidiculous
A comment...
ala C#: //This is a 1 line comment
          /* This starts a multiline comment
          This ends a multiline comment */
ala VB: 'This is a one line comment
There is no such thing as a multline comment in VB, but who comments code anyway?

You really should though.

a field...
ala C#: private int SomeNumberIWillUse;
ala VB: Private SomeNumberIWillUse as Integer
VB.NET surrounds the name of the variable with its access modifier and type.  C# gets all that out of the way then tells you the name.

a constant...
ala C#: private const string LAZY_GIT = "Lazy Git";
ala VB: Private Const LAZY_GIT as String = "Lazy Git"
a constructor...
ala C#: public TheClassINeverHad()
            {
                //Do Something Useful
             }
ala VB: public Sub New()
             'Do Something Useful
          End Sub

C# uses the name of the class to indicate the constructor. The Sub New in VB is a little clearer at first blush.

A structure can be a handy little doo-dad when a class is overkill...
ala C#: public struct Soda
           {
                 public string Name;
                 public int Calories;
            }
ala VB: Public Structure Soda
             Public Name as String
             Public Calories as Integer
          End Structure
More brackets in C#, another End statement in VB. C# shows it inclination for abbreviation. Patterns develop.

Let's not forget enumerations...
ala C#: public enum PlanetValues
           {
                    Mercury = 0,
                    Venus = 1,
                    Earth = 2,
                    Mars = 3,
                    Jupiter = 4,
                    Saturn = 5,
                    Uranus = 6,
                    Neptune = 7,
                    Pluto = 8
            }
            public enum PlanetValues
           {
                    Mercury,
                    Venus,
                    Earth,
                    Mars,
                    Jupiter,
                    Saturn,
                    Uranus,
                    Neptune,
                    Pluto
            }

ala VB: Public Enum PlanetValues
             Mercury = 0
             Venus = 1
             Earth = 2
             Mars = 3
             Jupiter = 4
             Saturn = 5
             Uranus = 6
             Neptune = 7
             Pluto = 8
          End Enum

        Public Enum PlanetValues
             Mercury
             Venus
             Earth
             Mars
             Jupiter
             Saturn
             Uranus
             Neptune
             Pluto
          End Enum

All these enumerations are identical.  If no value for the first element is specified it is set = 0, every other unspecified element is incremented one from the previous element. Curiously the C# syntax uses commas and not semi-colons.

a local variable...
ala C#: string DeveloperPersona;
ala VB: Dim DeveloperPersona as String
arrays...
ala C#: string[] CoolDevTools;
           string[] CoolDevTools = new string[5];
           //assignment
          CoolDevTools[0] = SomeString;
ala VB: Dim CoolDevTools as String()
          Dim CoolDevTools(5) as String
          'assignment
          CoolDevTools(0) = SomeString
             

C# uses square brackets [] for the elements.
VB uses parentheses ().

Ditto for collection elements...
ala C#: AnObjectType SomeObject = (AnObjectType)SomeHashtable[SomeKey];
           A
nObjectType SomeObject = (AnObjectType)SomeArrayList[SomeIndex];
ala VB:  Dim SomeObject as AnObjectType = SomeHashtable(SomeKey)
          
Dim SomeObject as AnObjectType = SomeArrayList(SomeIndex)
          'or if Option Strict is on
          D
im SomeObject as AnObjectType = CType(SomeHashtable(SomeKey), AnObjectType)
         
Dim SomeObject as AnObjectType = CType(SomeArrayList(SomeIndex), AnObjectType)
             
C# doesn't do narrowing implicit type casts,  so an element retrieved from an untyped collection must be explicitly cast.  This is done by wrapping the object type in parentheses and smooshing it against the collection name.
VB will implicitly cast unless Option Strict is On, in which case the CType method must be used to cast the element returned to the proper type.

a method that does NOT return a value...
ala C#: public void ThePerfectMethod(string DeveloperName)
             {
                // coding goodness
             }
ala VB: Public Sub ThePerfectMethod(DeveloperName as String)
                'Coding Goodness
          End Sub
a method that does return a value...
ala C#: public int ThePerfectMethod(string DeveloperName)
             {
                // coding goodness
                return 42;
             }
ala VB: Public Function ThePerfectMethod(DeveloperName as String) as Integer
                'Coding Goodness
                Return 42
          End Function
As with fields and constants, C# states the access modifier and the type being returned by the method before getting to the name.  When nothing is returned the type is void.
VB has separate keywords to differentiate between methods that return nada (Sub) and those that return something (Function).
Parameters are types just like variables are in each language:  type Name in C#, Name as Type in VB.

a read/write property...
ala C#: public int TheAnswer
             {
               get{   return mTheAnswer;}
               set{  mTheAnswer = value;}
             }
ala VB: Public Property TheAnswer() as Integer
                Get
                    Return mTheAnswer
                End Get
                Set (Value as Integer)
                   mTheAnswer = Value
                End Set
                     
          End Property

a read-only property...
ala C#: public int TheAnswer
             {
               get{   return mTheAnswer;}
             }
ala VB: Public ReadOnly Property TheAnswer() as Integer
                Get
                    Return mTheAnswer
                End Get
          End Property
a write-only property...
ala C#: public int TheAnswer
             {
               set{  mTheAnswer = value;}
             }
ala VB: Public WriteOnly Property TheAnswer() as Integer
                Set (Value as Integer)
                   mTheAnswer = Value
                End Set
                     
          End Property
VB.NET needs to be explicity told a property is read- or write-only, C# is happy as long as there is a get or set -- it figures it out.

static(Shared) members...
ala C#: private static int mANumberEveryoneNeeds;
           public static ANumberEveryoneNeeds
           {
                get{return
mANumberEveryoneNeeds;}
           }
           public static void ResetTheNumber()
           {
               
mANumberEveryoneNeeds = 0;
           }
ala VB: Private Shared mANumberEveryonNeeds as Integer
           Public Readonly Shared Property ANumberEveryoneNeeds() as Integer
                Get
                   Return mANumberEveryoneNeeds
                End Get
           End Property
           Public Shared Sub ResetTheNumber ()
                 mANumberEveryoneNeeds = 0
           End Sub

Shared = static.  static = Shared. Static members are shared by ALL instances of a class.  The meaning of static is not as immediately a clear as Shared. But it's not that hard to remember.

Branching...
ala C#: if(SomeVariable == 42)
             {
                Answer = "That's it!";
                HasWisdom = true;
             }
           else
             {
                Answer = "That's not it.";
                HasWisdon = false;
             }

          //one line syntax
           if(SomeVariable == 42)
                Answer = "That's it!";
           else
                Answer = "That's not it.";
               


ala VB: If SomeVariable = 42 Then
             Answer = "That's it!"
             HasWisdom = True
          Else
             Answer = "That's not it."
             HasWisdom = False
          End if
There's no Then in C#, the boolean expression is wrapped in parentheses and the code to execute is within {}. The brackets are not required if the condition only executes one line.  Like most other constructs in VB, the code block ends with a uniquely named End statement: End If.

Note in C# the == is an evaluation operator, as opposed to the assignment operator =.  In VB = performs both tasks.

What fun is an If statement without boolean logic...
ala C#: if(!Page.IsPostBack) //Not operator
          
if(Night != Day) //Inequality
          
if(Night == Day & Pigs.CurrentState == PigState.Flying) // And
           if(Night == Day && Pigs.CurrentState == PigState.Flying) //Conditional And
          
if(Night == Day | Pigs.CurrentState == PigState.Flying) // Or
          
if(Night == Day || Pigs.CurrentState == PigState.Flying) // Conditional Or
          
if(Night == Day ^ Pigs.CurrentState == PigState.Flying) // Xor


ala VB: If Not Page.IsPostBack Then
           If Night <> Day Then 'Inequality
           If Night = Day And Pigs.CurrentState = PigState.Flying Then
          
If Night = Day AndAlso Pigs.CurrentState = PigState.Flying Then 'Conditional And
           If Night = Day Or Pigs.CurrentState = PigState.Flying Then
          
If Night = Day OrElse Pigs.CurrentState = PigState.Flying Then 'Conditional Or
          
If Night = Day Xor Pigs.CurrentState = PigState.Flying Then
          
VB spells everything out, though <> is a unique feature of the language.  The conditional operators AndAlso (&&) and OrElse(||) are tres useful, they short circuit the code and stop evaluting as soon as the appropriate condition is met.

And when If Then is isn't enough...
ala C#: switch(SelectedPlanet)
           {
                 case PlanetValues.Earth:
                      message = "Live there";
                      break;
                 case PlanetValues.Venus:
                 case PlanetValues.Mars:
                      message = "Landed there";
                      break;
                
case PlanetValues.Mercury:
                 case PlanetValues.Jupiter:
                 case PlanetValues.Saturn:
                 case PlanetValues.Uranus:
                 case PlanetValues.Neptune:
                      message = "Flew by";
                      break;
                  case PlanetValues.Pluto:
                      message = "Is it a planet?"
                      break;
                   default:
                      message = "Never heard of it";
                      break;
           }

           

ala VB: Select Case SelectedPlanet
                Case PlanetValues.Earth
                   message = "Live there"
                Case PlanetValues.Venus, PlanetValues.Mars
                   message = "Landed there"
                Case PlanetValues.Mercury, PlanetValues.Jupiter, PlanetValues.Saturn, PlanetValues.Uranus, PlanetValues.Neptune
                   message = "Flew by"
                Case PlanetValues.Pluto
                   message = "Is it a planet?"
                Case Else
                   message = "Never heard of it"
          End Select

In C#, there's only one value per case, but once a supplied value matches a case, the code will "fall through" until it finds a case that executes code.  All cases that have code must end with a break;.
In VB, multiple values can be present on a line, it's also possible to do ranges. The code cannot fall through in VB, but the extra flexibility for defining case values makes it unecessary.

For Loops...
ala C#: for(int Index = 0; Index < SomeIntegerArray.Length; Index ++)
             {
                 Total += SomeIntegerArray[Index];
                 CallSomeOtherFunction(SomeIntegerArray[Index]);
             }
             //A single line For Loop can be done without the brackets
           
for(int Index = 0; Index < SomeIntegerArray.Length; Index ++)
               
Total += SomeIntegerArray[Index];

ala VB: For Index as Integer = 0 to SomeIntegerArray.Length -1
                Total += SomeIntegerArray(Index)
                CallSomeOtherFunction(SomeIntegerArray(Index))
          Next

In C#, {} brackets define what code gets looped, but a single line statement does not require brackets. Iteration step size is always specified
VB always requires the Next statement.  The iteration step size defaults to 1 for VB, to change the iteration step size...

ala C#: for(int Index = 0; Index < SomeIntegerArray.Length; Index += 2)
             {
                 Total += SomeIntegerArray[Index];
                 CallSomeOtherFunction(SomeIntegerArray[Index]);
             }
           


ala VB: For Index as Integer = 0 to SomeIntegerArray.Length -1 Step 2
                Total += SomeIntegerArray(Index)
               
CallSomeOtherFunction(SomeIntegerArray(Index))
          Next
To break out of the loop before it completes...
ala C#: for(int Index = 0; Index < SomeIntegerArray.Length; Index += 2)
             {
                 Total += SomeIntegerArray[Index];
                 if(CallSomeOtherFunction(SomeIntegerArray[Index]) == false)
                   break;
             }


ala VB: For Index as Integer = 0 to SomeIntegerArray.Length -1 Step 2
                Total += SomeIntegerArray(Index)
                If
CallSomeOtherFunction(SomeIntegerArray(Index)) = False Then
                   Exit For
                End if
          Next
break is used to get out of every kind of loop in C#.  The command for exiting a loop in VB.NET depends on the type of the loop. This can come in handy for nested loops of different types.

For each loops...

ala C#: foreach(Universe PossibleUniverse in PossibleUniverses)
             {
                 if(PossibleUniverse.HasStrongForce)
                 {
                     
                      AddToViableCandidates(PossibleUniverse);
                 }
             }
           


ala VB: For Each PossibleUniverse as Universe in PossibleUniverses
                If PossibleUniverse.HasStrongForce Then
                   AddToViableCandidates(PossibleUniverse)
                End if
          Next

Ignore the brackets and the for each loops look a lot alike.


Do While Loops...
ala C#: do
             {
                 Total += SomeIntegerArray[Index];
                 if(CallSomeOtherFunction(SomeIntegerArray[Index]) == false)
                   break;
                 Index++;
             }
             while(Index < SomeIntegerArray.Length);

ala VB: Do
                Total += SomeIntegerArray(Index)
                If
CallSomeOtherFunction(SomeIntegerArray(Index)) = False Then
                   Exit Do
                End if
                Index += 1
          Loop While Index < SomeIntegerArray.Length

          Do While Index < SomeIntegerArray.Length
                Total += SomeIntegerArray(Index)
                If
CallSomeOtherFunction(SomeIntegerArray(Index)) = False Then
                   Exit Do
                End if
                Index += 1
          Loop

The do loop in C# always executes at least once.  The top version of the VB loop does as well.  While the second version evaluates the condition before executing. This is the one of the few code structures in VB that doesn't denote it's end using an End statement (the others being the for and for each loops). If it did it would look something like this...

          'This is not legal syntax -- just what a Do loop would look like if VB were maddeningly consistent
          Do
                Total +=SomeIntegerArray(Index)
          End Do While Index < SomeIntegerArray.Length

Which is just goofy.

Do Until Loops...
ala C#: do
             {
                 Total += SomeIntegerArray[Index];
                 if(CallSomeOtherFunction(SomeIntegerArray[Index]) == false)
                   break;
                 Index++;
             }
             while(Index < SomeIntegerArray.Length);

ala VB: Do
                Total += SomeIntegerArray(Index)
                If
CallSomeOtherFunction(SomeIntegerArray(Index)) = False Then
                   Exit Do
                End if
                Index += 1
          Loop Until Index = SomeIntegerArray.Length

          Do Until Index = SomeIntegerArray.Length
                Total += SomeIntegerArray(Index)
                If
CallSomeOtherFunction(SomeIntegerArray(Index)) = False Then
                   Exit Do
                End if
                Index += 1
          Loop

Wait a second -- there's no do until in C#. Until is just the other side of while.  Instead of executing while a condition is true, it executes until it is true. When moving from VB.NET to C# just use the while and flip the condition to its opposite. Again the C# loop and the first VB loop execute at least once. 

And the last loop is the plain old while loop...
ala C#: while(Index < SomeIntegerArray.Length)
             {
                 Total += SomeIntegerArray[Index];
                 if(CallSomeOtherFunction(SomeIntegerArray[Index]) == false)
                   break;
                 Index++;
             }
           

ala VB: While Index < SomeIntegerArray.Length

                Total += SomeIntegerArray(Index)
                If
CallSomeOtherFunction(SomeIntegerArray(Index)) = False Then
                   Exit While
                End if
                Index += 1
          End  While
        
While loops in both languages evaluate the condition before executing.  Note the while uses the familiar Exit While to break and the End While to terminate the loop.

Finally, a tricky difference -- hooking up event handlers...
ala C#: SomeButton.Click += new ButtonEventHandler(SomeButton_Click);
           
ala VB: AddHandler SomeButton.Click, AddressOf SomeButton_Click

          'or directly declare it
          Sub SomeButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles SomeButton.Click
VB lets you hook up the Handler on the event declaration or add the handler dynamically.  C# only allows the dynamic hook. 

I think this post has sufficiently covered 93.7% of commonly encountered code.  I'd cover Generics (VB usage)  but I think anyone working with Generics probably doesn't have any problems reading either language.

Here are some reference links...
And for the truly lazy or people who have to translate more than 20 lines of code, there are converters (though you might get some interesting results) ...
So learn 'em both -- double your code examples, double your employment opportunities -- double your fun.
.NET | 2.0 | Annoyances
Friday, 30 March 2007 17:12:15 (Eastern Standard Time, UTC-05:00)   #     Comments [2]  | 
Wednesday, 14 March 2007
Sometimes I see a method and say "Where have you been all my life?"  When it's in code I wrote over a year ago, I have to say "How did I ever let you go?"  I'm writing this so I don't ever forget it again and to introduce the most useful class that holds it.

The method in question is quite simple, but very useful...

Path.GetFileName(SomeFilePath)

It takes a full file path and just returns the File Name and Extension. Very handy when uploading files or checking URLs.  So useful, I wrote my own version of the function and put it in the base web page class of my projects.   So today I am wandering through some code and there it was.  I used it in a method that I wrote almost 2 years ago and then FORGOT about it. Duh, talk about reinventing the wheel. 

And there are more wheels....

Path.GetFileNameWithoutExtension(SomeFilePath)

Nice! Saves an IndexOf or Split call to get the goodies.

Path.ChangeExtension(SomeFilePath, NewExtension)

Quick change file extension and it makes sure there is a dot between them.

Path.GetPathRoot(SomeFilePath)

Gets the other side of the file path.

But the real nice one is this one...

Path.Combine(SomeFilePath1, SomeFilePath2)

This is the one I REALLY wish I knew about.  There are so many things that need to be checked to join two parts of a path together properly.  Is one of the parts blank?  Does part 1 end with a path separator, does part 2 start with one?  This one call replaces 12-15 lines of code. 

Oy, if I had only remembered this class, it could have saved me a few hours of my life. Need to investigate the Framework a little more thoroughly in the future. 

As for the Path class -- she's never leaving my side again. 

Wednesday, 14 March 2007 21:11:17 (Eastern Standard Time, UTC-05:00)   #     Comments [1]  | 
Wednesday, 17 January 2007
Under ASP.NET 1.1, the ASP.NET engine is not (by default) responsible for the application's image, style sheet, and javascript files. These are served up directly by IIS. ASP.NET can be made responsible for these file types by playing with the ISAPI file mappings and maybe creating an HttpHandler or two.

This changes under ASP.NET 2.0.  The ASP.NET engine has responsibility for all these file types and is called when a request for one is made.

So what?  The files get served, the application works, who cares if IIS or ASP.NET does the work?

In many applications it wouldn't matter, but what happens if the application has been secured in web.config like so...

<authorization>
   <deny users="?" />
</authorization>

... and an anonymous user tries to access the site and gets redirected to the login page?

Under 1.1, since IIS was responsible for the css, javascript and image files, it wouldn't matter -- the page would be served as expected, showing all the images and properly referencing any stylesheets or script files.

Under 2.0, the anonymous user would see an unstyled page with blank image boxes. Any javascript calls to referenced files won't work either. Why? Because ASP.NET isn't going to serve up anything but the login page to an anonymous user -- because that is what it was told to do.

This is great for security, but can be a little frustrating when you KNOW you put the right path in for that image, and KNOW that the all h1 elements should be hot pink  and all you see is an unformatted mess.

Fortunately it is very easy to work around this so the public pages on a secured site show up properly.  All that needs to be done is to tell the application that anonymous users are allowed to access the content in certain folders. This can be done using a location element or two in the web.config file.  The following one allows anonymous users to access content in the unsecured_images folder...

<location path="unsecured_images">
    <system.web>
      <authorization>
        <allow users="*" />
      </authorization>
    </system.web>
  </location>

That's all there is to it.


Wednesday, 17 January 2007 22:29:44 (Eastern Standard Time, UTC-05:00)   #     Comments [1]  | 
Wednesday, 20 December 2006

Finally! .NET 2.0 has been out for a year.  Finally found the time to move our main application to 2.0. It's been a bit of an adventure.  There are 12 class libraries, 2 server control assemblies, a service, a web app and various utilities.  Two of the class libraries are in C++, one managed, one native. The truly insane can read about the little odyssey through those assemblies.  Everything else is written in VB.NET. 

The VB.NET class libraries converted easily.  The only issue was in the few classes that performed XSL Transformations where I had to change a couple of deprecated method calls.  These were no surprise.  Other than that there were only warnings for untyped functions or parameters (very naughty, and one of the dangers of working in VB with OPTION STRICT OFF) and a surprising number of unused local variables. 

The web application was a lot trickier than anticipated.  There are some fundamental differences between 1.1 and 2.0 web applications. One of the significant changes is in the coding model.  2.0 makes use of partial classes, so that a single class can be created from separate files, this cleans some things up.  There are no longer control declarations in the code-behind file, but it is a change. 

Here is a very handy resource that discusses most of the issues you will run into when converting from 1.1 to 2.0. 

In the standard out-of-the-box VS2005, the project file for web applications has also gone the way of the dodo, you create Web Site Projects.  Everything in the project tree gets put into the application. Fortunately, there is a feature to exclude files, which you will use. Since the Web Site Project includes ALL the files in the directory tree, files that you excluded in your 1.1 project will suddenly reappear like uncompilable ghosts in the 2.0 version. The other annoying "feature" is that these projects spew forth an assembly for every folder in your application, and couple of others for good measure, and the files are randomly named.  Hello deployment fun -- I'm sure there's good reason for this, but it is not intuitively obvious, it seems friggin' nutty.

This application model had been fine for the smaller projects I had converted, and I figured I would discover a way to deal with the assembly vomit, so I pushed on assuming that I was moments away from having a our application working in 2.0.

But it was not to be, this web application pushed the Web Site Project model over the cliff of despair.

The application has around 60 pages, 15 classes and 15 user controls spread amongst 10 directories. Most of the heavy lifting is done in the underlying libraries. I didn't think it was that large until I tried to compile it.  In VS 2003, it was up and running in under a minute, in VS2005 it was 5+ minutes, and the sucker was crashing every time I changed the base web page class that the pages inherited from.  I lived with this for about a day, googling while it compiled or restarted, toggling various settings, swearing and pruning previously exlcuded and unused pages ruthlessly. 

After one seemingly eternal cycle of rebooting, I seriously considered asking for a quad-core super box or retreating back to 1.1.  I decided to take one more look around the web for a solution and I stumbled across this article, which in turn led me to discover an alternate model to this lunancy, the Web Application Project! It was the old 1.1 compilation model, complete with a single assembly output -- hooray.  It required some VS update installations and yet another conversion from my original 1.1 application, but in a few hours I had a quickly compiling application.  Some testing and a small victory dance later, and it was time to start ripping out the facacta hand-rolled page templates and putting in the master pages!



Just a reminder kids, always use source code control, especially when undertaking a conversion.  It makes mistakes almost painless and recovery simple!


UPDATE:  MS has shipped the first service pack for VS 2005. This includes the Web Application Projects. If you have previously installed the Web Application update, you will have to uninstall it before installing the service pack.

Wednesday, 20 December 2006 23:04:59 (Eastern Standard Time, UTC-05:00)   #     Comments [0]  | 
Thursday, 07 September 2006
Time tramples on and those .NET 1.1 applications that were shiny and new just a few years ago are probably beginning to show their age.  Improvements and refinements in every application or class library have probably left behind a goodly number of dead and dying methods, or even whole classes.  This is probably even more true of 1.1 applications that were ported to 2.0 and since refactored to take advantage of new .NET features. 

While ripping out all these methods before some newbie team member (or forgetful old hand) accidentally uses one would be ideal, this is not always a practical solution. But there is an easy way to warn off developers while planning for eventual refactoring, the Obsolete Attribute.

Marking a method, property, field, class or interface with the Obsolete Attribute will generate a compiler warning, and Visual Studio will clearly mark each offending use of the "soon" to be removed member.  Best of all, it easy is to use. 

In C#...
[Obsolete("This method has been replaced by ReallyUsefulMethod.")]
public void OnceUsefulMethod(){


ala VB.NET (don't forget the line continuation)...
<Obsolete("This method has been replaced by ReallyUsefulMethod.")> _
Public Sub OnceUsefulMethod()

That's all there is to it. If it's called any place, a compiler warning will be generated, and Intellisense will also display its impending doom.

If for some reason, the method needs to be taken out of use immediately (for a security concern, etc.) , the Obsolete Attribute can also generate a compiler error using the code below.  The second argument to the constructor if set=true will generate an error instead of a warning.

In C#...
[Obsolete("This method has been replaced by ReallyUsefulMethod.", true)]
public void OnceUsefulMethod(){


ala VB.NET...
<Obsolete("This method has been replaced by ReallyUsefulMethod.", True)> _
Public Sub OnceUsefulMethod(){

Using this attribute is also a quick and dirty way to find out all the places in an application a particular code element is being used.  Compile the application they'll all be nicely listed in the task list.

The Obsolete Attribute -- an easy to use, graceful first step in pruning and refactoring -- try it today!

Thursday, 07 September 2006 09:14:07 (Eastern Standard Time, UTC-05:00)   #     Comments [0]  | 
Thursday, 18 May 2006
Just because an application is developed in .NET doesn't make it object oriented.

It might have classes.

It might have interfaces.

It might have methods.

It still is a mass of spaghetti code, with some objects thrown in to act as meatballs.

It never ceases to amaze me what lengths developers will go to to turn .NET into a overwrought scripting language, instead of harnessing some simple OOP principles to make their code and their lives simpler.

So, today we are going to talk about Encapsulation. Yes, I have spent the last two weeks ripping through an app that had objects, but frequently didn't use them as much more than fancy structures.  And, yes, I will rant a little bit (more).

Encapsulation is probably the simplest OOP concept to grasp, and it should be the easiest to implement.  A developer does not need to understand class factories, inheritance or polymorphism to develop encapsulated classes.  A desire for clean interfaces coupled with an abhorrence for writing the same code twice will lead naturally to encapsulation.

Yet, this well-known tool of code reuse, is often left unloved and dusty, next to the once-cracked Gang of Four OOP bible.

I like to think of Encapsulation as empowering an object.  It allows the object to say, "This is what I do. This is what I expect.  Don't tell me how to do my job, just give me what I need and let me do it."

Simple, no?  You'd think so, but it is clearly not a universal practice.

Here is an object.  What it does really doesn't matter for this discussion.  It has two ways of being populated -- one when it is first created, another for when it is  reconstituted from the database. It has two consctructors. This is a very common situation. 

public class SomeEntity{

    //Constructor for new instance
     public SomeEntity(string Name, string ANeededValue, int AnotherNeededValue){...}
    
    //Constructor for a retrieved instance
     public SomeEntity(int ID, string Name, XmlDocument TheReasonForTheObject){...}

    //Members
    private string mName;
    //...

    //Properties, Methods, Etc.

    public void DoSomethingImportant(){...}

    public string Name{
       { get{return mName;}
    }
    //...
}

Now, I don't have a problem with the first constructor -- at least there is one, this actually demonstrates an important bit of encapsulation: controlling how the object is instantiated.  The constructor gives a way to tell the world,  "This is what I need to start properly!"

For the free-for-all that can result without encapsulated instantiation, here's the same object sans a defined constructor...

public class SomeEntity{

       //default constructor
       public SomeEntity(){}
  
    //Members
    public string Name;
    public string ANeededValue;
    public int AnotherNeededValue;
   
   
//Properties, Methods, Etc....
    public void DoSomethingImportant(){...}

}

What's required to make sure an instance of this object works properly?  The developer's dilligence, memory and typing skills.  Everywhere the object is created, the developer must remember to type four lines of code -- just to get the object in a state where it is minimally functional.

SomeEntity AnObjectINeed = new SomeEntity();
AnObjectINeed.Name = "Fred";
AnObjectINeed.ANeededValue = "Tuesday";
AnObjectINeed.AnotherNeededValue = 789;

Forget to supply a value -- oops, error. What's missing?  Hope the exception message is clear and go hunting. It is bad enough that this code will be cut-and-pasted willy-nilly every time the object is needed, but what is worse is the maintenance implication.  Things change, the object needs an additonal value to work properly....

public class SomeEntity{

  
    //Members
    public string Name;
    public string ANeededValue;
    public int AnotherNeededValue;
    public DateTime OoopsForgotThis;
   
    //Properties, Methods, Etc....
    public void DoSomethingImportant(){...}

}

Hmmm, what happens now? The object won't work without the new value, but the application still compiles.  The developer must hunt for EVERY creation of the object and add another line of code, and then clean up the inevitable bugs when he misses a few.

Using a defined constructor avoids this problem.

    //Constructor for new instance
     public SomeEntity(string Name, string ANeededValue, int AnotherNeededValue, DateTime OoopsForgotThis){...}

The application won't compile now. All the places the code needs to be changed will be listed, they don't have to be hunted for.  Once the changes have been made and the app compiles, the object will always have what it needs to do its job.

Pardon the long aside, and let me finally return to what bothered me about the second constructor in the example above...

//Constructor for a retrieved instance
  public SomeEntity(int ID, string Name, XmlDocument TheReasonForTheObject){...}

What bothers me here is a subtle, but more troubling, lack of encapsulation related to this constructor. 

In order to call this constructor, three parameters must be supplied, an ID, a name and an XMLDocument. Now, where are these values stored? In a database record.  They are retrieved via a stored procedure call using the entity's ID, which is a unique integer value. 

A UNIQUE value.

The ID is unique and possesses all the object needs to know to reconstitute itself.  Why then, are the other two values needed in the constructor?

They're NOT!

Why are they there? 

I have no friggin' clue.  But this is part of the foo I've been fighting for the last few weeks. There are 5 or 6 lines of database-related code that precede every use of this constructor, along with the creation of an XmlDocument object from its string respresentation.  That's 8 lines of code repeated each time the object is recreated from the database, all of which SHOULD have been placed in the object, so it could have populated itself.

But that's not all?  What is controlling whether or not:
1) The name and XML document supplied are actually related to the supplied ID?
2) The XMLDocument has the proper schema the object expects?

The memory, diligence and typing skills of the developer.  In other words, NO ONE! 

By writing the object so it controls its own data retrieval, these problems are avoided. The object saved (or should have saved -- don't get me started) its own data and can be fairly confident it is getting the same information back -- in proper form. 

//Constructor for a retrieved instance
public SomeEntity(int ID){...}
The object is empowered, it controls its data, it works properly.  It can be used in code without requiring 8 supporting lines of code to be written each time. 

Why? 

It's encapsulated!

Want to make the app work when its disconnected and need to store the object in a local Access database?  No problem, change the storage and retrieval code in the object.  The rest of the app doesn't know and doesn't care how or where the object data is stored.  All it knows and cares about is that if it saved a SomeEntity object with a unique ID = 1776, that when this code is called...

    SomeEntity AnObjectINeed = new SomeEntity(1776);

It will get back a SomeEntity object with an ID = 1776 and the proper XMLDocument.

An object born ready to do what it is supposed to do.

What's hard about that?

Really?

Thursday, 18 May 2006 22:35:28 (Eastern Standard Time, UTC-05:00)   #     Comments [0]  | 
Friday, 14 April 2006
Saw a strange method call tonight while answering a post...

System.Threading.Interlocked.Increment(i)

It was in a simple loop, and it turns out it was generated by a code converter (C# to VB.NET) so the poster didn't know what it was for (curiosity is far too lacking in this world, but that's a rant for another day).  Fortunately, like every other of the 7-gazillion methods in the .NET framework, if you know it's name you can look it up very easily. Ah, it is a thread-safe incrementer for use on shared variables. It ensures that the value is updated and read in an atomic transaction, in other words, other threads won't increment it as well before it is read. There is no need to use it on a local variable, but it is a potentially handy tool found in the Interlocked class.

Now, about the only time I can think you would use this would be if you had a method that provided a unique integer ID throughout an application.  I personally let SQL Server handle its own ids.  But if you don't want to use IDENTITY in SQL or aren't using a database engine to store your data, this is a handy thing to have.  It also existed in  version 1.0 of the framework, so its not something new, but its not something you'd use everyday, which raises two related questions:

1) What facacta code converter turns a simple for loop into something so arcane?
or
2) is this call used under the covers of every single loop?

Ah, found the suspected converter on the first try. Thank you Google.

It turns this simple loop

for(int i=0;i<10;i++)
{
    Debug.WriteLine(i);
}


into

Dim i As Integer = 0
While i < 10
 System.Math.Min(System.Threading.Interlocked.Increment(i),i-1)
End While

Why not?

    Dim i as Integer
    For i = 0 to 9
       Debug.WriteLine(i)
    Next

Or even

Dim i As Integer = 0
While i < 10

 Debug.WriteLine(i) 
 i = i + 1 
End While

Of course, this could be what is happening under the covers anyway.  Why this would be so, I don't have the foggiest.  Let's see if we can find out.

As you probably know, when you compile a .NET app, it gets turned into MSIL (Microsoft Intermediate Language) code, not to machine code (the JIT handles that when you run the app). There is a tool that let's you look at this language if you are so inclined, the MSIL Disassembler.  Being so inclined today, let's see what our for loop looks like in MSIL (the // are comments in the MSIL that indicate the original source code)...

//000028:    for(int i = 0; i<10; i++)
  IL_0000:  ldc.i4.0
  IL_0001:  stloc.0
  IL_0002:  br.s       IL_0013
//000029:    {
//000030:     Debug.WriteLine(i);
  IL_0004:  ldloc.0
  IL_0005:  box        [mscorlib]System.Int32
  IL_000a:  call       void [System]System.Diagnostics.Debug::WriteLine(object)
//000028:    for(int i = 0; i<10; i++)
  IL_000f:  ldloc.0
  IL_0010:  ldc.i4.1
  IL_0011:  add
  IL_0012:  stloc.0
  IL_0013:  ldloc.0
  IL_0014:  ldc.i4.s   10
  IL_0016:  blt.s      IL_0004
//000029:    {
//000030:     Debug.WriteLine(i);
//000031:    }
//000032:   }
  IL_0018:  ret

You will notice that there is no reference to the Interlock class nor the Math class, which is reassuring.  It's simply looping through and adding 1 to i.  Time to do a little speed test in VB.NET and see what happens when we use the ugly converted code versus the vanilla implementation.

Time (milliseconds)
Iterations Vanilla Converted
10 16 16
100 93 93
1000 1050 1105
10000 15900 26300

Like almost every programming sin, the results are not evident in small samples, but become glaring when you actually start doing something intensive.  In fact running the 10,000 iterations on the converted code caused my little test app to crash occassionally.

The moral? If you use a code converter:
a) Find a good one
b) Don't take it as the gospel truth
c) Clean up after it when it makes boo-boos, especially obvious ones.

Found a couple of goodies while researching this entry.  This is an article about a VS add-in to paste a chunk of C# code as VB code.  Looks pretty cool.

And this is a list of research tools you can download from Microsoft.  Note the reference to F#!

Friday, 14 April 2006 22:53:33 (Eastern Standard Time, UTC-05:00)   #     Comments [0]  | 
Thursday, 23 March 2006
First the good news, there is a cool new method on the string class, instead of having to do the following...

if(astring != null)
   if(astring.Length > 0)
      bstring = astring;

There is the new String.IsNullOrEmpty function that allows you do this...

  if(!String.IsNullOrEmpty(astring))
     bstring = astring;

OK, it doesn't save a lot of code, but it's a 33% savings and it makes for more readable code.  Also it is faster than using the string == ""

if(astring != null)
   if(astring == "")
      bstring = astring;

and it won't throw a null execption that would occur on the following if you don't check for a null first.


   if(astring.length == 0)
      bstring = astring;

Now, for some disturbing news about app recycling when your web app deletes files or directories.  Mike Belcher found this the hard way, his sessions were dying and he didn't know why.  He was deleting some files, which worked fine in 1.1, but if you delete too many in 2.0, hello recycling, good-bye sessions.  Here's some more info.

This is some major foo.  If you are running some intensive logging or doing lots of file uploading, you can blow up your app info, sessions and cache without having a clue why.  The suggested workaround (using junction points) is a little tedious and  is also not viable for shared hosting systems.

A better workaround is buried in one of the comments of Scott's blog...

The App_Data folder of the web app is NOT monitored by the File Change Notification, so if any part of your web app needs to do lots of file or directory manipulation, do it there to prevent sudden AppDomain recycling.

I'm surprised that this new "feature" didn't bite more people on the ass during the beta period.

 In a perfect world, a patch to turn off this behavior will be available soon.

Thursday, 23 March 2006 22:55:17 (Eastern Standard Time, UTC-05:00)   #     Comments [0]  | 
Wednesday, 15 March 2006

Among the many improvements of .NET 2.0 is a subtle but welcome one in GridView, the replacement to the DataGrid control.

The Items have finally left the building.  Any old kinda grid control should have columns and rows.

The DataGrid had Columns and Items?

What in the world is an Item?  It's a row, but it's not called that -- for a very good reason I am sure.

The GridView has Columns and Rows!

Hooray!

Instead of ItemCreated, or ItemDataBound event handlers, there are RowCreated and RowDataBound.  Instead of ItemType there is RowType.

I cannot tell you how confusing this was for developers when first working with the DataGrid.  "How can I access a row?" must have been screamed at monitors from Mountain View to Mumbay.

What things are named can greatly affect how easy/hard it is use someone else's interface or maintain code.  How many times have you written code for something, only to find the same functionality in an obscurely/badly named function or class?

Consistent, meaningful naming makes it much easier for someone else, or the future you (go read some code you haven't touched in a year) to get what you are trying to do.

I must confess that I have not always been the best practioner.  My original programming platform was the Apple II, and variable names were limited to 8 characters (only the first three of which were meaningful -- found that out the HARD way), and I've never fully overcome the combined effects of that and my Modified Hunt & Peck Typing skills. 

This is something I have worked to be better at, but this post from Ryan Olshan really made it hit home.  I will paraphrase his thesis as "Variable names should be like characters in novel, they should be easily identifiable and make the reader care what happens to them". 

Especially with Intellisense and the built-in refactoring tools in Visual Studio (this one especially), there is no reason to skimp on meaningful naming and it's easy to fix past mistakes.

Wednesday, 15 March 2006 12:41:54 (Eastern Standard Time, UTC-05:00)   #     Comments [0]  | 
Tuesday, 07 March 2006
One of those stupid things...

I opened up a 2.0 website I was working on and Visual Studio decided it needed to be converted. Not sure why, unfortunately I wasn't paying attention.  Fortunately, I did tell VS to back up the project.  Went to run the website, which was working yesterday.  I get an allowDefinition='MachineToApplication' error.  What the badword !?!

(BTW, I believe coding -- much like plumbing -- requires lots of swearing to let off steam to save passers-by and inanimate objects from more physical acts of aggression.)

My first, VERY ERRONEOUS, thought was that the stupid project was trying to run under IIS, which I didn't want it to do.  I had been running it under the very handy ASP.NET Development Web Server. But I thought, I'll play along.  I created a virtual directory under my local IIS and pointed it to my website.

Same friggin' error.  More swearing.  Some googling.  What's going on?

Finally, looking at the directory structure, I see the backup folder and decide to just open the old project.  I nuke the "converted" website and copy the old files into the directroy stucture, "wisely" leaving the backup folder intact, just in case.

Same friggin' error.  More swearing. 

Then it hits me.  The backup folder has a web.config file in it. I move the backup folder out of my website tree.  I run the website.

It works. I get the last of the swearing out of my system.

The moral of the story, if you are getting the allowDefinition='MachineToApplication' error, and you have done everything to ensure you have a virtual directory set up with an application, check the rest of the tree to make sure you don't have a friggin' backup web.config file screwing things up. 

Tuesday, 07 March 2006 15:50:17 (Eastern Standard Time, UTC-05:00)   #     Comments [7]  | 
Monday, 06 March 2006
I have a number of code libraries I have created or inherited.  As time allows or urgency requires I am busily converting them into .NET 2.0 projects.  For the most part this is straightforward, but every now and again I run into something interesting that requires a little more digging/coding/swearing.

Today I discovered the XslTransform class has been deprecated in 2.0.  Since I do a fair amount of work with XSLT I decided I should pay attention to the little compilier warning Visual Studio was kind enough to generate and see what I should be using instead.  The new preferred class is XslCompiledTransform and Microsoft has also generated handy guides for using the new beast and to migrating your old XslTransform code.  Clearly there was a fairly meaty change made, so time to do some reading.

The documentation promises increased performance and also states "The new XSLT processor compiles the XSLT style sheet down to a common intermediate format, similar to what the common language runtime (CLR) does for other programming languages. Once the style sheet is compiled, it can be cached and reused."  Very interesting.  I will have to do some side-to-side comparison tests for performance at some point, but what do I have to do now to get my old code using XslCompiledTransform?

The function I need to change takes an XML document, calls another function that returns custom XSLT and then uses this to transform the input document and write it to a  string representation of an XML document.  The transformation simply sorts the document based on a number of supplied parameters.  (There is a better way to do this, but I inherited this particular method and it "works".  Also the need for the method will be removed shortly, so I just want to get it work in 2.0.)

Replacing the XslTransform class with XslCompiledTransfrom causes an error in the .Transform call that is the heart of the procedure...
Dim xTrans as XslCompiledTransform
'1.1 overload (IXPathNavigable, XsltArgument,TextWriter, XmlResolver) - Documentation
xTrans.Transform(
InputXMLDoc, Nothing, XMLStringWriter, Nothing)
Looking at the overloads for XslCompiledTransform.Transform reveals that what I want to do is...

'2.0 overload (IXPathNavigable, XsltArgument,TextWriter)
xTrans.Transform(InputXMLDoc, Nothing, XMLStringWriter)

The code wasn't using the
Resolver anyway, which is only used if you need to reference external resources such other DTDs or stylesheet namespaces, which isn't the case here.  If I wanted to use a resolver, I would need to use the one Transform overloads (of 14) that supports it, which requires an XMLReader as an input and an XMLWriter as an output. Fortunately, I don't need to do that much rewriting.  Dropping the unused XmlResolver parm does just what I need.

.NET | XSLT
Monday, 06 March 2006 16:01:38 (Eastern Standard Time, UTC-05:00)   #     Comments [0]  | 
Wednesday, 01 March 2006
I've been seeing everything as base classes lately. Not sure it is a good thing or a sign of insanity.

Had to do some driving of Excel from a web app -- not really something one should do as a matter of course -- but sometimes business requirements force more insanity than usual.

But I decided as long as I was going go insane, I was only going to do it once, so I created a base class that wrapped up all the goodies to open and close a workbook, get cell values, set cell values, etc. Excel exposes everything via COM.  .NET sets up the InterOp automatically, but if you've worked with automating Office apps, you know they are finicky about closing cleanly, so the destructor handles closing the workbook and quiting the app.  Works very nicely.

.NET | Excel | InterOp
Wednesday, 01 March 2006 22:45:02 (Eastern Standard Time, UTC-05:00)   #     Comments [0]  | 

Theme design by Dean Fiala

Pick a theme: