MVC ActionLink aggiunge tutti i parametri (opzionali) dall’URL corrente

Il famosissimo ActionLink :

   

Ora, questo collegamento è nella mia vista Dettagli. La vista indice è una pagina di ricerca. L’URL di questo assomiglia a questo:

 http://localhost:50152/2011-2012/Instelling/Details/76?gemeente=Dendermonde&postcode=92**&gebruikerscode=VVKSO114421&dossiernr=114421%20&organisatie=CLB 

Come puoi vedere, abbastanza la quantità di parametri. Ovviamente voglio mantenere tutti questi parametri quando torno alla pagina Index, quindi ho bisogno di aggiungerli in ActionLink .

Ora, sono stanco di farlo manualmente, va bene per 1, ma non per 6. Questo dovrebbe andare molto più facile.

Domanda: Come posso restituire tutti i parametri dell’URL corrente in ActionLink come RouteValues opzionali.

Ho cercato di Request.QueryString . Deve essere qualcosa con quello. Stavo pensando di scrivere un metodo statico in Global.asax facendo il lavoro ma ancora senza fortuna. Forse c’è un modo semplice per fare ciò che non conosco?

Modifica: questo è quello che mi è venuto in mente (che funziona)

In global.asax:

  public static RouteValueDictionary optionalParamters(NameValueCollection c) { RouteValueDictionary r = new RouteValueDictionary(); foreach (string s in c.AllKeys) { r.Add(s, c[s]); } return r; } 

Details.aspx:

   

Dove posso inserire questo codice? non in Global.asax immagino …

Modifica 2:

 using System; using System.Web.Mvc; namespace MVC2_NASTEST.Helpers { public static class ActionLinkwParamsExtensions { public static MvcHtmlString CustomLink(this HtmlHelper helper, string linktext) { //here u can use helper to get View context and then routvalue dictionary var routevals = helper.ViewContext.RouteData.Values; //here u can do whatever u want with route values return null; } } }  ...  

È così che ho finalmente risolto il problema, e sono piuttosto orgoglioso perché funziona molto bene e molto ASCIUTTO.

La chiamata nella vista:

  <%: Html.ActionLinkwParams("Back to List", "Index")%> 

ma con i sovraccarichi può essere qualsiasi cosa che un normale ActionLink richiede.

The Helper:

L’helper prende tutti i parametri dall’URL che non si trovano nella rotta. Ad esempio: questo URL:

 http://localhost:50152/2011-2012/myController/Details/77?postalCode=9***&org=CLB 

Quindi prenderà il codice postale e l’Org e lo inserirà nel nuovo ActionLink. Con il sovraccarico, è ansible aggiungere ulteriori parametri e rimuovere i parametri dall’URL esistente.

 using System; using System.Web.Mvc; using System.Web.Routing; using System.Collections.Specialized; using System.Collections.Generic; namespace MVC2_NASTEST.Helpers { public static class ActionLinkwParamsExtensions { public static MvcHtmlString ActionLinkwParams(this HtmlHelper helper, string linktext, string action, string controller, object extraRVs, object htmlAttributes) { NameValueCollection c = helper.ViewContext.RequestContext.HttpContext.Request.QueryString; RouteValueDictionary r = new RouteValueDictionary(); foreach (string s in c.AllKeys) { r.Add(s, c[s]); } RouteValueDictionary htmlAtts = new RouteValueDictionary(htmlAttributes); RouteValueDictionary extra = new RouteValueDictionary(extraRVs); RouteValueDictionary m = Merge(r, extra); return System.Web.Mvc.Html.LinkExtensions.ActionLink(helper, linktext, action, controller, m, htmlAtts); } public static MvcHtmlString ActionLinkwParams(this HtmlHelper helper, string linktext, string action) { return ActionLinkwParams(helper, linktext, action, null, null, null); } public static MvcHtmlString ActionLinkwParams(this HtmlHelper helper, string linktext, string action, string controller) { return ActionLinkwParams(helper, linktext, action, controller, null, null); } public static MvcHtmlString ActionLinkwParams(this HtmlHelper helper, string linktext, string action, object extraRVs) { return ActionLinkwParams(helper, linktext, action, null, extraRVs, null); } public static MvcHtmlString ActionLinkwParams(this HtmlHelper helper, string linktext, string action, string controller, object extraRVs) { return ActionLinkwParams(helper, linktext, action, controller, extraRVs, null); } public static MvcHtmlString ActionLinkwParams(this HtmlHelper helper, string linktext, string action, object extraRVs, object htmlAttributes) { return ActionLinkwParams(helper, linktext, action, null, extraRVs, htmlAttributes); } static RouteValueDictionary Merge(this RouteValueDictionary original, RouteValueDictionary @new) { // Create a new dictionary containing implicit and auto-generated values RouteValueDictionary merged = new RouteValueDictionary(original); foreach (var f in @new) { if (merged.ContainsKey(f.Key)) { merged[f.Key] = f.Value; } else { merged.Add(f.Key, f.Value); } } return merged; } } } 

Nella vista utilizzando sovraccarichi:

  <%: Html.ActionLinkwParams("Back to List", "Index","myController", new {testValue = "This is a test", postalCode=String.Empty}, new{ @class="test"})%> 

nell’URL ho i paramters codice postale con qualche valore. il mio codice li prende tutti nell’URL, impostandolo su string.Empty, rimuovo questo parametro dalla lista.

Commenti o idee sono ben accetti per ottimizzarlo.

Creare un metodo di estensione ToRouteValueDictionary () per Request.QueryString per utilizzare Html.ActionLink così com’è e semplificare il markup della vista:

 <%: Html.ActionLink("Back to List", "Index", Request.QueryString.ToRouteValueDictionary())%> 

Il tuo metodo di estensione potrebbe assomigliare a questo:

 using System.Web.Routing; using System.Collections.Specialized; namespace MyProject.Extensions { public static class CollectionExtensions { public static RouteValueDictionary ToRouteValueDictionary(this NameValueCollection collection) { var routeValueDictionary = new RouteValueDictionary(); foreach (var key in collection.AllKeys) { routeValueDictionary.Add(key, collection[key]); } return routeValueDictionary; } } } 

Per utilizzare il metodo di estensione nella tua vista, vedi questa domanda e risposta: Come utilizzo un metodo di estensione in una vista MVC ASP.NET?

Questo è più semplice e richiede molto meno codice rispetto alla risposta accettata.

Ecco un metodo di estensione per ViewContext che crea un RouteValueDictionary basato sui valori di instradamento della richiesta e querystring.

 using System.Collections.Specialized; using System.ComponentModel; using System.Linq; using System.Web.Mvc; using System.Web.Routing; namespace MyMvcApplication.Utilities { public static class ViewContextExtensions { ///  /// Builds a RouteValueDictionary that combines the request route values, the querystring parameters, /// and the passed newRouteValues. Values from newRouteValues override request route values and querystring /// parameters having the same key. ///  public static RouteValueDictionary GetCombinedRouteValues(this ViewContext viewContext, object newRouteValues) { RouteValueDictionary combinedRouteValues = new RouteValueDictionary(viewContext.RouteData.Values); NameValueCollection queryString = viewContext.RequestContext.HttpContext.Request.QueryString; foreach (string key in queryString.AllKeys.Where(key => key != null)) combinedRouteValues[key] = queryString[key]; if (newRouteValues != null) { foreach (PropertyDescriptor descriptor in TypeDescriptor.GetProperties(newRouteValues)) combinedRouteValues[descriptor.Name] = descriptor.GetValue(newRouteValues); } return combinedRouteValues; } } } 

È ansible passare il RouteValueDictionary creato a Html.ActionLink o Url.Action

 @Html.ActionLink("5", "Index", "Product", ViewContext.GetCombinedRouteValues(new { Page = 5 }), new Dictionary { { "class", "page-link" } }) 

Se il parametro Page non esiste nell’URL della richiesta, verrà aggiunto nell’URL generato. Se esiste, il suo valore sarà cambiato in 5.

Questo articolo ha una spiegazione più dettagliata della mia soluzione.

 public static class Helpers { public static MvcHtmlString CustomLink(this HtmlHelper helper,string LinkText, string actionName) { var rtvals = helper.ViewContext.RouteData.Values; var rtvals2 = helper.RouteCollection; RouteValueDictionary rv = new RouteValueDictionary(); foreach (string param in helper.ViewContext.RequestContext.HttpContext.Request.QueryString.AllKeys) { rv.Add(param, helper.ViewContext.RequestContext.HttpContext.Request.QueryString[param]); } foreach (var k in helper.ViewContext.RouteData.Values) { rv.Add(k.Key, k.Value); } return helper.ActionLink(LinkText, actionName, rv); } } 

ho provato questo e il suo funzionamento. i parametri opzionali possono essere acquisiti dalla stringa di query HTH

Forse il modo migliore è scrivere il proprio helper HTML dove si attraversa il dizionario del valore del percorso precedente e si aggiungono i valori del percorso al link di azione corrente, ad eccezione del parametro di azione fuori rotta.

modifica: puoi scrivere l’helper html in questo modo:

 public static MvcHtmlString CustomLink(this HtmlHelper helper,string linktext) { //here you can use helper to get View context and then routvalue dictionary var routevals = helper.ViewContext.RouteData.Values; //here you can do whatever you want with route values }