Search code examples
c#asp.net-coreasp.net-core-mvcattributerouting

Override controller name in ASP.NET Core


Similar to this question, but for the new ASP.NET Core.

I can override an action's routing name:

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

Can I do that for a controller, using attribute routing?

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

It should allow generation of links using tag helpers:

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

Solution

  • Such an attribute does not exist. But you can create one yourself:

    [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
    public class ControllerNameAttribute : Attribute
    {
        public string Name { get; }
    
        public ControllerNameAttribute(string name)
        {
            Name = name;
        }
    }
    

    Apply it on your controller:

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

    Then create a custom controller convention:

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

    And add it to MVC conventions in Startup.cs:

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

    Now HomeController Index action will respond at /Test/Index. Razor tag helper attributes can be set as you wanted.

    Only downside is that at least ReSharper gets a bit broken in Razor. It is not aware of the convention so it thinks the asp-controller attribute is wrong.