在ASP.NET MVC中保留来自多个表单的数据

时间:2009-06-14 19:45:58

标签: asp.net-mvc

我在一个页面上有两个表单:结果表单和搜索表单。搜索表单使用部分视图,因为它显示在几个不同的页面上。我希望能够将搜索表单中的数据保存在用户单击哪个表单的哪个按钮上。问题是当用户点击结果表单中的链接或按钮时,仅发布结果表单中的表单值,不包括搜索表单中的值。即使不是提交的表单,如何在搜索表单中维护这些值?我不想使用任何类型的会话状态来维护表单,我不想在结果表单中的隐藏字段中写入搜索值。我只是希望能够使用结果表单的表单值发布它们,以便可以在显示搜索部分视图的任何页面上维护用户搜索条件。我错过了什么?

我想到的第一个想法是删除包含搜索控件的表单,然后将其与结果数据一起渲染到表单中。我在这里担心命名冲突。当搜索来自具有与结果表单同名的控件时会发生什么情况,这不会导致命名冲突吗?我想这可以只是手动管理,以确保在将部分视图呈现到其他视图时有唯一的名称,甚至可能使用部分视图名称前缀值,但这让我想起INamingContainer的丑陋。网络表单 - 加上模型中繁琐的字段名称。

是否有某种优雅的解决方案可以让表格保持我失踪的状态?谢谢!

4 个答案:

答案 0 :(得分:1)

通常,我会在执行搜索时在服务器端保留搜索条件。如果用户在执行搜索后更改搜索条件,则发布表单当然会丢失任何更改,但这可以说是正确的行为,因为未调用搜索。无论搜索是从完整帖子还是通过ajax执行,都是如此。通过这种方式处理可以使操作更加清晰,我认为您不需要在其他操作中处理搜索数据。

如果你绝对需要包含搜索参数,你可以考虑通过javascript获得第二个表单发布,动态获取搜索字段值并在发布第二个表单之前将它们添加到第二个表单(作为隐藏字段) 。您不必在同步中维护两个位置的值,但在发布之前必须将它们复制到第二个表单。

答案 1 :(得分:1)

此刻我得到了这样的话:

具有搜索框的表单,发布查询(如果需要,还有其他数据)搜索控制器然后呈现搜索视图。搜索视图来自搜索框和搜索结果部分视图。在此期间 - 搜索框表单由发布的数据重建。

如果我需要搜索结果表单来执行另一个搜索请求(例如,使用指定的页面索引),它会通过ajax,它会从搜索结果表单中发布搜索框表单+页面索引。看看here的想法(使用targetId参数更新JS方法以更新指定的div /表单,如果需要,可以像这样发布其他数据:

form.serialize()+"&pageIndex=5"

简而言之:如果您需要在一个页面中维护表单状态+更新另一个 - 请考虑使用部分更新,否则您将最终发明ViewState 2.0。

有一点需要注意 - 使搜索框包含与搜索结果相关的内容(即 - 找到的项目的总数)是很棘手的。在我设法处理这个之前,我们的设计师做到了 - 我只需要添加具有适当类名的div(“sbsubst”或其他东西),它看起来就在搜索框内。 :)

答案 2 :(得分:0)

我认为最好的方法是在第二个表单操作网址的查询部分更改时,将搜索输入中的文本存储起来。例如(未测试):

$('input#yourSearchInput').change(function()
{
    var searchText = $(this).val();

    // or? var searchText = encodeURIComponent($(this).val());

    var secondForm = $('form#secondFormId');

    var action = secondForm.attr('action');

    var queryStart = action.lastIndexOf('?search=');
    if(queryStart > -1) {
        action = action.substring(1, queryStart);
    }

    action = action + "?search=" + searchText;

    secondForm.attr('action', action);
});

在Controller(或自定义过滤器)中:

protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
    var search = Request.QueryString["search"];
    if(!String.IsNullOrEmpty(search)) {
        ViewData["SearchFromPOST"] = search;
    }
    base.OnActionExecuting(filterContext);
}

在您的搜索控件中:

<%= TextBox("yourSearchInputId", ViewData["SearchFromPOST"]) %>

答案 3 :(得分:0)

如果页面上的表单很少,则每个表单只会发送自己的数据。在WebForms中,您只有一个表单(至少是服务器端),并且每个控件都包含在此表单中。在ASP.NET MVC中,您可以使用相同的场景,如果您想要具有所描述的行为,我恐怕您将不得不这样做。不要忘记 - 部分表格不一定是真实的形式。此外,RenderPartial主要用于“类似控件”的布局创建。

至于你问题的第二部分,我建议在搜索表单中用一些正常的前缀命名你的文本框,比如“搜索”或类似的东西。例如,如果表单中有文本框“text”和“language”,则会有“searchText”和“searchLanguage”。这些名称非常独特,您的参数中将包含普通名称。

我不建议您在POST事件中填充结果表单中的隐藏值,因为您说它不是您的选项,但如果您想要两个表单,它仍然是唯一的方法。