public override string ToString()
        {
            StringBuilder sb = new StringBuilder();

            //Message Type
            sb.Append(Type.ToString());
            //Requestid
            sb.Append(String.Format("~{0}", RequestId.ToString()));
            //UnitNumber
            sb.Append(String.Format("~A{0}", UnitNumber));
            //VendorId
            sb.Append(String.Format("~B{0}", VendorName));
            //D-F CardNumber based access
            sb.Append(String.Format("~DCARD~F{0}{1}", CardNumber, SourceAccount));
            //G and H fields Repgen Name / Locator Names
            sb.Append(Type == SymConnectMessageType.RG ? String.Format("~G{0}", Repgen.RepgenName) : String.Empty);
            //H - record locator
            sb.Append(Type == SymConnectMessageType.IQ || Type == SymConnectMessageType.FM ? FormatSourceRecord() : String.Empty);
            //Optional J params for FM
            sb.Append(Type == SymConnectMessageType.FM && FmType != null ? String.Format("~JFMTYPE={0}", (int)FmType.Value) : String.Empty);
            //J Params .. For Repgen calls, this is JRGSESSION, etc. For IQs this is our record locators, for FMs this is our revised fields, for TRS, nothing
            sb.Append(
                Type == SymConnectMessageType.RG
                //RG J params
                    ? Repgen.RepgenParameters.Aggregate(String.Empty,
                                                        (x, y) => x + String.Format("~JRG{0}={1}", y.Key, y.Value)) +
                String.Format("~JRGSESSION={0}", Repgen.RepgenSession)
                //TR, nothing
                    : Type == SymConnectMessageType.TR
                        ? String.Empty
                //IQ source fields
                        : Type == SymConnectMessageType.IQ
                            ? SourceFields.Aggregate(String.Empty, (x, y) => x + String.Format("~J{0}", y))
                //FM fields
                            : Type == SymConnectMessageType.FM
                                ? TargetFields.Aggregate(String.Empty,
                                                         (s, pair) => s + String.Format("~J{0}={1}", pair.Key, pair.Value))
                                : String.Empty);



            return(sb.ToString());
        }
 private void ValidateSymConnectContent()
 {
     //if the repgen name or parameters contain reserved characters, throw an exception
     if (Type == SymConnectMessageType.RG && (ContainsReservedChars(Repgen.RepgenName) ||
                                              Repgen.RepgenParameters.Aggregate(false, (agg, kvp) => agg || ContainsReservedChars(kvp.Key) || ContainsReservedChars(kvp.Value))))
     {
         throw new InvalidOperationException("Repgen name or parameters cannot contain symconnect reserved characters");
     }
     //if any of the source fields contain reserved characters, throw an exception
     if (Type == SymConnectMessageType.IQ && SourceFields.Aggregate(false, (agg, str) => agg || ContainsReservedChars(str)))
     {
         throw new InvalidOperationException("Source fields for iq cannot contain symconnect reserved characters");
     }
     //if any of the target fields contain reserved characters, throw an exception
     if (Type == SymConnectMessageType.FM &&
         TargetFields.Aggregate(false,
                                (agg, kvp) => agg || ContainsReservedChars(kvp.Key) || ContainsReservedChars(kvp.Value)))
     {
         throw new InvalidOperationException("Target fields for fm cannot contain symconnect reserved characters");
     }
 }