2009-02-05 9 views
7

Ho notato che il parametro URL returnurl sul collegamento StackOverflow/i collegamenti di logout non sono stati sfuggiti, ma quando provo ad aggiungere il percorso come parametro a un percorso, viene sfuggito.Come lasciare i parametri URL senza caratteri di escape in ASP.NET MVC?

Quindi/login? Returnurl =/questions/ask shows/login? Returnurl =% 2fquestions% 2fask ed è una specie di brutto. Come faccio a ottenere che non sfugga al valore di returnurl?

Ecco quello che sto facendo nel codice:

Html.ActionLink("Login", "Login", "Account", new { returnurl=Request.Path }, null) 
+0

Mi piacerebbe sapere anche la risposta a questo –

risposta

1

Capisco uno dei commenti sulla codifica che si sta verificando per un motivo; questa sarebbe solo un'eccezione, non la regola.

Ecco cosa ho messo insieme, come può essere migliorato?

public static string ActionLinkNoEscape(this HtmlHelper html, string linkText, string actionName, string controllerName, object values, object htmlAttributes) 
    { 
     RouteValueDictionary routeValues = new RouteValueDictionary(values); 
     RouteValueDictionary htmlValues = new RouteValueDictionary(htmlAttributes); 

     UrlHelper urlHelper = new UrlHelper(html.ViewContext.RequestContext, RouteTable.Routes); 
     string url = urlHelper.Action(actionName, controllerName); 
     url += "?"; 
     List<string> paramList = new List<string>(); 
     foreach (KeyValuePair<string, object> pair in routeValues) 
     { 
      object value = pair.Value ?? ""; 
      paramList.Add(String.Concat(pair.Key, "=", Convert.ToString(value, CultureInfo.InvariantCulture))); 
     } 
     url += String.Join("&", paramList.ToArray()); 

     TagBuilder builder = new TagBuilder("a"); 
     builder.InnerHtml = string.IsNullOrEmpty(linkText) ? "" : HttpUtility.HtmlEncode(linkText); 
     builder.MergeAttributes<string, object>(htmlValues); 
     builder.MergeAttribute("href", url); 
     return builder.ToString(TagRenderMode.Normal); 
    } 
+0

Funziona un po 'meglio se si restituisce un MvcHtmlString. –

0

mio solutionto un problema simile è stato quello di scrivere il mio proprio interno. Dopo aver scavato nel codice non sono riuscito a trovare un modo per farlo diversamente. Il tuo potrebbe sembrare così.

public static class HtmlHelperExtensions 
{ 
    public static string LoginLinkWithReturnUrl(this HtmlHelper helper, 
               string linkText, 
               string action, 
               string controller, 
               string returnUrl, 
               object htmlAttributes) 
    { 
     TagBuilder builder = new TagBuilder("a"); 
     builder.Attributes.Add("href", 
            string.Format("/{0}/{1}?returnurl={2}", 
               controller, 
               action, 
               returnUrl)); 
     var attrDict = new RouteValueDictionary(htmlAttributes); 
     builder.MergeAttributes(attrDict); 
     builder.InnerHtml = linkText; 
     return builder.ToString(); 
    } 
} 

Penso di aver avuto lo stesso problema facendo e utilizzando un UrlHelper così sono andato con il meccanismo string.Format invece. YMMV.

+0

L'unico problema è che si sta codificando l'instradamento, il che significa che si interromperà se non si utilizza la rotta predefinita. – JMS

+0

Era solo un esempio dalla cima della mia testa. Probabilmente potresti usare UrlHelper per costruire il percorso dall'azione/controller e quindi aggiungere i parametri di query alla fine di esso. – tvanfosson

6

Come faccio a farlo per non sfugge il valore ReturnURL

Come è su questo?

var url = Url.Action("Login", "Account", new {returnurl = Request.Path}); 
var unEncodedUrl = HttpUtility.UrlDecode(url); 
Response.Write("<a href='" + unEncodedUrl + "'>...</a>"); 

Essere sicuri che è quello che vuoi, però, URL encoding has its purpose.

+1

Soluzione rapida. Potrebbe essere necessario utilizzare @ Html.Raw (unEncodedUrl) se si sta creando qualsiasi contenuto JS –

0

Non credo ci sia un modo intorno ad esso che è costruito nel quadro. La costruzione effettiva dell'URL avviene nel metodo System.Web.Routing.ParsedRoute.Bind e non ci sono condizioni utilizzate per impedire l'escape.

Sembra che un metodo di estensione sia la strada da percorrere, ma una leggermente più robusta di quella menzionata in precedenza.

1

Il parametro è non escape. Noterete l'URL:

http://stackoverflow.com/users/login?returnurl=%2fquestions%2fask 

funziona veramente - così è la lettura e unescaping tale parametro come normale. Se si desidera includere altri caratteri fuori limite come "&" nel parametro, si dovrà comunque scappare da essi.

Il trucco è semplicemente che il carattere "/" in particolare non ha bisogno di essere% -escaped nei parametri di query. È deve essere sfuggito in altri contesti come in una parte del percorso, quindi URLEncode lo codifica sempre, per sicurezza.

Se si desidera che l'URL sia più bello, è sufficiente sfuggire il parametro normalmente (cosa che si deve fare per sfuggire a tutti gli altri caratteri che devono essere gestiti correttamente), quindi eseguire una sostituzione di stringa su "% 2f" con '/'.

+0

So che l'URL funzionerà ma non mi piace l'aspetto, a quanto pare Jeff e l'equipaggio di SO si sono sentiti allo stesso modo. Questa soluzione è troppo pesante. – Todd

+0

È garantito che rimanga un URL valido solo se si annulla la scansione di% 2F nei parametri. Il tuo codice sopra cadrà su qualsiasi altro carattere che non è valido nei parametri, ad es. &, ; o%. – bobince

+0

Come ho detto, è un'eccezione e non la regola. – Todd