10

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
1
  • 1
    I use [Route("api/v{version:apiVersion}/[controller]")] with [ApiVersion("1.0")] Commented Feb 20, 2017 at 18:12

4 Answers 4

28

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.

Sign up to request clarification or add additional context in comments.

2 Comments

I know it's been quite long time ago, but anyway thank you for the answer - it's very helpful. Can you please tell me how to rename controller name, but folder in Views remains in old name?
@svstnv you could try something like this ---- services.Configure<RazorViewEngineOptions>(options => options.ViewLocationFormats.Add("/Views/YourLocation/{0}" + RazorViewEngine.ViewExtension));
10

If you don't want to derive the controller name from the Controller class (Classname minus Controller surfix), then just leave out the [controller] place holder.

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

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

The overloads in HttpGet will set the action name. Doing so however, you can't use generic routes like

routes.MapRoute("default", "api/{controller}/{id?}");

or you have to register them manually there

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

Comments

3

Here is code we are using

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

4 Comments

What is the name of the controller in this case? And could I use it for generating links?
[controller] is a placeholder which will be replaced by the controller class name minus the word "Controller", so "Members".
Yeah but I needed to change the name of the controller, so this doesn't do it.
@grokky - Then fill it in with the name you want i.e. [Route("api/v{version:apiVersion}/Member")]
2

It should be the same way that you would do it in ASP.NET WebAPI2 before Core:

[Route("Bar")]
public IActionResult Foo() { }

If you're looking to do it on the Controller level as well, there's a different attribute for that:

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

Here is a (non-Microsoft) article that goes over how it should be done in .NET Core.

2 Comments

Does it matter when you are doing tag helpers? I have some controllers that "don't make sense", but I've modified the routes to look relevant.
Unfortunately it matters because I'd need to refactor dozens of views. I was hoping for a way to just perform a rename in one place. Also, all the controller's actions already specify a route. I need this specifically to work with tag helpers.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.