Избегайте жесткого кодирования контроллера и имен действий
ASP.NET MVC, похоже, побуждает меня использовать жестко закодированные строки для обозначения контроллеров и действий.
Например, в контроллере:
return RedirectToAction("Index", "Home");
или, в представлении:
Html.RenderPartial("Index", "Home");
Мне не нужны жестко закодированные строки по всему моему коду. Что я могу сделать, чтобы избежать этого?
Ответы
Ответ 1
Мне кажется, что вы хотите использовать строго типизированные перенаправления. Я создал статический вспомогательный класс под названием RedirectionHelper, который имеет следующий метод:
public static string GetUrl<T>(Expression<Action<T>> action, RequestContext requestContext, RouteValueDictionary values = null) where T : Controller
{
UrlHelper urlHelper = new UrlHelper(requestContext);
RouteValueDictionary routeValues = ExpressionHelper.GetRouteValuesFromExpression(action);
if (values != null)
foreach (var value in values)
routeValues.Add(value.Key, value.Value);
return urlHelper.RouteUrl(routeValues);
}
Единственное предостережение в том, что вам понадобится использовать фьючерсную библиотеку Microsoft.Web.Mvc, доступную в Nuget.
Теперь для вашего контроллера создайте базовый контроллер, который наследует все контроллеры, который имеет этот метод:
protected RedirectResult RedirectToAction<T>(Expression<Action<T>> action, RouteValueDictionary values = null) where T : Controller
{
return new RedirectResult(RedirectionHelper.GetUrl(action, Request.RequestContext, values));
}
Теперь, в вашем действии, все, что вам нужно сделать, это сказать:
return RedirectToAction<Controller>(x => x.Index());
Аналогичным образом вы можете написать метод расширения html, который принимает одни и те же параметры и создает тэг привязки.
Как вы сказали выше, что вы хотели, когда вы меняете имена контроллеров или Action, ваш проект будет ломаться во время компиляции и покажет вам, где происходят перерывы. Однако это произойдет только в контроллерах, поскольку они не компилируются.
Надеюсь, это поможет!
Ответ 2
Посмотрите T4MVC, это порождает классы, поэтому вы можете иметь строго типизированные действия и имена контроллеров. Поскольку это еще только сопоставление с строкой, рефакторинг не приведет к обновлению имен в ваших представлениях, если вы, например, измените имя контроллера.
После восстановления вы получите ошибки компиляции из-за того, что имена исчезают из ваших сгенерированных классов, хотя они по-прежнему полезны при рефакторинге и уловах, которые вы можете пропустить, используя жестко закодированные строки.
Ответ 3
попробуйте T4MVC: http://mvccontrib.codeplex.com/wikipage?title=T4MVC
Ответ 4
Не уверен, что кто-то уже добавил метод расширения в один из проектов ASP.NET MVC, но здесь часть кода, которую вы можете использовать для создания собственного метода расширения:
public RedirectToRouteResult RedirectToAction<TController>(Expression<Action<TController>> action, RouteValueDictionary routeValues) where TController : Controller
{
RouteValueDictionary rv = Microsoft.Web.Mvc.Internal.ExpressionHelper.GetRouteValuesFromExpression(action);
return RedirectToAction((string)rv["Action"], (string)rv["Controller"], routeValues ?? new RouteValueDictionary());
}
public ActionResult Index()
{
return RedirectToAction<DashboardController>(x => x.Index(), null);
}
Нет никаких параметров, объединяющих логику, поэтому вам придется добавлять их самостоятельно.
UPDATE: @mccow002 добавила аналогичное решение за несколько секунд до меня, поэтому я думаю, что его решение должно быть принято.
Ответ 5
Я знаю, что это старая тема, но когда я искал ответ для ASP.NET 5, эта тема впервые появилась.
Больше нет необходимости в hardcode, просто используйте имя
[HttpGet]
public IActionResult List()
{
...
return View();
}
[HttpPost]
public IActionResult Add()
{
...
return RedirectToAction(nameof(List));
}