views:

212

answers:

2

What I'm trying to do is create an extension method for the HtmlHelper to create a specific output and associated details like TextBoxFor<>. What I want to do is specify the property from the model class as per TextBoxFor<>, then an associated controller action and other parameters.

So far the signature of the method looks like:

public static MvcHtmlString Create<TModel, TProperty, TController>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, Expression<Action<TController>> action, object htmlAttributes)
        where TController : Controller
        where TModel : class

The issue occurs when I go to call it. In my view if I call it as per the TextBoxFor without specifying the Model type I am able to specify the lambda expression to set the property which it's for, but when I go to specify the action I am unable to.

However, when I specify the controller type Html.Create<HomeController>( ... ) I am unable to specify the model property that the control is to be created for.

I want to be able to call it like

<%= Html.Create<HomeController>(x => x.Title, controller => controller.action, null) %>

I've been hitting my head for a few hours now on this issue over the past day, can anyone point me in the right direction?

Edit: Thanks for the responses to this.

So without specifying all of the types I think I can live with

<%= Html.Create(x => x.Title, ((HomeController)controller) => controller.action, null) %>

But still need the reference to the action, not the actual action itself

*back to thinking :)

Edit #2:

I'm starting to think trying to make it purely strongly typed is a bit far fetched. Going along the same lines as the provided html helper extension methods maybe just specifying the action name and controller name as string parameters is the way to go?! But surely what I'm trying to do is possible? hits head

A: 

The type parameters can not be inferred. You have no choice but to invoke it like (supposing your TModel is of type Book and the Title is of type string)

<%= Html.Create<Book, string, HomeController>(x=>x.Title, controller=>controller.SomeAction(), null) %>

Otherwise it will not know over which controller it should invoke the action.

Regards.

uvita
Valid point, I've updated the question as I missed one bit. Can it be done to only define the controller type in the angle brackets?
WestDiscGolf
mmm, no you can't. Another way of invoking it would be<%= Html.Create(x=>x.Title, (HomeController controller) => controller.SomeAction(), null) %>
uvita
Was thinking about your response on the drive home, you are passing in the full action (and associated parameters) into the extension method, I just want to pass the reference to the action as I don't know what the value of the parameter(s) will be at this point.
WestDiscGolf
Then why don't you use simply string parameters? one for the controller name and the other for the action. The idea behind using the action delegate is that the rounting engine generates valid url according to your routes.
uvita
The main reason for not using string parameters is that I wanted it to be strongly typed to help with the usual arguments for strongly typing things.
WestDiscGolf
Yes, I know, that's very important. You can pass any parameters to the action (null, 0, string.Empty, etc) and get the method name inside the implementation by the following code: var methodCallExpression = action.Body as MethodCallExpression;var methodName = methodCallExpression.Method.Name;This is all I have!! Good luck! :)
uvita
Thanks for your time and pointers; I will look into these :-) I will post the solution I come up with ... once I've got one ;-) Cheers!
WestDiscGolf
+1  A: 

I think the closest you can get is:

<%= Html.Create(x => x.Title, (HomeController c) => c.Index(), null) %>
Darin Dimitrov