2010-04-01 7 views
7

sguardo sul mio codice che ho creato in una vista parziale: Non c'è modo semplice come unire due valori RouteValueDictionary per passare parametri a Html.ActionLink

  <% foreach (Customer customerInfo in Model.DataRows) {%> 

      <tr> 
       <td> 
        <%=Html.ActionLink(
          customerInfo.FullName 
          , ((string)ViewData["ActionNameForSelectedCustomer"]) 
          , JoinParameters(customerInfo.id, (RouteValueDictionary) ViewData["AdditionalSelectionParameters"]) 
          , null)%> 
       </td> 
       <td> 
        <%=customerInfo.LegalGuardianName %> 
       </td> 
       <td> 
        <%=customerInfo.HomePhone %> 
       </td> 
       <td> 
        <%=customerInfo.CellPhone %> 
       </td> 
      </tr> 
      <%}%> 

Qui sto costruendo semplice tabella che mostra i particolari del cliente.

Come si può vedere, in ogni riga, sto cercando di creare un collegamento che reindirizzerà a un'altra azione.

Questa azione richiede customerId e alcuni parametri aggiuntivi.

I parametri aggiuntivi sono diversi per ogni pagina in cui viene utilizzata questa vista parziale. Quindi, ho deciso di utilizzare i metodi Action per passare i parametri aggiuntivi nel ViewData come istanza RouteValueDictionary.

Ora, nella vista ho un problema, ho bisogno di passare customerId e che RouteValueDictionary insieme nel metodo Html.ActionLink. Questo mi consente di capire come combinare tutti i parametri in un oggetto (oggetto o nuova istanza RouteValueDictionary)

A causa del modo in cui il MVC lo fa, non posso creare creare un metodo nel codebehind class (non c'è codebihind in MVC) che entrerà a far parte di quei parametri.

Così, ho usato brutto modo - inserito il codice inline:

...script runat="server"...

private RouteValueDictionary JoinParameters(int customerId, RouteValueDictionary defaultValues) 
    { 
     RouteValueDictionary routeValueDictionary = new RouteValueDictionary(defaultValues); 

     routeValueDictionary.Add("customerId", customerId); 

     return routeValueDictionary;        
    } 
...script... 

In questo modo è molto brutto per me, perché io odio di utilizzare codice inline nella parte View.

La mia domanda è - c'è un modo migliore di come posso mescolare i parametri passati dall'azione (in ViewData, TempData, altro ...) e il parametro dalla vista quando si creano link di azione.

Potrebbe essere possibile creare questo collegamento in un altro modo?

Grazie!

risposta

2

Forse un modo semplice per fare questo sarebbe creare un'estensione UrlHelper che faccia qualcosa di simile a quello che fa il metodo JoinParameters. Qualcosa come il seguente metodo è un po 'più riutilizzabile:

public static RouteValueDictionary AppendRouteValue(this UrlHelper helper, RouteValueDictionary routeValues, string key, object value) 
{ 
    RouteValueDictionary routeValueDictionary = new RouteValueDictionary(routeValues); 
    routeValueDictionary.Add(key, value); 

    return routeValueDictionary; 
} 

Ora la vostra azione come sarebbe qualcosa di simile:

<%=Html.ActionLink(
    customerInfo.FullName 
    , ((string)ViewData["ActionNameForSelectedCustomer"]) 
    , Url.AppendRouteValue((RouteValueDictionary) ViewData["AdditionalSelectionParameters"], "customerId", customerInfo.id) 
    , null)%> 
9

Scrivi un metodo di estensione per unire dizionario fonte nella destinazione.

public static class Util 
{ 
    public static RouteValueDictionary Extend(this RouteValueDictionary dest, IEnumerable<KeyValuePair<string, object>> src) 
    { 
     src.ToList().ForEach(x => { dest[x.Key] = x.Value; }); 
     return dest; 
    } 

    public static RouteValueDictionary Merge(this RouteValueDictionary source, IEnumerable<KeyValuePair<string, object>> newData) 
    { 
     return (new RouteValueDictionary(source)).Extend(newData); 
    } 
} 

utilizzo:

Url.Action(actionName, controllerName, destRvd.Extend(srcRvd)); 

Se si desidera invece un 3 ° dizionario contenente il contenuto dei due - Unisci uso. Ma questo è meno efficiente.Questo approccio consente il concatenamento più o meno efficiente delle unioni, se avete bisogno di unire più di 2 dizionari:

Url.Action(actionName, controllerName, destRvd.Extend(srcRvd1).Extend(srcRvd2)); 

efficiente unire 3 dizionari in uno nuovo:

Url.Action(actionName, controllerName, srcRvd1.Merge(srcRvd2).Extend(srcRvd3)); 
5

- è possibile unire due (o più) oggetti RouteValueDictionary utilizzando il metodo Unione. Microsoft has good example code of the Union method here ma Microsoft non è molto chiaro quando si tratta di utilizzare RouteValueDictionary Unions (da qui il motivo del mio post).

Date le seguenti classi ...

public class Student 
{ 
    public int StudentID { get; set; } 
    public string FirstName { get; set; } 
    public string LastNamse { get; set; } 
    public string Email { get; set; } 
    public DateTime DateOfBirth { get; set; } 
} 

public class Address 
{ 
    public string StreetLine1 { get; set; } 
    public string StreetLine2 { get; set; } 
    public string Suburb { get; set; } 
    public string State { get; set; } 
    public string PostCode { get; set; } 
} 

... e alcuni esempi di codice ...

Student aStudent = new Student(); 
aStudent.StudentID = 1234; 
aStudent.FirstName = "Peter"; 
aStudent.LastNamse = "Wilson"; 
aStudent.Email = "[email protected]"; 
aStudent.DateOfBirth = new DateTime(1969, 12, 31); 

Address homeAddr = new Address(); 
homeAddr.StreetLine1 = "Unit 99, Floor 10"; 
homeAddr.StreetLine2 = "99-199 Example Street"; 
homeAddr.Suburb = "Sydney"; 
homeAddr.State = "NSW"; 
homeAddr.PostCode = "2001"; 

inizializzare e aggiungere il KeyValue<string, object> elementi ai RouteValueDictionary oggetti:

RouteValueDictionary routeStudent = new RouteValueDictionary(aStudent); 
RouteValueDictionary routeAddress = new RouteValueDictionary(homeAddr); 

... Unire i due oggetti del dizionario utilizzando l'operatore Unione:

RouteValueDictionary routeCombined = new RouteValueDictionary(routeStudent.Union(routeAddress).ToDictionary(k => k.Key, k => k.Value)); 

Ora è possibile passare la variabile routeCombined al metodo appropriato (ad esempio ActionLink).

@Html.ActionLink("Click to pass routeValues to the RouteAPI", "MyActionName", routeCombined); 

Scrivendo fuori alla finestra di debug ...

foreach (KeyValuePair<string, object> n in routeCombined) 
    System.Diagnostics.Debug.WriteLine(n.Key + ": " + n.Value); 

... produrrà il seguente:

 
StudentID: 1234 
FirstName: Peter 
LastNamse: Wilson 
Email: [email protected] 
DateOfBirth: 31/12/1969 12:00:00 AM 
StreetLine1: Unit 99, Floor 10 
StreetLine2: 99-199 Example Street 
Suburb: Sydney 
State: NSW 
PostCode: 2001 
+0

risposta eccezionale. +1. Benvenuti in SOF e grazie per il post. – JoshYates1980

Problemi correlati