ASP.NET MVC RouteValueDictionary和复杂对象 [英] ASP.NET MVC RouteValueDictionary and Complex Object

查看:1197
本文介绍了ASP.NET MVC RouteValueDictionary和复杂对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

什么是保留整个搜索结果页面表单POST(视图模型)的结果的最佳方法是什么?

我有一个包含复选框搜索表单。这种形式是建立使用视图模型像

 公共类SearchViewModel
{
    公共字符串名称{;组; }
    公共字符串[] {颜色搞定;组; }
}

在这个视图模型被调回我用值来建立一个查询(使用EF)。其结果变成PagedList。

 公共类SearchController:控制器
    {
    公众的ActionResult指数()
    {
        //这将显示搜索表单。
        返回查看();
    }    公众的ActionResult结果(字符串游戏,SearchViewModel VM)
    {
        //这显示结果
        ViewBag.SearchViewModel = VM;
        VAR匹配= _repository.AsQueryable()
            .ColorOr(vm.Colors)
            .WhereIf(vm.Name.IsNotEmpty()中,x => x.Name.Contains(vm.Name.Trim()));            返回视图(matches.ToPagedList(1,10));
    }
}

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

  @ Html.PagedListPager((IPagedList)型号,网页= GT; Url.Action(结果,新RouteValueDictionary(ViewBag.SearchViewModel)))

不过,创建的URL看起来是这样的:

 的http://本地主机:5139 /搜索名称=测试&放大器;颜色= System.String []和放大器;的PageIndex = 0

对于颜色的值最终被类型不是值。我希望的URL看起来更像是:

 的http://本地主机:5139 /搜索名称=测试&放大器;颜色=蓝色,粉红色,黄色]放大器;的PageIndex = 0


  1. 什么是保持整个搜索结果页面表单POST(视图模型)的结果的最佳方法是什么?

  2. 可以RouteValueDictionary支持复杂的对象吗?

  3. 我应该使用类似<一个href=\"http://mhinze.com/2010/03/17/serializing-models-for-routevaluedictionary-and-later-model-binding/\">unbinder

  4. 我会过得更好用的ViewData或会话?


解决方案

我已经为这样的情况下,我觉得简单,但功能强大做些什么,是我的连载视图模型对象JSON(你的情况 SearchViewModel ),使用类似 NewtonSoft JSON.net然后用生成的JSON 弦,做到通过 zlib.net Zlib.DeflateStream 类(你也可以使用类似的 AES Rijndael算法但无疑会慢一些,你想速度首先),然后通过在您的查询字符串所产生的Base64编码字符串。

然后,当你准备再次使用它(这实际上是一个视图状态),只需DECOM preSS的JSON字符串,并以你的情况再次从JSON反序列化到相应的.NET对象( SearchViewModel )。

工作一种享受我,你不就是无法管理或我见过的,只有表单域一把正在连载任何真正的可衡量的绩效影响的URL中结束。

我会很快一个code样品细说了。

更新:code样本...

这是我会做什么在您的特定方案:

结果(字符串,SearchViewModel)动作:

 公众的ActionResult结果(字符串encryptedUrlViewModel,串游戏,SearchViewModel VM)
{
    SearchViewModel searchUrlViewModel = NULL;
    如果(!string.IsNullOrEmpty(searchUrl)){
      //只有第一次提交,不链接视图模型设置还,所以COM preSS它和存储..
      encryptedUrlViewModel = Convert.ToBase64String(
        DeflateStream.Com pressString(JsonConvert.SerializeObject(VM)));
      ViewBag.EncryptedUrlViewModel = encryptedUrlViewModel;
    }
    其他{
      VAR jsonUrlViewModel = DeflateStream.Uncom pressString(Convert.FromBase64String(encryptedUrlViewModel));
      sea​​rchUrlViewModel = JsonConvert.DeserializeObject(jsonUrlViewModel的typeof(SearchViewModel))作为SearchViewModel;
      //在这一点上,你应该有一个序列化SearchViewModel'对象
      //准备使用,然后可以调整下面与您的查询。
    }
    VAR匹配= _repository.AsQueryable()
        .ColorOr(vm.Colors)
        .WhereIf(vm.Name.IsNotEmpty()中,x =&GT; x.Name.Contains(vm.Name.Trim()));    返回视图(matches.ToPagedList(1,10));
}

在视图:

  @ Html.PagedListPager((IPagedList)型号,网页= GT; Url.Action(结果,新的{encryptedUrlViewModel = ViewBag.EncryptedUrlViewModel}))

在code,可能需要一些调整,在您的方案未经测试,但它将是类似的东西,好运:)

您真的应该考虑不过,如果你是想携带用户在整个页面的URL请求,那么人们会认为为什么形式不作为取得 GET 要求,而不是一个 POST 首先请求。你特别想让它什么理由 POST ?我觉得 GET 将携带你的颜色阵列正确,但要确保您的视图模型是建立正确的。 见模型绑定到列表这个Haacked文章

What is the best method to retain the results of a form post (view model) across search results page?

I have a search form that contains checkboxes. This form is build up using a view model like

public class SearchViewModel
{
    public string Name { get; set; }
    public string[] Colors { get; set; }
}

When this view model gets posted back I use the values to build a query (using EF). The results are turned into a 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));
    }
}

Now that the results are displayed I would like to use Html.PagedListPager and RouteValueDictionary to create paging.

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

However; the URL created looks like this:

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

The values for Colors ends up being the type not the values. I was hoping the URL looks more like:

 http://localhost:5139/search?Name=test&Colors=[Blue,Pink,Yellow]&PageIndex=0

  1. What is the best method to retain the results of a form post (view model) across search results page?
  2. Can RouteValueDictionary support complex objects?
  3. Should I use something like unbinder
  4. Would I be better off using ViewData or Session?

解决方案

What I've done for cases like this, which I find simple, yet powerful, is serialized my view model object to JSON (in your case SearchViewModel), using something like NewtonSoft JSON.net then with the resulting JSON string, do a simple compression of the string via the zlib.net Zlib.DeflateStream class (you could also use something like AES Rijndael but will no doubt be slower and you want speed first and foremost) and then pass the resulting Base64 string across your QueryString.

Then when you are ready to use it again (it's effectively a viewstate), simply decompress the JSON string and deserialize it from JSON into the respective .NET object (again in your case SearchViewModel).

Worked a treat for me, and you don't end up with a URL that is unmanageable or any real measurable performance impacts that I've seen with only a handful of form fields being serialized.

I will elaborate with a code sample soon.

UPDATE: Code samples...

This is what I would do in your particular scenario:

In Results(string, SearchViewModel) action:

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

In view:

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

The code may require some tweaks, untested in your scenario but it will be something like that, best of luck :)

You should really consider though, if you are wanting to carry the user's request in the URL across paging then one would consider why the form wasn't made as a GET request as opposed to a POST request in the first place. Any reason you particularly wanted it POST? I think GET will carry your Colors array properly, but make sure your view model is setup right. See this Haacked article for model binding to lists.

这篇关于ASP.NET MVC RouteValueDictionary和复杂对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆