2010-04-01 6 views
7

Mira mi código que he creado en una vista parcial: ¿Hay manera sencilla cómo unir dos valores RouteValueDictionary para pasar parámetros 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> 
      <%}%> 

Aquí estoy construyendo sencilla tabla que muestra los detalles del cliente.

Como puede ver, en cada fila, estoy tratando de construir un enlace que redirija a otra acción.

Esa acción requiere customerId y algunos parámetros adicionales.

Los parámetros adicionales son diferentes para cada página donde esta vista parcial está siendo utilizada. Entonces, decidí hacer que los métodos de Acción pasen los parámetros adicionales en el ViewData como instancia de RouteValueDictionary.

Ahora, en la vista tengo un problema, necesito pasar customerId y ese RouteValueDictionary juntos en el método Html.ActionLink. Eso me hace pensar en cómo combinar todos los params en un objeto (ya sea un objeto o una nueva instancia de RouteValueDictionary)

Debido a la forma en que lo hace MVC, no puedo crear crear un método en el código subyacente clase (no hay codebihind en MVC) que unirá esos parámetros.

Por lo tanto, yo solía fea manera - se inserta el código en línea:

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

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

     routeValueDictionary.Add("customerId", customerId); 

     return routeValueDictionary;        
    } 
...script... 

De esta manera es muy feo para mí, porque no me gusta usar el código en línea en la parte Vista.

Mi pregunta es: ¿hay alguna forma mejor de cómo puedo mezclar los parámetros pasados ​​de la acción (en ViewData, TempData, otros ...) y el parámetro de la vista al construir enlaces de acción.

¿Puedo construir este enlace de otra manera?

Gracias!

Respuesta

2

Quizás una manera simple de lograr esto sea crear una extensión UrlHelper que haga algo similar a lo que hace su método JoinParameters. Algo así como el método de abajo es un poco más reutilizables:

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

    return routeValueDictionary; 
} 

Ahora su acción como sería algo así como:

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

Escribir un método de extensión de fusionar el diccionario de origen en el destino.

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); 
    } 
} 

uso:

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

Si por el contrario desea una tercera diccionario que contiene los contenidos de los dos - el uso de mezcla. Pero eso es menos eficiente.Este enfoque permite el encadenamiento de más o menos eficiente de las fusiones si es necesario combinar más de 2 diccionarios:

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

eficiente fusionar 3 diccionarios en uno nuevo:

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

- se puede fusionar dos (o más) objetos RouteValueDictionary juntos utilizando el método de unión. Microsoft has good example code of the Union method here pero Microsoft no está realmente claro cuando se trata de usar uniones RouteValueDictionary (de ahí el motivo de mi publicación).

Dadas las siguientes clases ...

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; } 
} 

... y algunos ejemplos de código ...

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"; 

inicializar y añadir los elementos a los KeyValue<string, object>RouteValueDictionary objetos:

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

... Fusiona los dos objetos del diccionario con el operador de la Unión:

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

Ahora puede pasar la variable routeCombined al método apropiado (como ActionLink).

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

Escribiendo a la ventana de depuración ...

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

... para producir lo siguiente:

 
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

respuesta excepcional. +1. Bienvenido a SOF y gracias por la publicación. – JoshYates1980

Cuestiones relacionadas