覆盖 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
属性是错误的。
类似 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
属性是错误的。