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

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

It works for me now, but it seems a little more bulky than I would prefer. I hope there is a more direct way to do this.

Here is what I still have.

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

Thank!

+43
lambda asp.net-mvc recursion extension-methods html-helper
May 17 '10 at 5:10
source share
6 answers

Try it 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()); } 
+69
May 17 '10 at 8:53 a.m.
source share
 ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData); Object value = metadata.Model; String name = metadata.PropertyName; 
+20
Jun 08 '10 at
source share

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

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

I use this in my extensions and have never had any problems with it. It also works great with nested properties.

+8
Aug 11 '11 at 16:14
source share

The easiest way is to do all this in the 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; } } 

Thus, the syntax of the call is:

 expression.Value(htmlHelper.ViewData) 
+5
Sep 28
source share

ASP.NET MVC 3 Futures contains an assistant for this.

+3
Aug 11 2018-11-18T00:
source share

This is not considered by Peter or BigMomma, but he combines both. If you call this from a controller method, where you do not have access to the HtmlHelper instance, simply create the base controller method as follows:

 public ModelMetadata GetModelMetadata<TModel, TProperty>( TModel model, Expression<Func<TModel, TProperty>> expression ) { ViewData.Model = model; //model is null in Controller; you must set it here (or earlier) in order to extract values from the returned ModelMetadata. return ModelMetadata.FromLambdaExpression( expression, new ViewDataDictionary<TModel>( ViewData ) ); } 

Then you can read what you need from the model metadata, as usual;

 var mm = GetModelMetaData( model, m => m.SomeProperty ); string name = mm.PropertyName; object value = mm.Model; 
+1
May 23 '16 at 21:31
source share



All Articles