I am trying to change
@{Html.RenderAction("Foo", "TheAction");}
to
@{Html.RenderAction((FooController c) => c.TheAction );}
which is nicer in a lot of ways, it improves:
- F12-navigation
- Type usage detection (resharper etc)
- Method usage detection
- Strictness
- …the possibility to keep dead links away from the project
…so I have written an extension class like this:
using System;
using System.Linq.Expressions;
using System.Reflection;
using System.Text.RegularExpressions;
using System.Web.Mvc;
using System.Web.Mvc.Html;
namespace V3NET.MVC.Extensions
{
public static class HtmlHelperExtension
{
public static void RenderAction<T>
(this HtmlHelper helper, Expression<Func<T, Func<int, int?, ActionResult>>> action)
{
var actionName =
(
(MethodInfo)
(
(ConstantExpression)
(
(MethodCallExpression)
(
((UnaryExpression)action.Body).Operand
)
).Object
).Value
).Name;
var controllerType = action.Parameters[0].Type;
var controllerName = new Regex("Controller$").Replace(controllerType.Name, "");
helper.RenderAction(actionName, controllerName);
}
}
}
…but as you can see, I have to write it specific for an action taking int, int? as arguments.
How do I express this more generally so I dont have to write a zillion of overloads?
You could use
Expression<Action<TController>>.Here’s an improved version of the helper you are trying to write which is taking into account many more scenarios that your helper doesn’t support such as asynchronous controller actions for example. It also adds a generic constraint for the type of the argument to be a Controller: