2011-06-30 28 views
11

ASP.NET MVC似乎是鼓励我使用硬编码字符串是指控制器和动作。避免硬编码控制器和动作名称

例如,在一个控制器:

return RedirectToAction("Index", "Home"); 

,或者在一个视图:

Html.RenderPartial("Index", "Home"); 

我不希望都在我的代码硬编码字符串。我能做些什么来避免这种情况?

+1

没有与此恕我直言没有问题。在某些时候,你必须告诉代码指向一个特定的类或函数。 – Timbo

+2

@Badger问题是如果你重命名你的动作/控制器。然后,您必须以某种方式找到所有硬编码的字符串来更新它们,并且您不能依靠编译器来告诉您,您错过了某些东西。 – Dolbz

+1

ReSharper可以使这个没有问题 – driushkin

回答

13

像你想使用强类型的重定向这听起来我。我做了一个静态辅助类叫做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扩展方法,它接受相同的参数并构建你的锚标签。

就像你在上面,你想,当你改变控制器或者动作名称,你的项目将打破在编译的时候,告诉你该休息发生在哪里说。但是,这只会发生在控制器中,看到视图如何编译。

希望这会有所帮助!

+0

好:)我几秒钟后发布相同的解决方案 –

+0

不错 - 比t4模板搞乱 - 这真的很糟糕 – iwayneo

+0

注意:为此,ExpressionHelper必须是'Microsoft.Web.Mvc .Internal.ExpressionHelper',**不** **'System.Web.Mvc.ExpressionHelper'。 –

5

T4MVC这会产生类,所以你可以有强类型的动作和控制器的名称。因为它仍然只是一个字符串映射,所以如果您更改控制器名称,重构不会导致视图中的名称更新。

再生您将获得由于从生成的类消失,但这样它仍然是有用的重构和捕捉,你可以错过使用硬编码字符串问题的名称编译错误后。

3

不知道是否有人已经添加一个扩展方法到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加入了类似的解决方案我之前几秒钟,所以我认为他的解决办法应该被接受。

0

我知道这是一个老话题,但是当我在寻找一个答案ASP.NET 5这个主题首次出现。 没有必要再进行硬编码,只需用nameof

[HttpGet] 
public IActionResult List() 
{ 
    ... 
    return View(); 
} 

[HttpPost] 
public IActionResult Add() 
{ 
    ... 
    return RedirectToAction(nameof(List)); 
} 
+0

如果某人通过ActionName属性覆盖了操作名称,这将不起作用,例如'[ActionName(“NewActionName”)]' –

+0

@DavidSpence 是的,它也不会像控制器一样工作,你需要实现扩展方法,它将切断“控制器”后缀。但是,这是一些东西。 – Serhii

相关问题