扩展方法来获取不带后缀的控制器名称

时间:2019-02-05 16:43:18

标签: c# asp.net-core

我不想重复以下内容

nameof(HomeController).Replace(nameof(Controller), string.Empty)

每次我都需要提供不带后缀“ Controller”的控制器名称。

有什么优雅的方法可以简化吗?我试图按如下方法创建扩展方法,但我不知道如何从cshtml视图获取有问题的控制器实例。

using Microsoft.AspNetCore.Mvc;

namespace WebApplication1
{
    public static class Utilities
    {
        public static string BareName(this Controller controller)
        {
            return nameof(controller.GetType).Replace(nameof(Controller), string.Empty);
        }
    }
}

例如,我想在视图页面中调用以下内容。

@Html.ActionLink("something", nameof(HomeController.someaction), nameof(HomeController).Replace(nameof(Controller), string.Empty))

5 个答案:

答案 0 :(得分:5)

您可以在ActionContext上创建一个单独的扩展方法,以从ActionDescriptor解析控制器名称。

public static string GetControllerName(this ActionContext actionContext)
{
    return (actionContext.ActionDescriptor as ControllerActionDescriptor)?.ControllerName;
}

在这种情况下,您不需要修剪字符串中的“控制器”部分。在您的视图中这样调用它:

var controllerName = ViewContext.GetControllerName();

答案 1 :(得分:2)

假设您想要当前未处理请求的控制器的名称,则需要这样的内容:

public static string BareName<T>() where T: Controller
{
    return typeof(T).Name.Replace(nameof(Controller), string.Empty);
}

然后您可以像这样使用它:

@Html.ActionLink("something", nameof(HomeController.someaction), Utilities.BareName<HomeController>())

我仍然不确定为什么微软没有将其作为ASP.NET Core核心软件包的一部分...

答案 2 :(得分:2)

如果您在视图中,只需使用ViewContext.RouteData.Values["controller"]

更新(基于已编辑的问题)

所以,是的,您实际想要实现的目标尚不清楚。基本上,您希望能够在不使用硬编码字符串的情况下指定诸如Html.Action之类的方法的控制器/操作参数。就扩展方法而言,最好的选择是IHtmlHelper扩展,例如:

public static class IHtmlHelperExtensions
{
    public static string GetControllerName<TController>(this IHtmlHelper helper)
        where TController : Controller
    {
        return typeof(TController).GetName().Replace("Controller", "");
    }
}

然后您可以像这样使用

Html.GetControllerName<HomeController>()

但是,这仍然让我感到笨拙。老实说,如果您希望避免对代码进行硬编码,建议您命名路由并使用静态类来存储名称:

public static class RouteNames
{
    public const string Home = "Home";
}

然后:

public class HomeController : Controller
{
    [HttpGet("", Name = RouteNames.Home)]
    public IActionResult Index() => View();
}

然后终于:

@Html.RouteLink(RouteNames.Home, RouteNames.Home)

或通过标签助手:

<a asp-route="@RouteNames.Home">@RouteNames.Home</a>

答案 3 :(得分:0)

如果要在视图或控制器中获取控制器,动作或区域名称,请使用以下选项:

您只需要引用ViewContextHttpContextIHtmlHelper对象:

////////////////////////////////
// with an IHtmlHelper object //
////////////////////////////////
var request = htmlHelper.ViewContext.HttpContext.Request;
var controllerName = request.RouteValues["controller"].ToString();
var actionName = request.RouteValues["action"].ToString();
// if area exists
var areaName = request.RouteValues["area"].ToString();

//////////////////////////////////
// with an `ViewContext` object //
//////////////////////////////////
var controllerName = ViewContext.RouteData.Values["controller"].ToString();
var actionName = ViewContext.RouteData.Values["action"].ToString();
// if area exists
var areaName = ViewContext.RouteData.Values["area"].ToString();

因此,IHtmlHelper的扩展方法如下:

public static class IHtmlHelperExtensions
{
    public static string GetControllerName(this IHtmlHelper htmlHelper) =>
        htmlHelper.ViewContext.RouteData.Values["controller"].ToString();
}

答案 4 :(得分:-1)

[HttpGet]
public IActionResult Get([FromRoute]string controller)
{ 
    //controller will be Controller name without suffix "Controller".
}