Reputation: 18059
I have the following code I have created to try and get rid of any magic strings related to MVC Action names. Potentially a dev could change the access mutator and access this in a page too.
private const string IndexAction = "Index";
public ActionResult Index(){
//do stuff
}
public ActionResult Other(){
// do stuff
if(foo)
return RedirectToAction(IndexAction);
//don't foo
}
I have never seen this anywhere which leads me to that it is not a good idea and in the world of programming I doubt I am the first person to try this. Question: Is putting the name of the action bad practice does it break any principal of MVC.
Upvotes: 4
Views: 1350
Reputation: 3381
The nameof feature in C# allows you to do this easily. Your RedirectToAction call would look like this:
return RedirectToAction(nameof(Index));
nameof(Index) returns the string "Index". If you accidently change the name of the Index function, then this line would produce a compiler error. Plus doing a rename refactor on Index would change this too, and a Find All References command would point to it as well. But if you want to redirect to a method in a different controller, then this would not work so well.
Upvotes: 1
Reputation: 21
What sometimes do is create an Enum with the action names in a given controller like so:
public class HomeController : Controller
{
public enum Actions
{
Index,
About,
Contact,
Hosting,
Hartware
}
and I create an Extension method in and use the same namespace as the original class that I would like to extend, in this case I would use System.Web.Mvc and create the following class
namespace System.Web.Mvc
{
public static class MvcExtentions
{
/// <summary>
/// Generates a fully qualified URL to an action method by using the specified action Name.
/// </summary>
/// <param name="sender">used for the generate the logic</param>
/// <param name="actionName">an enum that will be used to generate the name from</param>
/// <returns>a fully qualified url to the action in the current controller</returns>
public static string Action(this UrlHelper sender, Enum actionName)
{
return sender.Action(actionName.ToString());
}
}
}
Then in my Razor ViewPage add the Using to get to the in this case "HomeController" on the top of my page where ByteStream is the name of my project
@using ByteStream.Web.Controllers
@{
ViewData["Title"] = "Home Page";
}
To generate the link I then use
<a class="btn btn-default btn-default" ref="@Url.Action(HomeController.Actions.Hosting))">
Learn More
</a>
Upvotes: 2
Reputation: 22511
Basically it's a good idea to use constants (though from my experience it is uncommon in MVC - and maybe also not needed if your controllers are small). By the way you suggest, you reduce the number of spots you have to change from potentially several to two.
If you want to reduce it to just one spot, you can also use the ActionName-attribute to assign the name of the action also by using the constant. This breaks the conventions that are used in MVC and therefore others might take longer to understand the system, but has the advantage to limit the changes to one spot:
private const string IndexAction = "Index";
[ActionName(IndexAction)]
public ActionResult Index(){
//do stuff
}
public ActionResult Other(){
// do stuff
if(foo)
return RedirectToAction(IndexAction);
//don't foo
}
For details on the ActionName attribute and its purpose, see this question and its answer.
Upvotes: 4