erichexter / twitter.bootstrap.mvc

nuget package to make bootstrap easy with mvc4
Apache License 2.0
248 stars 134 forks source link

BeginControlGroupFor doesn't always identify property names from an expression #85

Open roryprimrose opened 11 years ago

roryprimrose commented 11 years ago

Sorry, Github still 404's when trying to edit online.

src/Bootstrap/BootstrapSupport/ControlGroupExtensions.cs does not correctly determine property names for some data types. For example, we pass in a DateTime which does not get handled correctly. The outcome is that validation styling is not correct because ExpressionHelper.GetExpressionText on line 34 does not identify the property.

The issue is that the expression contains a Convert expression type that GetExpressionText does not cater for.

This is my fix replacing lines 33-35.

    public static IHtmlString BeginControlGroupFor<T>(this HtmlHelper<T> html,Expression<Func<T, object>> modelProperty,IDictionary<string, object> htmlAttributes){
        string propertyName = ExpressionHelper.GetExpressionText(modelProperty);

        if (string.IsNullOrEmpty(propertyName))
        {
            // There may be a cast/Convert in the expression
            // ExpressionHelper.GetExpressionText does not support parsing these out
            propertyName = GetPropertyName(modelProperty);
        }

        return BeginControlGroupFor(html, propertyName, htmlAttributes);
    }

    private static string GetPropertyName<T>(Expression<Func<T, object>> propertyRefExpr)
    {
        return GetPropertyNameCore(propertyRefExpr.Body);
    }

    private static string GetPropertyNameCore(Expression propertyRefExpr)
    {
        // NOTE:  Code taken from http://ivanz.com/2009/12/04/how-to-avoid-passing-property-names-as-strings-using-c-3-0-expression-trees/
        if (propertyRefExpr == null)
        {
            return string.Empty;
        }

        MemberExpression memberExpr = propertyRefExpr as MemberExpression;
        if (memberExpr == null)
        {
            UnaryExpression unaryExpr = propertyRefExpr as UnaryExpression;
            if (unaryExpr != null && unaryExpr.NodeType == ExpressionType.Convert)
                memberExpr = unaryExpr.Operand as MemberExpression;
        }

        if (memberExpr != null && memberExpr.Member != null && memberExpr.Member.MemberType == MemberTypes.Property)
            return memberExpr.Member.Name;

        return string.Empty;
    }