Reputation: 22222
The newly introduced nameof
operator is useful in making my code my "typed".
Instead of
return RedirectToAction("Edit");
we can write
return RedirectToAction(nameof(Edit));
But for to get a controller's name is not that straightforward, because we have a Controller
suffix. Just want to know if I want to have a
return RedirectToAction(nameof(Index), controllernameof(Home));
to take the place of
return RedirectToAction("Index", "Home");
how can we implement the controllernameof
operator?
Upvotes: 40
Views: 10418
Reputation: 874
Based on @Trương Quốc Khánh answer, I've modified the extension method by adding some checks:
public static class StringExtensions
{
public static string ControllerName(this string controllerName)
{
if (!controllerName.EndsWith("Controller") || controllerName == "Controller")
throw new ArgumentException($"{controllerName} is not a valid name for a Controller class");
return controllerName.Substring(0, controllerName.LastIndexOf("Controller"));
}
}
Usage:
nameof(Controller).ControllerName()
Upvotes: 0
Reputation: 61
In C# 8 and later you can use the range operator to remove the last 10 chars:
nameof(AccountController)[..^10]
The 10 can be replaced with a constant, if you’re not into the whole brevity thing.
Upvotes: 5
Reputation: 1108
To achieve this kind of thing, I took @stephen.vakil's answer, merged with @huysentruitw's answer and wrote this:
namespace Helpers
{
public static class ControllerHelper
{
public static string Nameof<TController>() where TController : Controller
{
var name = typeof(TController).Name;
var indexOfControllerText = name.LastIndexOf("Controller");
if (indexOfControllerText > 0)
{
return name.Substring(0, indexOfControllerText);
}
return name;
}
}
}
To use this, first you have to add "using static"
using static Helpers.ControllerHelper;
And then use it in the code like this
var controllerName = Nameof<TestController>();
Upvotes: 2
Reputation: 567
public class BaseController : Controller
{
public RedirectToRouteResult RedirectToAction<T>(string ActionName, object routeValues) where T : BaseController
{
string controllerName = typeof(T).Name;
controllerName = controllerName.Substring(0, controllerName.LastIndexOf("Controller"));
return RedirectToAction(ActionName, controllerName, routeValues);
}
public RedirectToRouteResult RedirectToAction<T>(string ActionName) where T : BaseController
{
return RedirectToAction<T>(ActionName, null);
}
}
Used like so:
return RedirectToAction<AccountController>(nameof(AccountController.Login));
return RedirectToAction<AccountController>(nameof(AccountController.Login), new { text= "searchtext" });
Extension for razor page:
public static string ControllerName(this string controllerName)
{
return controllerName.Substring(0, controllerName.LastIndexOf("Controller"));
}
Which you can use like this:
nameof(AccountController).ControllerName()
Upvotes: 3
Reputation: 1637
Totally understand your desire to not use magic strings! Between the comments above and this article. I've started using the following in a base controller which my other controllers inherit from:
public RedirectToRouteResult RedirectToAction<TController>(Expression<Func<TController, string>> expression, object routeValues)
{
if (!(expression.Body is ConstantExpression constant))
{
throw new ArgumentException("Expression must be a constant expression.");
}
string controllerName = typeof(TController).Name;
controllerName = controllerName.Substring(0, controllerName.LastIndexOf("Controller"));
return RedirectToAction(constant.Value.ToString(), controllerName, routeValues);
}
public RedirectToRouteResult RedirectToAction<TController>(Expression<Func<TController, string>> expression)
{
return RedirectToAction(expression, null);
}
I then use :
return RedirectToAction<HomeController>(a => nameof(a.Index));
and
return RedirectToAction<HomeController>(a => nameof(a.Index), new { text= "searchtext" });
Upvotes: 8
Reputation: 62137
No, there is no such possibility. You might be intertested to use T4MVC
instead.
T4MVC
- a T4 template forASP.NET MVC
apps that creates strongly typed helpers that eliminate the use of literal strings in many places.e.g. instead of
@Html.ActionLink("Dinner Details", "Details", "Dinners", new { id = Model.DinnerID }, null)
T4MVC
lets you write@Html.ActionLink("Dinner Details", MVC.Dinners.Details(Model.DinnerID))
Upvotes: 8
Reputation: 59
The solution that solves the case of the XControllerController would look more like:
String nameStr = nameof(FlightControllerController);
nameStr = nameStr.Substring(0, nameStr.LastIndexOf("Controller"));
Upvotes: 5
Reputation: 3540
Maybe an extension method like the following would suit your needs:
public static class ControllerExtensions
{
public static string ControllerName(this Type controllerType)
{
Type baseType = typeof(Controller);
if (baseType.IsAssignableFrom(controllerType))
{
int lastControllerIndex = controllerType.Name.LastIndexOf("Controller");
if (lastControllerIndex > 0)
{
return controllerType.Name.Substring(0, lastControllerIndex);
}
}
return controllerType.Name;
}
}
Which you could invoke like so:
return RedirectToAction(nameof(Index), typeof(HomeController).ControllerName());
Upvotes: 10