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

Asp.net mvc Net mvc 5-如何在Html.ActionLink()中将复杂对象作为路由值传递,以便默认模型绑定器可以映射它?,asp.net-mvc,model-binding,html.actionlink,Asp.net Mvc,Model Binding,Html.actionlink,我有一个包含搜索、排序和分页参数的对象,以及要编辑的记录的id 我希望将此对象作为路由值对象传递到Html.ActionLink()中,以便生成的查询字符串将由默认模型绑定器正确映射到编辑操作的参数(EditViewModel)中 其思想是,在编辑操作完成后,它可以重定向回索引,并在相同的数据集中保持相同的分页/排序位置,并通过相同的搜索字符串进行过滤 编辑视图模型: public class EditViewModel { public SearchSortPageViewModel

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

我希望将此对象作为路由值对象传递到Html.ActionLink()中,以便生成的查询字符串将由默认模型绑定器正确映射到编辑操作的参数(EditViewModel)中

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

编辑视图模型:

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>
@{string theQueryString=“?SearchSortPageParams.SearchString=“++@evm.SearchSortPageParams.SearchString+”&SearchSortPageParams.SortCol=“++@evm.SearchSortPageParams.SortOrder=“++@evm.SearchSortPageParams.SortOrder+”&SearchSortPageParams.Page=“++@evm.SearchSortPageParams.Page”“&SearchSortPageParams.PageSize=“+@evm.SearchSortPageParams.PageSize;”
我曾想过编写一个自定义模型绑定器,但如果默认模型绑定器按照预期的方式格式化为查询字符串,那么它已经可以处理嵌套对象了,这似乎很愚蠢

我还考虑编写一个自定义对象序列化程序,它输出默认模型绑定器所期望的串行格式,但还没有实现

最后,我考虑将EditViewModel展平,这样就不会嵌套任何内容,只需将所有属性展平列出即可。但是,这并不理想


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

据我所知,您不能直接传递复杂对象,但可以通过传递
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, ... })

使用RouteValueDictionary,它至少比原始查询字符串要好:-)谢谢。