Pytanie Asp.Net mvc 5 - Jak mogę przekazać obiekt złożony jako wartość trasy w Html.ActionLink (), więc domyślny segregator modelu może go odwzorować?


Mam obiekt zawierający parametry wyszukiwania, sortowania i stronicowania oraz identyfikator rekordu do edycji.

Chciałbym przekazać ten obiekt do Html.ActionLink () jako obiekt wartości trasy, aby wynikowy ciąg zapytania był poprawnie odwzorowany przez domyślny segregator modelu na parametr akcji edycji, który jest EditViewModel.

Chodzi o to, że po zakończeniu akcji edycji można przekierować z powrotem do indeksu i zachować tę samą pozycję stronicowania / sortowania w tym samym zbiorze danych i przefiltrować za pomocą tego samego ciągu wyszukiwania.

Edytuj model widoku:

public class EditViewModel
{
    public SearchSortPageViewModel SearchSortPageParams { get; set; }
    public int Id { get; set; }

    public EditViewModel() 
    {
        SearchSortPageParams = new SearchSortPageViewModel();
        Id = 0;
    }

    public EditViewModel(SearchSortPageViewModel searchSortPageParams, int id)
    {
        SearchSortPageParams = searchSortPageParams;
        Id = id;
    }
}

public class SearchSortPageViewModel
{
    public string SearchString { get; set; }
    public string SortCol { get; set; }
    public string SortOrder { get; set; }
    public int Page { get; set; }
    public int PageSize { get; set; }
}

Edytuj akcję:

public ActionResult Edit(EditViewModel evm)
    {
        /* ... */
    }

Kiedy robię to w widoku:

@model MyApp.Areas.Books.ViewModels.Books.IndexViewModel
...
@{EditViewModel evm = new EditViewModel(Model.SearchSortPageParams, item.ID);}
@Html.ActionLink("Edit", "Edit", evm)

Rozumiem:

http://localhost:63816/Books/Books/Edit/4?SearchSortPageParams=MyApp.Areas.Base.ViewModels.SearchSortPageViewModel

Ale chcę tego:

http://localhost:63816/Books/Books/Edit/4?SearchSortPageParams.SearchString=abc&SearchSortPageParams.SortCol=name&SearchSortPageParams.SortOrder=asc&SearchSortPageParams.Page=1&SearchSortPageParams.PageSize=3

Jedynym sposobem, w jaki udało mi się przekazać obiekt do tej pory, było ręczne przygotowanie ciągu zapytania, jak poniżej:

@{string theQueryString = "?SearchSortPageParams.SearchString=" + @evm.SearchSortPageParams.SearchString + "&SearchSortPageParams.SortCol=" + @evm.SearchSortPageParams.SortCol + "&SearchSortPageParams.SortOrder=" + @evm.SearchSortPageParams.SortOrder + "&SearchSortPageParams.Page=" + @evm.SearchSortPageParams.Page + "&SearchSortPageParams.PageSize=" + @evm.SearchSortPageParams.PageSize;}
<a href="@Url.Action("Edit", new { evm.Id })@(theQueryString)">Edit</a>

Pomyślałem o napisaniu niestandardowego segregatora modelu, ale wydaje się to niemądre, biorąc pod uwagę, że domyślny segregator modelu obsługuje już zagnieżdżone obiekty, jeśli jest sformatowany jako ciąg zapytania w oczekiwany sposób.

Pomyślałem również o napisaniu serializera obiektów niestandardowych, który wyprowadza format szeregowy, którego oczekuje domyślny spinacz modelu, ale nie przeszedł jeszcze tej trasy.

W końcu pomyślałem o spłaszczeniu EditViewModel, więc nie ma nic zagnieżdżonego, po prostu wszystkie właściwości są wyszczególnione. Ale nie jest idealny.

Jaki jest najlepszy sposób na zrobienie tego?


11
2018-05-19 16:55


pochodzenie




Odpowiedzi:


Z tego co wiem, nie możesz bezpośrednio przekazać obiektu złożonego, ale możesz uniknąć konieczności budowania ciągu zapytania przez przekazanie a RouteValueDictionary:

@Html.ActionLink("Edit", "Edit", new RouteValueDictionary {
    {"SearchSortPageParams.SortOrder", evm.SearchSortPageParams.SortOrder },
    { /* etc... */ }
})

Powinno to wygenerować ciąg zapytania tak, jak tego potrzebujesz.

Jedyną inną alternatywą byłoby wykorzystanie refleksji do iteracji nad właściwościami modelu i wygenerowania tego słownika w ten sposób, ale to, moim zdaniem, byłoby zbyt zaawansowane.

Oczywiście generalnie sugerowałbym w tej sytuacji, że masz tylko swoją metodę działania, przyjmującą oddzielne parametry:

public ActionResult Search(string searchString, SortOrder sortOrder, ...)

Ogólnie uważam, że jest to bardziej odpowiedni sposób przekazywania parametrów GET do metody (oczywiście, może to stać się nieporęczne, jeśli masz dużo parametrów). Następnie możesz wykonać następujące czynności, które są znacznie bardziej przejrzyste:

@Html.ActionLink("Edit", "Edit",
    new { sortOrder = evm.SearchSortPageParams.SortOrder, ... })

9
2018-05-19 17:03



Poszedł z RouteValueDictionary, jest co najmniej lepszy niż ciąg surowego zapytania :-) Dzięki. - user482184