Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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!

like image 249
Andrew Siemer Avatar asked May 17 '10 05:05

Andrew Siemer


People also ask

How to store a lambda expression in a variable?

The lambda expression should have the same number of parameters and the same return type as that method. Java has many of these kinds of interfaces built in, such as the Consumer interface (found in the java.util package) used by lists. Use Java's Consumer interface to store a lambda expression in a variable:

Is there a better way to get property name from lambda expression?

Is there a better way to get the Property name when passed in via a lambda expression? Here is what i currently have. eg. It worked by casting it as a memberexpression only when the property was a string. because not all properties are strings i had to use object but then it would return a unaryexpression for those. Show activity on this post.

What is lambda expression in Java 8?

1 Java Lambda Expressions. Lambda Expressions were added in Java 8. A lambda expression is a short block of code which takes in parameters and returns a value. 2 Syntax. Expressions are limited. ... 3 Using Lambda Expressions. Lambda expressions can be stored in variables if the variable's type is an interface which has only one method.

What is htmlhelper in HTML5?

The HtmlHelper class renders HTML controls in the razor view. It binds the model object to HTML controls to display the value of model properties into those controls and also assigns the value of the controls to the model properties while submitting a web form.


4 Answers

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());
}
like image 83
Darin Dimitrov Avatar answered Oct 16 '22 08:10

Darin Dimitrov


ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
Object value = metadata.Model;
String name = metadata.PropertyName;
like image 25
Peter Hedberg Avatar answered Oct 16 '22 09:10

Peter Hedberg


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.

like image 10
Ales Potocnik Hahonina Avatar answered Oct 16 '22 09:10

Ales Potocnik Hahonina


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)
like image 5
BigMomma Avatar answered Oct 16 '22 07:10

BigMomma