ASP.NET MVC 3:有没有办法从类型中获取控制器的字符串名称?

Cod*_*ike 9 .net c# asp.net asp.net-mvc-3

使用UrlHelperMVC3,您可以使用字符串为控制器和操作构建URL:

@Url.Action("Index", "Somewhere")
Run Code Online (Sandbox Code Playgroud)

哪个会将请求路由到SomewhereController.Index().

我想做的是获取控制器和操作的URL,但是传递控制器的类型:

@Url.Action("Index", typeof(SomewhereController))
Run Code Online (Sandbox Code Playgroud)

有没有办法做到这一点?


编辑/澄清:

我意识到控制器的约定是控制器名称路由到一个名为的类,{Name}Controller所以我可以从我的Type.Name的末尾删除'Controller'.我想我假设有一种方法可以通过一些自定义路由覆盖此约定.虽然我看得越多,但我不确定是否可能......

也许MVC3 只能路由到名为"*Controller"的类?我正在通过MVC3源寻找"控制器"硬编码的地方,但还没有找到答案......但是如果可以将"Somewhere"路由到类SomewhereFoo而不是SomewhereController,那么只需删除"Controller"从类名称将是不正确的.

如果某人可以向我提供证据支持或反对"控制器"被硬编码到某个地方的MVC3,那么我会对"从名称中移除控制器"的方法感到更舒服.

tva*_*son 6

没有现有的扩展,但您可以编写自己的扩展,以MvcFutures的ActionLink为模型.我建议使用类似的通用方法@Url.Action<SomewhereController>( c => c.Index )

public static UrlHelperExtensions
{
    public static string Action<TController>( this UrlHelper helper,  Expression<Action<T>> action ) where TController : Controller
    {
        var routeValues = GetRouteValuesFromExpression( action ); 
        return helper.Action( routeValues["action"], routeValues );
    }

    // copied from MvcFutures
    // http://aspnet.codeplex.com/SourceControl/changeset/view/72551#266392
    private static RouteValueDictionary GetRouteValuesFromExpression<TController>(Expression<Action<TController>> action) where TController : Controller
    {
        if (action == null) {
            throw new ArgumentNullException("action");
        }

        MethodCallExpression call = action.Body as MethodCallExpression;
        if (call == null) {
            throw new ArgumentException(MvcResources.ExpressionHelper_MustBeMethodCall, "action");
        }

        string controllerName = typeof(TController).Name;
        if (!controllerName.EndsWith("Controller", StringComparison.OrdinalIgnoreCase)) {
            throw new ArgumentException(MvcResources.ExpressionHelper_TargetMustEndInController, "action");
        }
        controllerName = controllerName.Substring(0, controllerName.Length - "Controller".Length);
        if (controllerName.Length == 0) {
            throw new ArgumentException(MvcResources.ExpressionHelper_CannotRouteToController, "action");
        }

        // TODO: How do we know that this method is even web callable?
        //      For now, we just let the call itself throw an exception.

        var rvd = new RouteValueDictionary();
        rvd.Add("Controller", controllerName);
        rvd.Add("Action", call.Method.Name);
        AddParameterValuesFromExpressionToDictionary(rvd, call);
        return rvd;
    }
}
Run Code Online (Sandbox Code Playgroud)