2010-04-01 9 views
7

Spójrz na mojego kodu, który został utworzony w częściowym widokiem: Czy istnieje prosty sposób, jak połączyć dwie wartości RouteValueDictionary przekazać parametry do 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> 
      <%}%> 

Tutaj buduję prostą tabelę, która pokazuje dane klienta.

Jak widać, w każdym wierszu próbuję utworzyć link, który przekieruje do innej akcji.

To działanie wymaga customerId i kilku dodatkowych parametrów.

Dodatkowe parametry są różne dla każdej strony, z której korzysta ten widok częściowy. Postanowiłem więc, aby metody Action przekazały te dodatkowe parametry w instancji ViewData jako RouteValueDictionary.

Teraz, w widoku Mam problem, muszę przekazać customerId i RouteValueDictionary razem do metody Html.ActionLink. To pozwala mi dowiedzieć się, jak połączyć wszystkie te params w jeden obiekt (obiekt lub nowa instancja RouteValueDictionary)

Ze względu na sposób, w jaki robi to MVC, nie mogę utworzyć metody w kodzie źródłowym klasa (nie ma kodu w MVC), która połączy te parametry.

Więc użyłem brzydkiego sposób - dodaje kod inline:

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

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

     routeValueDictionary.Add("customerId", customerId); 

     return routeValueDictionary;        
    } 
...script... 

w ten sposób jest bardzo brzydki dla mnie, bo nienawidzę używać kodu inline w widoku strony.

Moje pytanie brzmi - czy istnieje lepszy sposób, w jaki sposób mogę mieszać parametry przekazane z akcji (w ViewData, TempData, inne ...) i parametr z widoku podczas budowania linków akcji.

Może mogę zbudować ten link w inny sposób?

Dzięki!

Odpowiedz

2

Być może prostym sposobem osiągnięcia tego byłoby utworzenie rozszerzenia UrlHelper, które robi coś podobnego do metody JoinParameters. Coś jak poniższa metoda jest nieco bardziej wielokrotnego użytku:

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

    return routeValueDictionary; 
} 

Teraz twoja akcja jak byłoby coś jak:

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

Napisz metodę rozszerzenia do łączenia słownika źródłowego do docelowego.

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

Wykorzystanie:

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

Jeśli zamiast tego chcesz 3rd słownika zawierającego zawartość dwóch - wykorzystanie seryjnej. Ale to mniej wydajne.Takie podejście pozwala na bardziej lub mniej efektywne łańcuchowym z scala jeśli trzeba połączyć więcej niż 2 słowniki:

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

Skutecznie łączyć 3 słowniki na nową:

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

Tak - można scalić dwa (lub więcej) obiektów razem, przy użyciu metody unijnej. Microsoft has good example code of the Union method here ale Microsoft nie jest do końca jasny jeśli chodzi o używanie związków RouteValueDictionary (stąd powód mojego wpisu).

Biorąc pod uwagę następujące klasy ...

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

... i przykładowy kod ...

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

Inicjowanie i dodać KeyValue<string, object> elementy do RouteValueDictionary obiektów:

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

... Scal dwa obiekty słownika przy użyciu operatora unijnego:

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

Teraz można przekazać zmienną routeCombined do odpowiedniej metody (takiej jak ActionLink).

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

Spisanie do okna debugowania ...

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

... przyniesie następujące:

 
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

Znakomita odpowiedź. +1. Witamy w SOF i dzięki za post. – JoshYates1980

Powiązane problemy