The end result of what I am trying to do is build a form dynamically by reflecting an object and it's properties.
I've created HtmlHelper methods that call TextBoxFor and CheckBoxFor and so on, but now I need help figuring out how to properly reflect the property when passing it to Html.TextBoxFor
Here's the helper method:
public static MvcHtmlString FormTextBox<TModel>(this HtmlHelper<TModel> helper, String id, String property_name, object model, RouteValueDictionary attributes)
{
Type model_type = model.GetType();
return helper.TextBoxFor(model_object => model_type.InvokeMember(property_name, BindingFlags.ExactBinding | BindingFlags.GetProperty, null, model, null));
}
But it breaks on the return with this error code:
Templates can be used only with field access, property access, single-dimension array index, or single-parameter custom indexer expressions.
Basically I want to take what would be this:
@Html.TextBoxFor(model => model.Name)
And turn it into this:
@FormHelpers.FormTextBox("Name", model)
And have it output the same thing.
UPDATE
I will restate this, as I have made some progress in solving the problem.
I've created an Expression from Expression.PropertyOrField that creates exactly what I am looking for. However I can't get the TextBoxFor function to accept it.
Expression fieldExpr = Expression.PropertyOrField(Expression.Constant(model),property_name);
return helper.TextBoxFor(Expression.Lambda<Func<TModel>>(fieldExpr, null).Compile()());
Any ides on how to properly pass the Expression to the function?
Ok, I solved this problem by building a lambda expression using the property name and the type of the object being passed in using the library System.Linq.Expressions
.
ParameterExpression fieldName = Expression.Parameter(typeof(object), property_name);
Expression fieldExpr = Expression.PropertyOrField(Expression.Constant(model), property_name);
Expression<Func<TModel, object>> exp = Expression.Lambda<Func<TModel, object>>(fieldExpr, fieldName);
return helper.TextBoxFor(exp);
Example:
@{ Name myname = new Name();}
@Html.FormTextBox("first", myname)
fieldName builds an expression for the left hand side (first) and then fieldExpr builds the body of the expression with the class name and property name.
exp ends up looking like this:
first => value(DynamicForm.Models.Name).first