如何在重定向,asp.net mvc3之前确保控制器和操作存在

在我的一个控制器+动作对中,我从另一个地方获取另一个控制器和动作的值作为字符串,我想重定向我当前的动作。 在进行重定向之前,我想确保我的应用程序中存在控制器+操作,如果没有,则重定向到404.我正在寻找一种方法来执行此操作。

public ActionResult MyTestAction() { string controller = getFromSomewhere(); string action = getFromSomewhereToo(); /* At this point use reflection and make sure action and controller exists else redirect to error 404 */ return RedirectToRoute(new { action = action, controller = controller }); } 

我所做的就是这个,但它不起作用。

 var cont = Assembly.GetExecutingAssembly().GetType(controller); if (cont != null && cont.GetMethod(action) != null) { // controller and action pair is valid } else { // controller and action pair is invalid } 

您可以实现IRouteConstraint并在路由表中使用它。

此路由约束的实现可以使用reflection来检查控制器/操作是否存在。 如果它不存在,将跳过该路线。 作为路由表中的最后一个路由,您可以设置一个捕获所有路由并将其映射到呈现404视图的操作。

这里有一些代码片段可以帮助您入门:

 public class MyRouteConstraint : IRouteConstraint { public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection) { var action = values["action"] as string; var controller = values["controller"] as string; var controllerFullName = string.Format("MvcApplication1.Controllers.{0}Controller", controller); var cont = Assembly.GetExecutingAssembly().GetType(controllerFullName); return cont != null && cont.GetMethod(action) != null; } } 

请注意,您需要使用控制器的完全限定名称。

RouteConfig.cs

 routes.MapRoute( "Home", // Route name "{controller}/{action}", // URL with parameters new { controller = "Home", action = "Index" }, // Parameter defaults new { action = new MyRouteConstraint() } //Route constraints ); routes.MapRoute( "PageNotFound", // Route name "{*catchall}", // URL with parameters new { controller = "Home", action = "PageNotFound" } // Parameter defaults ); 

如果无法获取要传递给GetType()的控制器的完全限定名称,则需要使用GetTypes(),然后对结果进行字符串比较。

 Type[] types = System.Reflection.Assembly.GetExecutingAssembly().GetTypes(); Type type = types.Where( t => t.Name == controller ).SingleOrDefault(); if( type != null && type.GetMethod( action ) != null ) 

反思是一项昂贵的操作。

您应该对这些方法进行unit testing,以确保它们重定向到适当的操作和控制器。

例如(NUnit)

 [Test] public void MyTestAction_Redirects_To_MyOtherAction() { var controller = new MyController(); var result = (RedirectToRouteResult)controller.MyTestAction(); Assert.That(result.RouteValues["action"], Is.EqualTo("MyOtherAction"); Assert.That(result.RouteValues["controller"], Is.EqualTo("MyOtherController"); }