Cómo asegurarse de que el controlador y la acción existan antes de redirigir, asp.net mvc3

En uno de mis pares de controlador + acción, obtengo los valores de otro controlador y acción como cadenas de algún lugar y quiero redirigir mi acción actual. Antes de hacer una redirección, quiero asegurarme de que exista una acción de controlador + en mi aplicación, de lo contrario, redirigir a 404. Estoy buscando una forma de hacerlo.

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 }); } 

Todo lo que he hecho es esto, pero no funciona.

 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 } 

Puede implementar IRouteConstraint y usarlo en su tabla de rutas.

La implementación de esta restricción de ruta puede utilizar la reflexión para verificar si existe un controlador / acción. Si no existe se omitirá la ruta. Como última ruta en su tabla de rutas, puede establecer una que atrape todas y asignarla a la acción que muestre la vista 404.

Aquí hay algunos fragmentos de código para ayudarte a comenzar:

 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; } } 

Tenga en cuenta que debe usar el nombre completo del controlador.

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 ); 

Si no puede obtener el nombre completo del controlador para pasarlo a GetType (), deberá usar GetTypes () y luego realizar una comparación de cadenas sobre los resultados.

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

La reflexión es una operación costosa.

Realmente debe probar estos métodos de forma unitaria para asegurarse de que estén redirigiendo a la acción y al controlador adecuados.

Por ejemplo (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"); }