I went looking for a way to get the built-in Html.EditorFor to do it, but didn't find any.
Here's a new helper called "LimitedEditorFor" which automatically adds the correct MAXLENGTH attribute to the text input tag. Call this exactly the same way you would call Html.EditorFor.
 
namespace ExtensionMethods
{
   public static class MyExtensions
   {
     public static MvcHtmlString LimitedEditorFor<TModel, TValue>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TValue>> expression)
     {
       string S = htmlHelper.EditorFor(expression).ToString().Replace("/>", "MAXLENGTH=\"" + GetLengthLimit(expression) + "\"/>");
       return new MvcHtmlString(S);
     }
  
     private static int GetLengthLimit(Expression expression)
     {
       MemberExpression ME = GetMemberInfo(expression);
       Type type = ME.Member.ReflectedType;
       string field = ME.Member.Name;
       PropertyInfo prop = type.GetProperty(field);
       // Find the Linq 'Column' attribute
       // e.g. [Column(Storage="_FileName", DbType="NChar(256) NOT NULL", CanBeNull=false)]
       object[] info = prop.GetCustomAttributes(typeof(ColumnAttribute), true);
  
       if (info.Length != 1) return 0;  // Assume there is just one
  
       ColumnAttribute ca = (ColumnAttribute)info[0];
       string dbtype = ca.DbType;
       if (!dbtype.StartsWith("NChar") && !dbtype.StartsWith("NVarChar")) return 0;
  
       Regex pattern = new Regex("\\((.+)\\)");
       Match m = pattern.Match(dbtype);
       if (!m.Success) return 0;
  
       return Convert.ToInt16(m.Groups[1].Value);
     }
  
     private static MemberExpression GetMemberInfo(Expression method)
     {
       LambdaExpression lambda = method as LambdaExpression; 
       if (lambda == null) throw new ArgumentNullException("method"); 
       MemberExpression memberExpr = null; 
  
       if (lambda.Body.NodeType == ExpressionType.Convert)
       {
         memberExpr = ((UnaryExpression)lambda.Body).Operand as MemberExpression;
       } 
       else if (lambda.Body.NodeType == ExpressionType.MemberAccess)
       {
         memberExpr = lambda.Body as MemberExpression;
       } 
  
       if (memberExpr == null) throw new ArgumentException("method"); 
  
       return memberExpr;
     }
   }
}
This was a huge help: http://joaodepaula.com/articles/columnsizereflection.html
