Alexander Matusiak
Alexander Matusiak

Reputation: 1828

Best practice on forming links to MVC /controller/actions

I was wondering what the best practice was for specifying an action on a certain controller.

Parts of the code I've been working on are specifying a url as:

<a href="/controller/action"/>

I'm generally not a big fan of this style. I've preferred to use:

<a href='@Url.Action("Action", "Controller")'/>

1) What is the best practice in forming urls for internal actions in this case? Both work, just wondering what is better.

2) Is there a benefit to using one versus the other?

Upvotes: 4

Views: 1289

Answers (4)

Uuuuuumm
Uuuuuumm

Reputation: 656

I created a static class to store all the controller types in my BaseController and I use nameof() for the action to ensure no silent errors from typos or action name changes.

public static class CONTROLLERS
{
    public const string
        Cat = nameof(Cat),
        Dog = nameof(Dog),
        Mouse = nameof(Mouse);
}

So my links would look like this:

<a href="@Url.Action(nameof(CatController.Index), CONTROLLERS.Cat)"></a>

Upvotes: 0

Chris Pratt
Chris Pratt

Reputation: 239390

@hutchonoid sort of touched on this, but virtual paths are just one part of the benefit. While the default route pattern is controller/action/id?, it doesn't have to be that way. Especially if you're using attribute routing in MVC5+, the URL could be literally anything, and may not even include the controller or action name.

By handling all your links using Url.Action or Html.ActionLink, you abstract the view's knowledge of the URL, which is a very good thing. True separation of concerns, which is fundamental to MVC, requires pieces to be as "dumb" as possible, only knowing or caring about the things that it needs to.

If you do end up using attribute routing, I would go a step further and actually recommend naming all your routes, and then using Url.RouteUrl/Html.RouteLink instead of the action-centric versions. This provides even greater abstraction, as you could then have a completely different action or even controller handle that named route, without changing any of your views. You could also technically do this with standard routing, but naming routes with standard routing would require you to manually define each route, instead of relying on a default route or set of default routes.

Upvotes: 2

Erik Philips
Erik Philips

Reputation: 54638

You can also create StronlyTyped ActionLinks if you really wanted too.

@(Html.ActionLink<CustomersController>(x => x.Index(), "Customers"))

Upvotes: 3

hutchonoid
hutchonoid

Reputation: 33306

Of the two options I would say the second is the better approach as it will work with virtual paths/directories:

<a href='@Url.Action("Action", "Controller")'/>

I prefer to use ActionLinks though:

@Html.ActionLink("text", "action", "controller")

Upvotes: 4

Related Questions