2011-05-01 63 views
27

我想我错过了关于MVC表单工作原理的一些基础知识。我在我的主页上有一个搜索表单,其中有五六个不同的字段供用户搜索。所以我有这个发布到我的结果行动就好了。结果操作如下所示:MVC 3表单发布并保留模型数据

[HttpPost] 
public ActionResult Results(SearchModel model) 
{ 
    ResultsModel results = new ResultsModel(); 
    results.ResultList = SearchManager.Search(model).ToList(); 

    return View("Results", results); 
} 

我简化了上述方法,但这个想法是相同的。所以这一切都很好。我的结果页面显示了结果的列表,我的用户是在以下网址:

http://www.site.com/results

所以......现在我想要做的事很常见。结果页面上有两个下拉列表。 “排序”和“每页结果数量”。我该怎么做,并将全套模型数据发送回控制器,以便我可以使用新参数进行查询?实际上,SearchModel类拥有大约60个不同的字段。潜在的所有数据都可以包含在模型中。你如何坚持到一个页面“回发”?

同样的问题让我对如何进行分页以及有点难过。我的分页链接会去一个网址,如:

http://www.site.com/results/2

但是,假设我们在响应GET请求(我不想在查询字符串数据的60场)和模型数据在GET请求之间传递,我知道情况并非如此。如上所述,我想我错过了一些关于MVC 3,模型和表单帖子的基础知识。

任何人都可以帮助我指出正确的方向吗?我很乐意根据需要编辑/更新这篇文章,以澄清事情。

编辑:我也想指出,我想避免将视图模型存储在Session变量中。这个网站最终最终会在一个网络农场中实现负载均衡,我真的想尽可能避免使用Session。但是,如果它是唯一的选择,我将配置另一个会话状态提供程序,但我不想。

+0

嗯,我想听听一些关于这方面的专家意见,但也有可能让我有选择直接或间接地通过TempData掌握Session。其他选项是在结果页面上有大量隐藏字段。 – 2011-05-01 15:54:55

+0

对不起,那个带隐藏字段的部分是无稽之谈。最简洁的方法是使用tempdata。 – 2011-05-01 16:06:19

+0

它仍然感觉像2001 :( – andrew 2012-06-01 00:15:01

回答

15

您可以将当前的SearchModel参数添加到表单的路由值。 BeginForm的几个版本允许你传递一个对象/ RouteValuesDictionary。

@Html.BeginForm("Action", "Controller", new { SearchModel = Model }, FormMethod.Post) 

这应该传递您当前的SearchModel值,以便您可以重新使用它们以获取下一页。您需要定义一个控制器操作,以接受任何当前页面的表单值以及SearchModel。

我没有使用表单帖子完成此任务,但是从我所做的以及从文档所说的内容来看,这是我要开始的地方。当然,这也意味着页面上的每个页面“链接”都需要发布信息。如果用户希望能够在浏览器中使用“后退”按钮,那真的很不方便。

在这种情况下,您可以尝试定义允许页码显示为URL的一部分的路由 - “操作/控制器/ {页面}”。但是,我不确定该表单如何发挥作用,因为该表单正在发布帖子。

回应评论:

是的,你可以使用路由值的SearchModel添加到每个网页链接,但正如我在评论说,如上所述,由于链接将做“得到,”你的用户会请参阅序列化的SearchModel作为链接的一部分。

无论采用哪种方式,使用路径值都是您在不使用隐藏字段,会话或TempData的情况下取回原始SearchModel的答案。

+0

如果我找不到其他解决方案,我会仔细研究,但我想避免表单帖子,哈哈。我觉得用户希望能够在没有表单文章的情况下浏览结果(因此他们可以刷新或使用后退按钮),并且能够在不担心会话超时的情况下进行分页。也许这只是MVC的一个缺点。我倾向于在这一点上使用GET,并让URL变得有点混乱。 – Scott 2011-05-01 16:53:33

2

我在这里想到的一个选项是实现一个支持充当自定义会话提供者(即Memcached或Windows Server AppFabric)的分布式缓存系统,从而允许我在TempData(和Session)中使用一个负载均衡的环境如下:

[HttpPost] 
public ActionResult Results(SearchModel model) 
{ 
    ResultsModel results = new ResultsModel(); 
    results.ResultList = SearchManager.Search(model).ToList(); 

    TempData["SearchModel"] = model; 

    return View("Results", results); 
} 

    [HttpGet] 
    public ActionResult Results(int? page) 
    { 
     SearchModel model = (SearchModel)TempData["SearchModel"]; 

     ResultsModel results = new ResultsModel(); 
     results.ResultList = SearchManager.Search(model).ToList(); 

     TempData["SearchModel"] = model; 

     return View("Results", results); 
    } 

对此方法有何想法?似乎需要经过许多才能获取请求之间传递的搜索参数。或者,也许我只是被宠坏了,这一切都发生在WebForms幕后。 :)

+0

Grrr ...这个小问题。TempData显然仍然使用会话。我不希望用户不能仅仅因为他们走了20分钟和他们的会话过期这种事情不应该需要会话任何想法呢这应该是非常简单的我认为我过于复杂 – Scott 2011-05-01 16:19:16

+0

斯科特你可以使用TempData只是为了填充结果上的隐藏字段这样会话在进一步的请求中就不起作用了Btw TempData在你使用它初始化视图后会自动抛弃 – 2011-05-01 16:22:27

+0

隐藏的字段在这里不起作用我的分页链接只是简单地将http:// www.site.com/results/2“(对于第2页),每个分页链接都不是一个表单提交按钮,所以这些隐藏的字段将永远不会被发送回来,这看起来像是一个简单的问题,也许我正在接近这是错误的方式。即使没有考虑到我的方法,我也会很乐意听到其他人如何解决这个问题。 – Scott 2011-05-01 16:27:12

8

您的SearchModel类需要包含您的搜索条件和结果。像下面的东西。如果您为结果使用PagedList,那么它将包含当前页面,总页数,总项目等。您可以通过编写包含值的搜索条件来限制页面中的信息量。

public class SearchModel 
{ 
    public string Product { get; set; } 
    public string Sku { get; set; } 
    public string Size { get; set; } 
    public string Manufacturer { get; set; } 
    // etc... 

    public PagedList ResultsList { get; set; } 
} 


[HttpPost] 
public ActionResult Results(SearchModel model) 
{ 
    model.ResultList = SearchManager.Search(model).ToList(); 
    return View(model); 
} 
+0

这是一个有趣的方法。我会明天(或者第二天)尝试一下,然后再回来。 – Scott 2011-05-03 05:45:52