¿Cómo enruto una URL con una cadena de consulta en ASP.NET MVC?

Estoy tratando de configurar una ruta personalizada en MVC para tomar una URL de otro sistema en el siguiente formato:

../ABC/ABC01?Key=123&Group=456

El 01 después del segundo ABC es un número de paso que cambiará y los parámetros de clave y grupo cambiarán. Necesito dirigir esto a una acción en un controlador con la tecla numérica del paso y el grupo como parámetros. Intenté el siguiente código pero arroja una excepción:

Código:

 routes.MapRoute( "OpenCase", "ABC/ABC{stepNo}?Key={key}&Group={group}", new {controller = "ABC1", action = "OpenCase"} ); 

Excepción:

 `The route URL cannot start with a '/' or '~' character and it cannot contain a '?' character.` 

No puede incluir la cadena de consulta en la ruta. Pruebe con una ruta como esta:

 routes.MapRoute("OpenCase", "ABC/ABC{stepNo}", new { controller = "ABC1", action = "OpenCase" }); 

Luego, en su controlador agregue un método como este:

 public class ABC1 : Controller { public ActionResult OpenCase(string stepno, string key, string group) { // do stuff here return View(); } } 

ASP.NET MVC mapeará automáticamente los parámetros de cadena de consulta a los parámetros en el método en el controlador.

Al definir rutas, no puede usar un / al comienzo de la ruta:

 routes.MapRoute("OpenCase", "/ABC/{controller}/{key}/{group}", < -- Bad; see / at beginning new { controller = "", action = "OpenCase" }, new { key = @"\d+", group = @"\d+" } ); routes.MapRoute("OpenCase", "ABC/{controller}/{key}/{group}", <-- Good; No / at beginning new { controller = "", action = "OpenCase" }, new { key = @"\d+", group = @"\d+" } ); 

Prueba esto:

 routes.MapRoute("OpenCase", "ABC/{controller}/{key}/{group}", new { controller = "", action = "OpenCase" }, new { key = @"\d+", group = @"\d+" } ); 

Entonces su acción debería verse de la siguiente manera:

 public ActionResult OpenCase(int key, int group) { //do stuff here } 

Parece que estás armando el stepNo y el "ABC" para obtener un controlador que sea ABC1 . Es por eso que reemplacé esa sección de la URL con {controller} .

Como también tiene una ruta que define la "clave" y el "grupo", la ruta anterior también captará su URL inicial y la enviará a la acción.

No hay ninguna razón para usar el enrutamiento basado en querystring en el nuevo proyecto ASP.NET MVC. Puede ser útil para un proyecto antiguo que se haya convertido del clásico proyecto ASP.NET y desee conservar las URL.

Una solución puede ser el enrutamiento de atributos.

Otra solución puede ser escribir el enrutamiento personalizado derivando de RouteBase:

 public class MyOldClassicAspRouting : RouteBase { public override RouteData GetRouteData(HttpContextBase httpContext) { if (httpContext.Request.Headers == null) //for unittest return null; var queryString = httpContext.Request.QueryString; //add your logic here based on querystring RouteData routeData = new RouteData(this, new MvcRouteHandler()); routeData.Values.Add("controller", "..."); routeData.Values.Add("action", "..."); } public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values) { //Implement your formating Url formating here return null; } } 

Y registre su clase de enrutamiento personalizado

 public static void RegisterRoutes(RouteCollection routes) { ... routes.Add(new MyOldClassicAspRouting ()); } 

Los argumentos de cadena de consulta generalmente son específicos de ese controlador y de esa lógica de aplicación específica.

Por lo tanto, será mejor si esto no está escrito en las reglas de ruta, que son generales.

Puede incrustar la detección de cadena de consulta en el argumento de acción de la siguiente manera.

Creo que es mejor tener un Controlador para manejar StepNo.

 public class ABC : Controller { public ActionResult OpenCase(OpenCaseArguments arg) { // do stuff here // use arg.StepNo, arg.Key and arg.Group as You need return View(); } } public class OpenCaseArguments { private string _id; public string id { get { return _id; } set { _id = value; // keep original value; ParseQueryString(value); } } public string StepNo { get; set; } public string Key { get; set; } public string Group { get; set; } private void ParseQueryString(string qs) { var n = qs.IndexOf('?'); if (n < 0) return; StepNo = qs.Substring(0, n); // extract the first part eg. {stepNo} NameValueCollection parms = HttpUtility.ParseQueryString(qs.Substring(n + 1)); if (parms.Get("Key") != null) Key = parms.Get("Key"); if (parms.Get("Group") != null) Group = parms.Get("Group"); } } 

ModelBinder asigna {id} valor al campo id de OpenCaseArguments. El método set maneja la lógica de división de la querystring.

Y sigue enrutando de esta manera. Tenga en cuenta el enrutamiento obtenga su cadena de consulta en el argumento id.

 routes.MapRoute( "OpenCase", "ABC/OpenCase/{id}", new {controller = "ABC", action = "OpenCase"} ); 

He usado este método para obtener valores clave de múltiples campos en la acción del controlador.