Override controller name in ASP.NET Core

grokky picture grokky · Feb 20, 2017 · Viewed 10.3k times · Source

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

Answer

juunas picture juunas · Feb 20, 2017

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

[AttributeUsage(AttributeTargets.Class)]
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.