Search code examples
asp.net-mvcrecursionlambdaextension-methodshtml-helper

What is the easiest way to get the property value from a passed lambda expression in an extension method for HtmlHelper?


I am writing a dirty little extension method for HtmlHelper so that I can say something like HtmlHelper.WysiwygFor(lambda) and display the CKEditor.

I have this working currently but it seems a bit more cumbersome than I would prefer. I am hoping that there is a more straight forward way of doing this.

Here is what I have so far.

public static MvcHtmlString WysiwygFor<TModel, TProperty>(this HtmlHelper<TModel> helper, Expression<Func<TModel, TProperty>> expression)
{
    return MvcHtmlString.Create(string.Concat("<textarea class=\"ckeditor\" cols=\"80\" id=\"",
                                        expression.MemberName(), "\" name=\"editor1\" rows=\"10\">", 
                                        GetValue(helper, expression),
                                        "</textarea>"));
}

private static string GetValue<TModel, TProperty>(HtmlHelper<TModel> helper, Expression<Func<TModel, TProperty>> expression)
{
    MemberExpression body = (MemberExpression)expression.Body;
    string propertyName = body.Member.Name;
    TModel model = helper.ViewData.Model;
    string value = typeof(TModel).GetProperty(propertyName).GetValue(model, null).ToString();
    return value;
}

private static string MemberName<T, V>(this Expression<Func<T, V>> expression)
{
    var memberExpression = expression.Body as MemberExpression;
    if (memberExpression == null)
            throw new InvalidOperationException("Expression must be a member expression");

    return memberExpression.Member.Name;
}

Thanks!


Solution

  • Try like this:

    public static MvcHtmlString Try<TModel, TProperty>(
        this HtmlHelper<TModel> htmlHelper, 
        Expression<Func<TModel, TProperty>> expression
    )
    {
        var builder = new TagBuilder("textarea");
        builder.AddCssClass("ckeditor");
        builder.MergeAttribute("cols", "80");
        builder.MergeAttribute("name", "editor1");
        builder.MergeAttribute("id", expression.Name); // not sure about the id - verify
        var value = ModelMetadata.FromLambdaExpression(
            expression, htmlHelper.ViewData
        ).Model;
        builder.SetInnerText(value.ToString());
        return MvcHtmlString.Create(builder.ToString());
    }