2010-09-28 14 views
23

Ho una pagina ASP.NET che prende un numero di parametri nella stringa di query:Modificare query Singolo URL valore stringa

search.aspx?q=123&source=WebSearch 

Ciò visualizzare la prima pagina dei risultati di ricerca. Ora all'interno del rendering di quella pagina, voglio visualizzare una serie di collegamenti che consentono all'utente di passare a pagine diverse all'interno dei risultati della ricerca. Posso farlo semplicemente accodamento &page=1 o &page=2 ecc

Dove diventa complicato è che voglio preservare la stringa di query in ingresso dalla pagina originale per tutti i parametri, tranne quello che sto cercando di cambiare. Ci possono essere altri parametri nell'URL utilizzato da altri componenti e il valore che sto cercando di sostituire può o non può già essere definito:

search.aspx?q=123&source=WebSearch&page=1&Theme=Blue 

In questo caso per generare un link alla pagina successiva dei risultati, Voglio cambiare page=1 a page=2 lasciando invariato il resto della stringa di query.

Esiste un modo incorporato per eseguire questa operazione oppure è necessario eseguire manualmente l'analisi/ricombinazione di tutte le stringhe?

risposta

0

Utilizzare l'URIBuilder In particolare la proprietà link text Query

Credo che fa quello che ti serve.

+0

UriBuilder mi permette di cambiare l'intero componente di query della richiesta URL, quello che sto cercando di fare è di cambiare/aggiungere un parametro query specifica all'interno dell'URL. – star

5

Usando questo QueryStringBuilder helper class, si può afferrare la QueryString corrente e chiamare il metodo Add di cambiare una coppia chiave/valore esistente ...

//before: "?id=123&page=1&sessionId=ABC" 
string newQueryString = QueryString.Current.Add("page", "2"); 
//after: "?id=123&page=2&sessionId=ABC" 
+0

Bella risorsa. Grazie! – Mark1270287

+0

La nuova versione utilizza il formato: string newQueryString = QueryString.Current.Add ("page", "2"). ToString(); – Mark1270287

51

Non è possibile modificare la QueryString direttamente in quanto è in sola lettura. Dovrai ottenere i valori, modificarli, quindi rimetterli insieme. Prova questo:

var nameValues = HttpUtility.ParseQueryString(Request.QueryString.ToString()); 
nameValues.Set("page", "2"); 
string url = Request.Url.AbsolutePath; 
string updatedQueryString = "?" + nameValues.ToString(); 
Response.Redirect(url + updatedQueryString); 

Le ParseQueryString method restituisce un NameValueCollection (in realtà in realtà restituisce un HttpValueCollection che codifica i risultati, as I mention in an answer to another question). È quindi possibile utilizzare il metodo Set per aggiornare un valore. È inoltre possibile utilizzare il metodo Add per aggiungerne uno nuovo oppure Remove per rimuovere un valore. Infine, chiamando ToString() sul nome NameValueCollection restituisce le coppie di valori nome in un formato pronto per la querystring name1=value1&name2=value2. Una volta che hai che aggiungerlo all'URL e reindirizzare.

In alternativa, è possibile aggiungere una nuova chiave, o modificare uno esistente, utilizzando l'indicizzatore:

nameValues["temp"] = "hello!"; // add "temp" if it didn't exist 
nameValues["temp"] = "hello, world!"; // overwrite "temp" 
nameValues.Remove("temp"); // can't remove via indexer 

Potrebbe essere necessario aggiungere un using System.Collections.Specialized; di utilizzare la classe NameValueCollection.

+0

In realtà è possibile impostarlo direttamente, la riflessione consente di modificarlo. Personalmente sono d'accordo con l'utilizzo di un NVC però. – annakata

+0

@annakata leggi la tua risposta. Approccio interessante, non la prima cosa che mi verrebbe in mente. –

+0

C'è ancora un problema con il metodo ToString. Gestisce in modo errato le chiavi con più valori. Invece di creare un elenco separato da virgole, duplica coppie chiave = valore. Ad esempio, se hai aggiunto la voce param due volte con valori value1, value2 otterrai risultato param = value1 & param = value2 invece di param = value1, value2. – Stoune

12

È possibile eseguire questa operazione senza tutto il sovraccarico del reindirizzamento (che non è trascurabile). La mia preferenza personale è quello di lavorare con un NameValueCollection cui un querystring è davvero, ma utilizzando la riflessione:

// reflect to readonly property 
PropertyInfo isReadOnly = typeof(System.Collections.Specialized.NameValueCollection).GetProperty("IsReadOnly", BindingFlags.Instance | BindingFlags.NonPublic); 

// make collection editable 
isReadOnly.SetValue(this.Request.QueryString, false, null); 

// remove 
this.Request.QueryString.Remove("foo"); 

// modify 
this.Request.QueryString.Set("bar", "123"); 

// make collection readonly again 
isReadOnly.SetValue(this.Request.QueryString, true, null); 
+0

Questa è una soluzione carina che non ero sicuro se avrebbe funzionato, ma ha fatto il trucco per me. Non potevo davvero permettermi una risposta .redirect basata sulla mia architettura e potrei evitare con questo approccio. Grazie! –

+0

Ricevo l'errore "'PropertyInfo' è un tipo in 'Reflection' e non può essere usato come espressione." – jbyrd

0

Questo è piuttosto arbitraria, in .NET Nucleo almeno.E tutto si riduce a asp-all-route-data

Si consideri il seguente esempio banale (tratto dal modello di vista "paginator" Io uso in quasi tutti i progetti):

public class SomeViewModel 
{ 

    public Dictionary<string, string> NextPageLink(IQueryCollection query) 
    { 
     /* 
     * NOTE: how you derive the "2" is fully up to you 
     */ 
     return ParseQueryCollection(query, "page", "2"); 
    } 

    Dictionary<string, string> ParseQueryCollection(IQueryCollection query, string replacementKey, string replacementValue) 
    { 
     var dict = new Dictionary<string, string>() 
     { 
      { replacementKey, replacementValue } 
     }; 

     foreach (var q in query) 
     { 
      if (!string.Equals(q.Key, replacementKey, StringComparison.OrdinalIgnoreCase)) 
      { 
       dict.Add(q.Key, q.Value); 
      } 
     } 

     return dict; 
    } 
} 

quindi di utilizzare a vostro parere, è sufficiente passare il il metodo corrente di raccolta richiesta di query da Context.Request:

<a asp-all-route-data="@Model.NextPageLink(Context.Request.Query)">Next</a> 
Problemi correlati