Asp.Net mvc 5 - 如何在Html.ActionLink()中传递复杂对象作为路由值,以便默认模型绑定器可以映射它?

时间:2014-05-19 16:55:51

标签: asp.net-mvc model-binding html.actionlink

我有一个对象,其中包含搜索,排序和分页参数以及要编辑的记录的ID。

我想将此对象作为路由值对象传递给Html.ActionLink(),以便生成的查询字符串将由默认模型绑定器正确映射到Edit操作的参数,即EditViewModel。 / p>

我们的想法是,在编辑操作完成后,它可以重定向回索引并在同一数据集中保持相同的分页/排序位置,并使用相同的搜索字符串进行过滤。

修改视图模型:

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

编辑操作:

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

当我在视图中执行此操作时:

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

我明白了:

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

但我想要这个:

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

到目前为止,我能够传递对象的唯一方法是手动准备查询字符串,如下所示:

@{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>

我想过编写一个自定义模型绑定器,但是如果默认模型绑定器已经按照预期的方式格式化为查询字符串,它就已经处理了嵌套对象,这似乎很愚蠢。

我还想过编写一个自定义对象序列化程序,它输出一个默认模型绑定器所期望的串行格式,但还没有走下去。

最后,我想要将EditViewModel弄平,所以没有嵌套,只是将所有属性都列出来。但是,这并不理想。

那么,最好的方法是什么?

1 个答案:

答案 0 :(得分:10)

据我所知,您不能直接传递复杂对象,但可以通过传递RouteValueDictionary来避免自己构建查询字符串:

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

这应该根据需要生成查询字符串。

唯一的另一种选择是使用反射来迭代模型的属性并以这种方式生成这个字典,但在我看来,这将被过度设计。

当然,在这种情况下,我通常会建议你只需要使用不同的参数:

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

我通常认为这是将GET参数传递给方法的更合适的方法(当然,如果你有很多参数,这可能会变得难以处理)。然后你可以做以下,这更加整洁:

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