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

28,728

Solution 1

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());
}

Solution 2

ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
Object value = metadata.Model;
String name = metadata.PropertyName;

Solution 3

I Know this is an old thread but just in case if someone is looking for it, the way to generate id / name attribute is also:

System.Web.Mvc.ExpressionHelper.GetExpressionText(expression);

I'm using this in my extensions and never had any issues with it. It also works great with nested properties.

Solution 4

Simplest way is to wrap it all up in an extension method:

public static class ExtensionMethods
{   

    public static object Value<TModel, TProperty>(this Expression<Func<TModel, TProperty>> expression, ViewDataDictionary<TModel> viewData)
    {
        return ModelMetadata.FromLambdaExpression(expression, viewData).Model;
    }  

}

So the calling syntax is:

expression.Value(htmlHelper.ViewData)

Solution 5

ASP.NET MVC 3 Futures includes a helper for that.

Share:
28,728
Andrew Siemer
Author by

Andrew Siemer

I am currently the Director of Engineering at Volusion, author of several technical and soft skill books, father of 6, and a big friendly guy. I love to ride horses, play with my kids, learn new stuff, teach new stuff, and have fun with life. Moved to Texas in 2010 and stated a sustainable farm where we raise vegetables, egg laying hens, meat birds, and pigs. Books: ASP.NET 3.5 Social Networking ASP.NET MVC Cookbook ASP.NET 4 Social Networking Programmer's Dream Career Sites: LostTechies.com/AndrewSiemer LinkedIn Friendly Pastures Twitter Facebook AndrewSiemer.com

Updated on July 09, 2022

Comments

  • Andrew Siemer
    Andrew Siemer almost 2 years

    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!

  • Andrew Siemer
    Andrew Siemer almost 14 years
    I was mostly interested in this line from the above - var value = ModelMetadata.FromLambdaExpression( expression, htmlHelper.ViewData ).Model; which worked great! I did find that your expression.Name returns null. I swapped that to point to my MemberName method to get that working for the ID. Also, I found that there is a TagBuilder.GenerateId() for adding the ID attribute. Thanks. I will be sure to mention you in my upcoming book (ASP.NET MVC Cookbook - groups.google.com/group/aspnet-mvc-2-cookbook-review)
  • bjan
    bjan almost 12 years
    This will get the name of the Property but not its Value
  • Carlos Miguel Colanta
    Carlos Miguel Colanta almost 8 years
    Hey darin, can you please explain to me this line? var value = ModelMetadata.FromLambdaExpression( expression, htmlHelper.ViewData ).Model;
  • DaEagle
    DaEagle over 7 years
    This is working for me and correctly gets the property name via PropertyName where expression.Name returns null. Edit to add - I'm running MVC5 in case that matters