Automatic Property Upgrading
Get rid of SoldierRankLibrary


GetSoldierRank() belongs in the Soldier class. That's what Rank { get; set; } is for.
the Dictionary will be replaced by an enum (see below). An enum does not need be inside of any class. You can use boolean operators on enums ("&lt;", "==", ...)


Use Enum instead of Dictionary


Your dictionary is mimicking an Enum. In other words and Enum
inherently associates a number with a name. And in general using Enum
is preferred over strings.
Make separate OfficerRank and EnlistedRank enums if that works
better.
I like @Nik's answer with "unknown". But I'd make it "0" instead of
"-1". The natural default value of an enum variable is zero.
If the underlying int values matter elsewhere in code just make sure you put the ranks in the desired order.


Soldier Class


Rank and Title appear to be the same thing. Do you really need to refer to the soldier's rank by its underlying (integer) value?
Explicitly set variables in the constructor. We all know default values for .NET types, but you want to convey intent and meaning.
Exhaustively set the entire state in the constructor. Again, intent and meaning.
Rankup() - change name to Promote(). Don't pass in an integer, pass in something that has meaning. We're going to utilize Rank enum so this fills the bill.
RefreshTitle() - obsolete. Rank/Title is the same thing. The Rank enum keeps us from having to deal with a string and an int.
Property mis-use. It makes no sense to have a private Title set and
a public RefreshTitle(). Think of a Property as a method. A lot of existing code goes away simply by using the public get properties.
Override ToString(). Now PrintSoldierInfo() disappears. 


New Code

public enum Rank {undefined, BuckPrivate, Sergeant, Lieutenant, Captain}

public class Soldier {
    public string   Name { get; protected set; }
    public Rank     Rank { get; protected set; }

    public Soldier (string name) {
        Name = name ?? "No Name";       // null coalescing.
        Rank = Rank.undefined;   // maybe private if enlisted or lieutenant if officer 
    }

    public void Promote (Rank newRank) {
        if ((int)this.Rank &lt; (int)newRank ) this.Rank = newRank;
        // we don't allow Demotion in this method. 
    }

   public override string ToString() {
       Stringbuilder me = new Stringbuilder();  // need to import System.Text to use Stringbuilder

// C# string formatting avoids clumsy string concatination; clearer and less error prone
       me.AppendLine("Name: {0}  Rank: {1}", Name,Rank); 

       return me.ToString();  // Stringbuilder must be converted to a string.
   }
}


Using Soldier

Soldier grunt = new Soldier("Sad Sack");
grunt.Promote(Rank.Sergeant);
Console.WriteLine (grunt); // ToString() is automagically called.