Tuesday, December 13, 2011

Automatically set MAXLENGTH on text input fields in ASP.net MVC 3

It seemed to me that ASP.net MVC 3 should know what the max string length is for any given database field and set it in the MAXLENGTH attribute on the corresponding web form.

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

1 comment:

  1. Need to add these usings to global.asax.cs: