【问题标题】:Extension method to get a controller name without suffix获取不带后缀的控制器名称的扩展方法
【发布时间】:2019-02-05 16:43:17
【问题描述】:

我不想重复以下内容

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

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

有什么优雅的方法可以简化吗?我尝试按如下方式创建扩展方法,但我不知道如何从 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))

【问题讨论】:

  • 您不能在控制器的方法中调用this.BareName() 并将返回值添加到传递给te cshtml 视图的ViewBag 吗?
  • @PietroMartinelli:但使用ViewBag 容易出错。

标签: c# asp.net-core


【解决方案1】:

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

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

在这种情况下,您不需要从字符串中删除“控制器”部分。在你的视图中这样称呼它:

var controllerName = ViewContext.GetControllerName();

【讨论】:

  • 这是获取 current 控制器名称的好方法。但是,OP 从他的问题中给人的印象是,他们想要获得任意控制器的名称,因为提到了使用 Html.ActionLink。如果控制器与您当前使用的控制器相同,您甚至不需要传递控制器参数。
【解决方案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 核心包的一部分...

【讨论】:

    【解决方案3】:

    如果您在视图中,只需使用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>
    

    【讨论】:

    • 这不是硬编码。 “控制器”就是你要找的东西。
    【解决方案4】:

    如果您想在视图或控制器中获取控制器、动作或区域名称,这里有一些选项:

    您只需要引用 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();
    }
    

    【讨论】:

      【解决方案5】:
      [HttpGet]
      public IActionResult Get([FromRoute]string controller)
      { 
          //controller will be Controller name without suffix "Controller".
      }
      

      【讨论】:

        【解决方案6】:
        var controllerName = ControllerContext.ActionDescriptor.ControllerName.Replace(nameof(Controller), string.Empty);
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2014-05-11
          • 2020-01-04
          • 1970-01-01
          • 2017-12-10
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2010-12-30
          相关资源
          最近更新 更多