关于jquery:MVC 3中的Ajax帖子,具有多表单视图

Ajax post in MVC 3 with multiple-form View

我删除了之前关于主题的问题,因为上下文有所改变,问题是新的。

我现在只有一个模型的单一视图。该视图有两种形式。每个表单都提交自己的操作,每个操作使用模型数据的子集,使用数据执行搜索。然后将搜索结果添加到模型的属性中,并且需要将其渲染回视图。我可以通过一个标准的html帖子来完成这一切,但现在需要成为一个ajax帖子。

这是我的ViewModel:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public sealed class SearchUsersViewModel {

    [Display(Name ="Last Name")]
    public string LastName { get; set; }

    [Display(Name ="Username")]
    public string Username { get; set; }

    [Display(Name ="Email Address")]
    public string EmailAddress { get; set; }

    [Display(Name ="Entity Type")]
    public byte EntityTypeID { get; set; }

    [Display(Name ="Search Name")]
    public string SearchField { get; set; }

    public IEnumerable<SelectListDTO> EntityTypes { get; set; }

    public IEnumerable<UserEditViewModel> Users { get; set; }

    [Display(Name ="Total Rows")]
    public int TotalRowCount { get; internal set; }

    public SearchUsersViewModel() {
        EntityTypes = LookupEntityTypeService.Instance.SelectList;
        Users = new List<UserEditViewModel>();
    }
}

这是我的观点:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
@model SearchUsersViewModel


   
        @using (Html.BeginForm("FilterByUserData","Admin", FormMethod.Post, new {model = Model})) {
            @Html.ValidationSummary(true)
            <table cellpadding="0" cellspacing="0" border="0">
                <tr style="height: 30px;">
                    <td class="Header01">
                        User Search:
                    </td>
                </tr>
            </table>
            <table cellpadding="0" cellspacing="0" border="0">
                <tr style="height: 20px;">
                    <td class="Header02">
                        Search By User Information:
                    </td>
                </tr>
            </table>
            <table cellpadding="0" cellspacing="0" border="0">
                <tr style="height: 1px;">
                    <td class="ContentDividerHoriz_425"></td>
                </tr>
            </table>
            <table id="searchByUserDataTable" cellpadding="0" cellspacing="0" border="0">
                <tr style="height: 26px;">
                    <td class="leftColumn">
                        @Html.LabelFor(model => model.LastName):
                    </td>
                    <td class="rightColumn">
                        @Html.TextBoxFor(model => model.LastName, new { id ="lastNameSearchField", @class ="TextField_220" })
                    </td>
                </tr>
                <tr style="height: 26px;">
                    <td class="leftColumn">
                        @Html.LabelFor(model => model.Username):
                    </td>
                    <td class="rightColumn">
                        @Html.TextBoxFor(model => model.Username, new { id ="userNameSearchField", @class ="TextField_220" })
                    </td>
                </tr>
                <tr style="height: 26px;">
                    <td class="leftColumn">
                        @Html.LabelFor(model => model.EmailAddress):
                    </td>
                    <td class="rightColumn">
                        @Html.TextBoxFor(model => model.EmailAddress, new { id ="emailAddressSearchField", @class ="TextField_220" })
                    </td>
                </tr>
            </table>
            <table cellpadding="0" cellspacing="0" border="0">
                <tr>
                    <td id="filterByUserError" style="width: 375px;"></td>
                    <td align="right" style="width: 50px; padding-right: 75px;">
                       
                            <input id="filterByUserButton" type="submit" value="Search" />
                       
                    </td>
                </tr>
            </table>
        }
   

   
        @using (Html.BeginForm("FilterByEntityData","Admin", FormMethod.Post, new { model = Model })) {
            <table cellpadding="0" cellspacing="0" border="0">
                <tr style="height: 28px;">
                    <td style="width: 425px;"></td>
                </tr>
            </table>
            <table cellpadding="0" cellspacing="0" border="0">
                <tr style="height: 20px;">
                    <td class="Header02">
                        Search By Entity Information:
                    </td>
                </tr>
            </table>
            <table cellpadding="0" cellspacing="0" border="0">
                <tr style="height: 1px;">
                    <td class="ContentDividerHoriz_425"></td>
                </tr>
            </table>
            <table id="searchByEntityDataTable" cellpadding="0" cellspacing="0" border="0">
                <tr style="height: 26px;">
                    <td class="leftColumn">
                        @Html.LabelFor(model => model.EntityTypeID):
                    </td>
                    <td class="rightColumn">
                        @Html.DropDownListFor(model => model.EntityTypeID, new SelectList(Model.EntityTypes,"ID","Name"), new { id ="entityTypeDropDown", @class ="DropDown_220" })
                    </td>
                </tr>
                <tr style="height: 26px;">
                    <td class="leftColumn">
                        @Html.LabelFor(model => model.SearchField, new { id ="entityTypeSearchLabel"}):
                    </td>
                    <td class="rightColumn">
                        @Html.TextBoxFor(model => model.SearchField, new { id ="entityTypeSearchField", @class ="ui-widget TextField_220" })
                    </td>
                </tr>
                <tr style="height: 26px;">
                    <td class="leftColumn"></td>
                    <td class="rightColumn"></td>
                </tr>
            </table>
            <table cellpadding="0" cellspacing="0" border="0">
                <tr>
                    <td id="filterByEntityError" style="width: 375px;"></td>
                    <td align="right" style="width: 50px; padding-right: 75px;">
                       
                            <input type="submit" value="Search" />
                       
                    </td>
                </tr>
            </table>
        }
   

   
        @(Html.Telerik().Grid(Model.Users)
            .Name("Users").TableHtmlAttributes(new { style ="width: 870px;"})
            .Columns(columns => {
                columns.Bound(o => o.EntityTypeName).Title("Entity Type");
                columns.Bound(o => o.FirstName).Title("First Name");
                columns.Bound(o => o.LastName).Title("Last Name");
                columns.Bound(o => o.Username).Title("Username");
                columns.Template(
                    @<text>
                        @item.EmailAddress
                    </text>).Title("Email").HtmlAttributes(new { style ="text-align: center" }).HeaderHtmlAttributes(new { style ="text-align: center" });
                columns.Template(
                    @<text>
                         
                        @{
                            if (item.IsApproved) {
                                 
                            }
                            else {
                                 
                            }
                        }
                        @{
                            if (item.IsLockedOut) {
                                 
                            }
                             
                        }
                       
                    </text>).Title("Actions");
                columns.Bound(o => o.RowNumber).Hidden(true);
                columns.Bound(o => o.MembershipID).Hidden(true);
                columns.Bound(o => o.EntityTypeID).Hidden(true);
            })
            .Pageable(paging => paging.PageSize(10))
            .Sortable()
        )
        <span>Total Rows: </span> @Html.DisplayFor(model => Model.TotalRowCount)

        <p>

            @Html.ActionLink("Create New User","Create","Invitation")
       
</p>

我使用此行作为BeginForm使用此视图:

1
@using (Html.BeginForm("FilterByUserData","Admin", FormMethod.Post, new {model = Model}))

使用这个:

1
 @using (Html.BeginForm())

使用此Ajax脚本

1
2
3
4
5
6
7
8
9
$('#filterByUserButton').click(function () {
    $.ajax({
        url: '/Admin/FilterByUserData',
        type: 'POST',
        success: function (result) {
            alert(result);
        }
    });
});

使用HTML帖子的第一种方法它工作正常,但我需要使用ajax功能,所以第二种方法是我的麻烦

1)使用ajax调用,发布到操作的模型包含文本字段中的所有Null值,而不是我在表单上输入的值。该模型使用HTML方法发布

2)即使我可以让模型正确发布以便我有值搜索,如何将数据返回到网格,如何在验证失败时显示模型错误而不是将结果发送到UpdateTargetID?

3)能够将两个表单提交给控制器并将相同的结果返回到视图,即搜索结果

看起来我只能有1个UpdateTarget - 如果你从来没有错误就没问题......但是行为很糟糕,我需要在字段上显示验证错误,就像这是同步调用一样。因此,来自该操作的错误结果需要具有它自己的目标。

我想出了这个Ajax调用,该调用适用于不需要返回数据的操作,只需成功或错误消息。每个都加载到自己的div中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
$(function () {
    $('form').submit(function () {
        if ($(this).valid()) {
            $.ajax({
                url: this.action,
                type: this.method,
                data: $(this).serialize(),
                success: function (result) {
                    if (result.toString().indexOf("Success") == -1) {
                        $('#successDiv').hide();
                        $('#errorDiv').html('');
                        $('#errorDiv').fadeIn(100).append($('<ul />').append(result));
                    }
                    else {
                        $('#errorDiv').hide();
                        $('#successDiv').fadeIn(1000).html(result).fadeOut(6000);
                    }
                }
            });
        }
        return false;
    });
});

这些是处理搜索的操作(FilterByUserData操作不同,因为我试图找出如何获得正确的结果,我还没有正确地返回数据。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
    public ActionResult Search() {
        var model = new SearchUsersViewModel();
        return View(model);
    }

    [HttpPost]
    public ActionResult FilterByUserData(SearchUsersViewModel model) {
        var result = string.Empty;
        if (model.LastName != null || model.Username != null || model.EmailAddress != null) {
            var listOfMatchingUsers = SearchUserService.SearchByUserData(model.LastName, model.Username, model.EmailAddress);
            model = PrepareResultsModel(listOfMatchingUsers, model);
        }
        else {
            ModelState.AddModelError("","Last Name, Username or Email Address must be entered for search");
        }
        if (ModelState.IsValid)
            result ="Success: Thanks for your submission:" + model.Username;
        else {
            result = ModelState.SelectMany(item => item.Value.Errors).Aggregate(result, (current, error) => current + error.ErrorMessage);
        }
        return Content(result,"text/html");
    }

    [HttpPost]
    public ActionResult FilterByEntityData(SearchUsersViewModel model) {
        if(model.EntityTypeID > 0 &&  model.SearchField != null) {
            var listOfMatchingUsers = SearchUserService.SearchByEntityData(model.EntityTypeID, model.SearchField);
            model = PrepareResultsModel(listOfMatchingUsers, model);
        }
        else {
            var entityType = string.Empty;
            if(model.EntityTypeID == 2) entityType ="Lender";
            if (model.EntityTypeID == 3) entityType ="School";
            ModelState.AddModelError("", entityType +" name must be entered for search");
        }
        return View("Search", model);
    }

    private SearchUsersViewModel PrepareResultsModel(ICollection<SearchUserResultsDTO> listOfMatchingUsers, SearchUsersViewModel model) {
        if (listOfMatchingUsers.Count != 0) {
            model.Users = listOfMatchingUsers.Select(item => new UserEditViewModel(item)).ToList();
            model.TotalRowCount = model.Users.Count();
        }
        return model;
    }

如何获取ajax帖子的模型以使其成为我的行动?以及如何获得正确的模型,以便我的网格有结果?如果出现错误,我怎样才能以与验证相似的方式显示?

更新:@Shyju
我尝试了你的建议尝试将你的例子合并到我的代码中,但模型属性的值仍然是null并且没有被设置。这是我在ajax函数中所做的,请注意它与form.post方法不同:

1
2
3
4
5
6
7
8
9
10
$('#filterByUserButton').click(function () {
    $.ajax({
        url: '/Admin/FilterByUserData',
        type: 'POST',
        data: {LastName : $('#LastName').val(), Username : $('#Username').val(), EmailAddress : $('#EmailAddress').val()},
        success: function (result) {
            processResult(result);
        }
    });
});

我也试过这个:

1
2
3
4
5
6
7
$('form').submit(function() {
    alert("submitting");
    $.post('@Url.Action("FilterByUserData","Admin")', { LastName: $("#LastName").val(), UserName: $("#Username").val(), EmailAddress: $("#EmailAddress").val() },
        function(data) {
            alert(data);
    });
});

页面闪烁,第一个警告是它,但它从未达到第二个警报,从不击中控制器,所以看起来它甚至没有真正发布。
我也尝试了这个,但它也没有达到控制器动作:

1
2
3
4
5
6
7
8
9
10
11
12
$('#filterByUserButton').click(function () {
    alert("submitting");
    $.ajax({
        url: '/Admin/FilterByUserData',
        type: 'POST',
        data: {LastName : $('#LastName').val(), Username : $('#Username').val(), EmailAddress : $('#EmailAddress').val()},
        success: function (result) {
            alert(result);
            processResult(result);
        }
    });
});

我也尝试了上面的数据:省略了行,它将触发我的控制器动作但是再一次,被发送的模型在属性中具有空值。模型不是null,只是属性值。我在模型的下拉列表属性中有值,EntityTypes仍然显示4个值。所以发布该表单有一些东西,但表单值没有进入模型属性。

更新2

@Shyju我正在使用你的ajax代码:

1
2
3
4
5
6
7
8
9
$(function () {
    $('#SearchByUserForm').submit(function () {
        $.post('@Url.Action("FilterByUserData","Admin")', { LastName: $("#LastName").val(), UserName: $("#UserName").val(), EmailAddress: $("#EmailAddress").val() },
        function (data) {
            alert(data);
        });
        return false;
    });
});

我点击提交按钮后可以通过这个步骤,但它无法点击我的控制器的后期操作。我查看了为表单呈现的HTML,这是我看到的..这是不正确的:

1
<form action="/Admin/Search/SearchByUserForm" method="post">

正如您所看到的,这里的POST操作是错误的。控制器是正确的,但其余的是错误的。它应该发布到/ Admin / FilterByUserData。我确定这只是一个语法混乱,我在,我只是不确定我做错了什么。在标准形式中,我会这样做:

1
@using (Html.BeginForm("FilterByUserData","Admin", FormMethod.Post, new { model = Model })) {

哪个工作正常。但我无法将此表单签名与您的Ajax代码中的URL操作帖子结合使用。我试着只用身份证离开表格,但我得到了上面提到的问题:

1
@using (Html.BeginForm(new {@id ="SearchByUserForm"})) {

我认为这个问题来自于我的视图是通过点击我的控制器的搜索操作来呈现的,因此URL是/ Admin / Search但是视图上的表单需要发布到/ Admin / FilterByUserData和/ Admin / FilterByEntityData 。就像我上面说的,如果我用正确的签名显式创建Html.BeginFrom然后它可以工作,但它只是不是Ajax

更新3

@Shyju

我得到它的工作,问题肯定是表签名,我修改它,我可以成功地击中我的控制器动作,并且数据正在传递!感谢你的帮助!

这就是它的工作原理:

1
@using (Html.BeginForm(new {id ="SearchByUserForm", @controller ="Admin", @action ="FilterByUserData"})) {

当您在jquery帖子中传递数据时,请使用与属性名称相同的名称(viewmodel的名称,这是您的操作方法的参数)。 你会得到那里填充数据的对象。

1
2
3
4
5
6
7
8
('form').submit(function () {
    $.post('@Url.Action("Logon","Account")', { LastName : $("#username").val(),
                     UserName:   $("#password").val() },
                     EmailAddress:   $("#password").val() },  function (data) {

    //process the result and update the grid

});

编辑:由于OP说,它不起作用,我从头开始创建一个示例项目来验证这一点,它工作正常。
这是我的View看起来像

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js" type="text/javascript">

Index
<form id="frm1" action="Search">
LastName <input type="text" id="LastName" /><br />
UserName <input type="text" id="UserName" /><br />
Email Address <input type="text" id="EmailAddress" />
<input type="submit" value="go" />
</form>
<script type="text/javascript">
    $(function () {
        $('#frm1').submit(function () {
            $.post('@Url.Action("Search","Home")', { LastName: $("#LastName").val(),
                UserName: $("#UserName").val(),
                EmailAddress: $("#EmailAddress").val()
            }, function (data) {

                alert(data)
            });
            return false;
        });
    });

我收到邮件调用的动作方法是

1
2
3
4
public ActionResult Search(SearchUsersViewModel objVM)
{
   return View();
}

这是结果的屏幕截图

客户

enter image description here

控制器动作方法

enter image description here

您甚至可以使用jquery serialize()方法将表单发送到控制器操作。

http://api.jquery.com/serialize/