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 mem开发者_如何学JAVAberExpression = expression.Body as MemberExpression;
if (memberExpression == null)
throw new InvalidOperationException("Expression must be a member expression");
return memberExpression.Member.Name;
}
Thanks!
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());
}
ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
Object value = metadata.Model;
String name = metadata.PropertyName;
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.
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)
ASP.NET MVC 3 Futures includes a helper for that.
This isn't addressed by either Peter or BigMomma's answer, but it combines both. If you're calling this from a controller method, where you don't have access to an HtmlHelper instance, just create a base controller method like this:
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;
精彩评论