ASP.NET MVC RouteValueDictionary和复杂对象

det*_*pro 6 asp.net-mvc razor asp.net-mvc-3

在搜索结果页面中保留表单帖子(视图模型)结果的最佳方法是什么?

我有一个包含复选框的搜索表单.此表单使用视图模型构建

public class SearchViewModel
{
    public string Name { get; set; }
    public string[] Colors { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

当这个视图模型被回发时,我使用这些值来构建查询(使用EF).结果将转换为PagedList.

    public class SearchController : Controller
    {
    public ActionResult Index()
    {
        //this displays the search form.
        return View();
    }

    public ActionResult Results(string game, SearchViewModel vm)
    {
        //this displays the results
        ViewBag.SearchViewModel = vm;
        var matches = _repository.AsQueryable()
            .ColorOr(vm.Colors)
            .WhereIf(vm.Name.IsNotEmpty(), x => x.Name.Contains(vm.Name.Trim()));

            return View(matches.ToPagedList(1, 10));
    }
}
Run Code Online (Sandbox Code Playgroud)

现在结果显示我想使用Html.PagedListPager和RouteValueDictionary来创建分页.

@Html.PagedListPager((IPagedList)Model, page => Url.Action("Results", new RouteValueDictionary(ViewBag.SearchViewModel)))
Run Code Online (Sandbox Code Playgroud)

然而; 创建的URL如下所示:

http://localhost:5139/search?Name=test&Colors=System.String[]&PageIndex=0
Run Code Online (Sandbox Code Playgroud)

颜色的值最终是类型而不是值.我希望URL看起来更像:

 http://localhost:5139/search?Name=test&Colors=[Blue,Pink,Yellow]&PageIndex=0
Run Code Online (Sandbox Code Playgroud)
  1. 在搜索结果页面中保留表单帖子(视图模型)结果的最佳方法是什么?
  2. RouteValueDictionary可以支持复杂对象吗?
  3. 我应该使用像unbinder这样的东西
  4. 使用ViewData或Session会更好吗?

GON*_*ale 2

我对这样的情况所做的,我发现简单但功能强大,是将我的视图模型对象序列化为 JSON(在您的情况下SearchViewModel),使用NewtonSoft JSON.net之类的东西,然后使用生成的 JSON 字符串,进行简单的压缩通过zlib.net Zlib.DeflateStream类(您也可以使用AES Rijndael之类的东西,但无疑会更慢,并且您首先需要速度),然后将生成的 Base64 字符串传递到您的 QueryString。

然后,当您准备再次使用它时(它实际上是一个视图状态),只需解压缩 JSON 字符串并将其从 JSON 反序列化到相应的 .NET 对象中(同样在您的情况下SearchViewModel)。

这对我来说是一种享受,并且您最终不会得到无法管理的 URL 或任何真正可衡量的性能影响,就像我在只有少数表单字段被序列化时所看到的那样。

我很快就会用代码示例来详细说明。

更新:代码示例...

这就是我在您的特定场景中会做的事情:

行动中Results(string, SearchViewModel)

public ActionResult Results(string encryptedUrlViewModel, string game, SearchViewModel vm)
{
    SearchViewModel searchUrlViewModel = null;
    if (!string.IsNullOrEmpty(searchUrl)) {
      // only first submission, no url view model set yet, so compress it and store..
      encryptedUrlViewModel = Convert.ToBase64String(
        DeflateStream.CompressString(JsonConvert.SerializeObject(vm)));
      ViewBag.EncryptedUrlViewModel = encryptedUrlViewModel;
    }
    else {
      var jsonUrlViewModel = DeflateStream.UncompressString(Convert.FromBase64String(encryptedUrlViewModel));
      searchUrlViewModel = JsonConvert.DeserializeObject(jsonUrlViewModel, typeof(SearchViewModel)) as SearchViewModel;
      // at this point you should have a serialized 'SearchViewModel' object 
      // ready to use which you can then tweak your query below with.
    }
    var matches = _repository.AsQueryable()
        .ColorOr(vm.Colors)
        .WhereIf(vm.Name.IsNotEmpty(), x => x.Name.Contains(vm.Name.Trim()));

    return View(matches.ToPagedList(1, 10));
}
Run Code Online (Sandbox Code Playgroud)

视图中:

@Html.PagedListPager((IPagedList)Model, page => Url.Action("Results", new { encryptedUrlViewModel = ViewBag.EncryptedUrlViewModel }))
Run Code Online (Sandbox Code Playgroud)

该代码可能需要一些调整,在您的场景中未经测试,但它会是类似的东西,祝你好运:)

不过,您确实应该考虑一下,如果您希望跨分页在 URL 中携带用户的请求,那么人们首先会考虑为什么表单不是作为请求而不是作为请求来创建GETPOST您有什么特别想要它的理由POST吗?我认为GET会正确携带您的Colors阵列,但请确保您的视图模型设置正确。有关模型绑定到列表的信息,请参阅这篇 Haacked 文章