ASP.NET MVC RouteValueDictionary和复杂对象

时间:2011-12-20 17:48:10

标签: asp.net-mvc asp.net-mvc-3 razor

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

我有一个包含复选框的搜索表单。使用像

这样的视图模型构建此表单
public class SearchViewModel
{
    public string Name { get; set; }
    public string[] Colors { get; set; }
}

当这个视图模型被回发时,我使用这些值来构建一个查询(使用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));
    }
}

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

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

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

http://localhost:5139/search?Name=test&Colors=System.String[]&PageIndex=0

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

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

2 个答案:

答案 0 :(得分:2)

我为这样的案例做了些什么,我发现它很简单但功能强大,将我的视图模型对象序列化为JSON(在您的情况下为SearchViewModel),使用类似NewtonSoft JSON.net的内容然后使用生成的JSON字符串,通过zlib.net Zlib.DeflateStream类对字符串进行简单压缩(您也可以使用类似AES Rijndael的内容,但无疑会慢一点,您首先需要速度然后在QueryString中传递生成的Base64字符串。

然后,当您准备再次使用它(它实际上是一个视图状态)时,只需解压缩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));
}

在视图中:

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

代码可能需要一些调整,在你的场景中没有经过测试,但它会是这样的,祝你好运:)

你应该考虑一下,如果你想在分页中的URL中传递用户的请求,那么就会考虑为什么表单不是作为GET请求而不是POST。首先请求。你特别想要的任何理由POST?我认为GET会正确显示您的Colors数组,但请确保您的视图模型设置正确。 See this Haacked article for model binding to lists

答案 1 :(得分:1)

我有同样的问题,但有搜索参数。我们有一个颜色参数,它是搜索引擎正在使用的颜色名称列表。所以你可以勾选黑色和蓝色,结果包含黑色和蓝色产品。

我最终使用了Unbound

using Unbound;
Unbinder u = new Unbinder();

@Url.Action("Index", new RouteValueDictionary(u.Unbind(SearchParams)))

这会产生如下链接:

/MyRoute?color[0]=black&color[1]=blue