2012-02-25 8 views
5

Nella mia applicazione, parametro stringa key query può essere utilizzato per concedere l'accesso a determinate azioni/vista.
Ora desidero che tutti gli ActionLink e i moduli includano automaticamente questo parametro se presente nella stringa di query corrente.ASP.NET MVC: Il modo giusto per propagare parametro di query attraverso tutti ActionLinks

Qual è il modo giusto per farlo?

sto chiedendo circa il modo giusto perché ho visto diverse soluzioni che hanno proposto cambiando il punto di vista in un modo o nell'altro (metodi di estensione alternativa/aiutanti, passaggio di parametri manuale). Questa non è una soluzione che sto cercando.

UPDATE:
soluzione finale (sulla base di anwer di MikeSW): https://gist.github.com/1918893.

+0

Questo sembra anche rilevante: http: // stackoverflow.com/questions/5060346/howto-automatically-add-a-specific-value-from-current-route-to-all-generated-lin – DenNukem

risposta

9

È possibile farlo con percorsi ma è necessario un po 'più di infrastrutture. Qualcosa di simile

public class RouteWithKey:Route 
{ 
    //stuff omitted 
    public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values) 
    { 
    values.Add("key", requestContext.HttpContext.Request.QueryString["key"]); 
    var t = base.GetVirtualPath(requestContext, values);   
     return t; 
    } 
} 

Naturalmente avrete bisogno di recuperare la chiave dalle params di richiesta e di gestire il caso in cui chiave è il secondo parametro nella query, ma questo suddetto approccio aggiungerà automaticamente la chiave di ogni Utel costruito via normale come.helpers net mvc

Mi è capitato di utilizzare un percorso personalizzato per un'applicazione, per uno scopo diverso ma io; ho testato con il codice sopra e aggiunge il parametro, quindi almeno nel mio progetto sembra funzionare correttamente.

+0

Questa è una buona idea che è effettivamente pertinente alla domanda, grazie. Sfortunatamente, si rompe se usato in ActionLink con i propri parametri. Produce url con '? Key = mykey? Other = myother' dato che' ActionLink' non si aspetta '?' In 'VirtualPath'. –

+0

Ho aggiornato l'esempio per gestire il caso – MikeSW

+0

Hooray, questo funziona davvero! Molte grazie. Ho trovato ancora più semplice: aggiungere chiave/valore ai 'valori' prima di chiamare' base.GetVirtualPath'. Puoi aggiornare la tua risposta con quella (dato che è buona la soluzione migliore nella risposta accettata)? –

0

Salve per la situazione che descrivi, puoi facilmente utilizzare i cookie. Crea un cookie con la chiave del nome e assegna lo stesso valore del parametro della tua chiave URL. Ora puoi dare o rifiutare l'accesso ai tuoi utenti utilizzando la presenza o l'assenza di cookie validi, anziché la presenza o l'assenza di parametri chiave.

È possibile accedere ai biscotti utilizzando Response.Cookies

Se si vuole ancora cambiare tutto il modulo e aiutanti ActionLink, quindi è possibile creare i propri aiutanti, che internamente chiamare i soccorritori MVC, con il parametro chiave in più, e usa gli aiutanti personalizzati ovunque. Cercare here per la scrittura di aiutanti personalizzati

+0

Considera "condivisione", dove vuoi mostrare una certa galleria fotografica per alcuni persone che non sono registrate sul sito. Puoi semplicemente spedire loro un link. È anche possibile impostare un cookie al momento della prima visita, ma rende la convalida della sicurezza più complessa (controlliamo ora query string o cookie) e crea problemi se in realtà vogliono condividere determinati collegamenti secondari con qualcun altro. Inoltre, non tutti hanno abilitato i cookie. –

+0

Questo non è esattamente il mio caso di utilizzo corrente, ma ho anche ragioni per quello attuale, quindi preferirei implementarlo esattamente come richiesto. –

+0

Nota che ho detto di non considerare gli helper personalizzati (metodi di estensione alternativi nella domanda), richiede modifiche alla vista. Domanda aggiornata per renderla più chiara. –

-1

Avere un parametro querystring che controlla l'autorizzazione è un'idea IMHO male. Cosa mi impedisce di aggiungere questo parametro al mio URL che non conteneva?

Il modo migliore per implementare l'autorizzazione è utilizzare i ruoli (http://msdn.microsoft.com/en-us/library/system.web.security.roleprovider.aspx).

+2

Sono consapevole di ciò, tuttavia non tutti i casi d'uso e non tutte le applicazioni richiedono quel livello di sicurezza. Ad esempio, puoi consentire a qualcuno di accedere al tuo documento Google utilizzando l'url con una chiave specifica. –

+0

@JakubKonecki dare un'occhiata alla sicurezza basata sulle capacità e Waterken http://higherlogics.blogspot.com/2012/01/clavis-web-security-microframework.html –

1

Come aggiungere la chiave ai valori del percorso.

{Controller}/{action}/{key}

Ogni volta che un URL contiene una stringa di query con chiave = someValue, l'URL sarà simile

Home/Indice/somevalue,

Ora tutti i link di azione e gli URL relativi includeranno anche questo per impostazione predefinita.

+0

La chiave deve essere in stringa di query (e facoltativo), può Lo faccio con i valori del percorso? Voglio dire che l'URL previsto è 'Home/Index? Key = somevalue'. –

+0

no questo non può essere fatto dai valori del percorso. Ma sempre nell'approccio sopra menzionato è possibile definire la chiave come Opzionale. Se si desidera averlo nella stringa di query, è possibile definire un'estensione al metodo ActionLink, che aggiungerà i valori chiave di querystring (se disponibili) durante la creazione di un collegamento. – Manas

-1

La cosa più semplice è quello di mettere il parametro "chiave" in tutta l'Url.Action e Html.ActionLink in questo modo:

@Url.Action("MyAction", "MyController", new { key = Request["key"] }) 

se Request["key"] è vuota verrà saltato il parametro querystring.

+0

Ho detto che questa non è la risposta che cerco in questa domanda. Avere un framework che rende le preoccupazioni trasversali più semplici nella maggior parte dei casi ('ActionFilter' ecc.), Non sono ancora pronto a rinunciare qui. –

0

Per fare ciò, ho scritto un'estensione di HtmlHelper chiamata "ActionLinkBack". I metodi compongono i link di azione sullo stesso controller un'azione e uniscono i valori di route esistenti con quelli nuovi specificati.

public static HtmlString ActionLinkBack(this System.Web.Mvc.HtmlHelper htmlHelper, string linkText, object routeValues) 
{ 
    return ActionLinkBack(htmlHelper, linkText, new RouteValueDictionary(routeValues), new RouteValueDictionary()); 
} 

public static HtmlString ActionLinkBack(this System.Web.Mvc.HtmlHelper htmlHelper, string linkText, object routeValues, object htmlAttributes) 
{ 
    return ActionLinkBack(htmlHelper, linkText, new RouteValueDictionary(routeValues), new RouteValueDictionary(htmlAttributes)); 
} 

public static HtmlString ActionLinkBack(this System.Web.Mvc.HtmlHelper htmlHelper, string linkText, RouteValueDictionary routeValues) 
{ 
    return ActionLinkBack(htmlHelper, linkText, routeValues, new RouteValueDictionary()); 
} 

public static HtmlString ActionLinkBack(this System.Web.Mvc.HtmlHelper htmlHelper, string linkText, RouteValueDictionary routeValues, IDictionary<string, object> htmlAttributes) 
{ 
    // Build a new dictionary of route values based on the previous set 
    var newRouteValues = new RouteValueDictionary(htmlHelper.ViewContext.RouteData.Values); 

    // Retain current querystring parameters 
    var queryString = htmlHelper.ViewContext.HttpContext.Request.QueryString; 
    if (queryString.Count > 0) 
    { 
     foreach (string key in queryString.Keys) 
     { 
      newRouteValues[key] = queryString[key]; 
     } 
    } 

    // Add and override entries from the list of new route values 
    if (routeValues != null) 
    { 
     foreach (var routeValueItem in routeValues) 
     { 
      newRouteValues[routeValueItem.Key] = routeValueItem.Value; 
     } 
    } 

    return new HtmlString(htmlHelper.ActionLink(linkText, null, newRouteValues, htmlAttributes).ToHtmlString()); 
} 

Nel mio riutilizzabile "pagina navigatore" vista che utilizzare le estensioni per comporre i precedenti, successivi e singoli collegamenti della pagina:

@Html.ActionLinkBack("Next", new { page = (int)ViewData["Page"] + 1 }, new { @class = "navigationLink" }) 
Problemi correlati