覆盖 ASP.NET 核心中的控制器名称

Override controller name in ASP.NET Core

类似 to this question,但用于新的 ASP.NET 核心。

我可以覆盖动作的路由名称:

[ActionName("Bar")]
public IActionResult Foo() {

我可以使用属性路由为控制器执行此操作吗?

[?("HelloController")]
public SomeController : Controller {

它应该允许使用标签助手生成链接:

<a asp-controller="some" ...      // before
<a asp-controller="hello" ...     // after

它应该与在 Core:

之前的 ASP.NET WebAPI2 中一样
[Route("Bar")]
public IActionResult Foo() { }

如果您也希望在控制器级别执行此操作,则有一个不同的属性:

[RoutePrefix("ControllerFoo")]
public class MyController() { }

Here 是一篇 (non-Microsoft) 文章,介绍了在 .NET Core 中应如何完成。

这是我们使用的代码

[ApiVersion("1.0")]
[Route("api/v{version:apiVersion}/[controller]")]
public class MembersController : Controller { /* */ }

如果您不想从控制器 class 派生控制器名称(类名减去控制器后缀),则只需省略 [controller] 占位符。

[Route("/api/hello")]
public SomeController : Controller {
    [HttpGet]
    public IActionResult Get() { }

    [HttpGet("something")]
    public IActionResult GetSomething() { }
}

HttpGet 中的重载将设置动作名称。但是,这样做,您不能使用像

这样的通用路由
routes.MapRoute("default", "api/{controller}/{id?}");

或者您必须在那里手动注册它们

routes.MapRoute("hello", "api/hello/{id?}", defaults: new { controller = "Hello" });
routes.MapRoute("default", "api/{controller}/{id?}");

这样的属性不存在。但是你可以自己创建一个:

[AttributeUsage(AttributeTargets.Class)]
public class ControllerNameAttribute : Attribute
{
    public string Name { get; }

    public ControllerNameAttribute(string name)
    {
        Name = name;
    }
}

在您的控制器上应用它:

[ControllerName("Test")]
public class HomeController : Controller
{
}

然后创建自定义控制器约定:

public class ControllerNameAttributeConvention : IControllerModelConvention
{
    public void Apply(ControllerModel controller)
    {
        var controllerNameAttribute = controller.Attributes.OfType<ControllerNameAttribute>().SingleOrDefault();
        if (controllerNameAttribute != null)
        {
            controller.ControllerName = controllerNameAttribute.Name;
        }
    }
}

并将其添加到 Startup.cs 中的 MVC 约定中:

services.AddMvc(mvc =>
{
    mvc.Conventions.Add(new ControllerNameAttributeConvention());
});

现在 HomeController 索引操作将在 /Test/Index 响应。 Razor 标签助手属性可以根据需要设置。

唯一的缺点是至少 ReSharper 在 Razor 中有点损坏。它不知道约定,所以它认为 asp-controller 属性是错误的。