Come faccio a instradare un URL con una querystring in ASP.NET MVC?

Sto cercando di impostare un percorso personalizzato in MVC per prendere un URL da un altro sistema nel seguente formato:

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

Il 01 dopo il secondo ABC è un numero di step che cambierà e i parametri Key e Group cambieranno. Ho bisogno di indirizzare questo a un’azione in un controller con il tasto numero di passo e raggruppare come parametri. Ho tentato il seguente codice, tuttavia genera un’eccezione:

Codice:

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

Eccezione:

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

Non è ansible includere la stringa di query nel percorso. Prova con un percorso come questo:

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

Quindi, sul controller aggiungere un metodo come questo:

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

ASP.NET MVC esegue automaticamente il mapping dei parametri della stringa di query ai parametri nel metodo nel controller.

Quando si definiscono i percorsi, non è ansible utilizzare un / all’inizio del percorso:

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

Prova questo:

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

Quindi la tua azione dovrebbe apparire come segue:

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

Sembra che stai mettendo insieme il stepNo e il "ABC" per ottenere un controller che sia ABC1 . Ecco perché ho sostituito quella sezione dell'URL con {controller} .

Poiché hai anche un percorso che definisce la 'chiave' e 'gruppo', il percorso sopra prenderà anche il tuo URL iniziale e lo invierà all'azione.

Non vi è alcun motivo per utilizzare il routing basato su querystring nel nuovo progetto ASP.NET MVC. Può essere utile per il vecchio progetto che è stato convertito dal classico progetto ASP.NET e si desidera conservare gli URL.

Una soluzione può essere il routing degli attributi.

Un’altra soluzione può essere quella di scrivere il routing personalizzato derivando da 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; } } 

E registra la tua class di routing personalizzata

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

Gli argomenti della stringa di query in genere sono specifici di tale controller e di quella specifica logica dell’applicazione.

Quindi sarà meglio se questo non è scritto nelle regole di percorso, che sono generali.

È ansible incorporare il rilevamento della stringa di query sull’argomento azione nel modo seguente.

Penso che sia meglio avere un controller per gestire 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 assegna il valore {id} al campo id di OpenCaseArguments. Il metodo set gestisce la logica split querystring.

E continua a seguire questo percorso. Il routing della nota ottiene la tua querystring nell'argomento id.

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

Ho usato questo metodo per ottenere il valore chiave di più campi sull'azione del controller.