jquery ajax表单提交不会绑定mvc 4中的复杂模型

时间:2015-03-12 15:00:39

标签: jquery ajax asp.net-mvc asp.net-mvc-4

我需要通过ajax提交的表单是提交但不绑定到模型。

我的jquery源代码如下

function SubmitForm() {
console.log($("#PackageSubscription").serialize());
$.ajax({
    url: '/HelpDesk/CalculateCost',
    cache: false,
    processData: false,
    data: $("#PackageSubscription").serialize(),
    type: 'POST',
    success: function (data) {
    }
});

}

当我通过提交按钮使用标准mvc submit(同步)时,完全相同的表单会绑定。

有趣的是,控制台日志具有所有表单值,并且当我们同步提交表单时它们完全相同(来自ajax调用的控制台日志字符串和来自fiddler请求检查器的表单值完全相同)

一些示例数据就像

MemberId=12345678
&SitePackges[0].SiteId=50
&SitePackges[0].SizeIndicator=2
&SitePackges[0].LstPackageDisplayItems[0].PackageId=4
&SitePackges[0].LstPackageDisplayItems[0].Name=PAT and Emergency Lighting 
&SitePackges[0].LstPackageDisplayItems[0].IsSubscribed=True
&SitePackges[0].LstPackageDisplayItems[0].LastServiceDate=
&SitePackges[0].LstPackageDisplayItems[0].ProposedDate=
&SitePackges[0].LstPackageDisplayItems[1].PackageId=6
&SitePackges[0].LstPackageDisplayItems[1].Name=Fire Alarm and Extinguishers
&SitePackges[0].LstPackageDisplayItems[1].IsSubscribed=True
&SitePackges[0].LstPackageDisplayItems[1].LastServiceDate=
&SitePackges[0].LstPackageDisplayItems[1].ProposedDate=

我的viewmodel看起来像

public class PpmTypePackageSubscriptionModel
{        
    public int MemberId { get; set; }
    public DateTime TimeStamp { get; set; }
    public List<SitePackage> SitePackges { get; set; }
    public double TotalCost { get; set; }

    public PpmTypePackageSubscriptionModel()
    {
        SitePackges=new List<SitePackage>();
    }
}

public class SitePackage
{
    public int SiteId { get; set; }
    public int SizeIndicator { get; set; } 
    public string Site { get; set; }

    public List<PackageDisplayItem> LstPackageDisplayItems { get; set; }

    public SitePackage()
    {
        LstPackageDisplayItems=new List<PackageDisplayItem>();

    }

}

见下面的视图标记

@using Booker.WebUI.Models
@model PpmTypePackageSubscriptionModel
@using (@Html.BeginForm("CalculateCost", "HelpDesk", FormMethod.Post, new { @class = "form", id = "PackageSubscription", name = "PackageSubscription" }))
{
@Html.AntiForgeryToken()
@Html.HiddenFor(x => x.MemberId)
<table class="table table-responsive table-condensed table-hover table-striped">
    @for (int i = 0; i < Model.SitePackges.Count; i++)
    {
        <tr>
            <td class="siteHeading">
                @Html.HiddenFor(x => x.SitePackges[i].SiteId) @Html.DisplayFor(x => x.SitePackges[i].Site)
                @Html.HiddenFor(x => x.SitePackges[i].SizeIndicator) @Html.DisplayFor(x => x.SitePackges[i].SizeIndicator)
            </td>
        </tr>
        <tr>
            <th class="col-sm-3">
                Name
            </th>
            <th class="col-sm-2">
                Subscribe
            </th>
            <th class="col-sm-2">
                Last Service Date If Known
            </th>
            <th class="col-sm-2">
                Proposed Date
            </th>
        </tr>

        for (int j = 0; j < Model.SitePackges[i].LstPackageDisplayItems.Count; j++)
        {
            <tr>
                <td>
                    @Html.HiddenFor(x => x.SitePackges[i].LstPackageDisplayItems[j].PackageId)
                    @Html.HiddenFor(x => x.SitePackges[i].LstPackageDisplayItems[j].Name)
                    @Html.DisplayFor(x => x.SitePackges[i].LstPackageDisplayItems[j].Name)
                </td>
                <td>
                    @Html.RadioButtonFor(x => x.SitePackges[i].LstPackageDisplayItems[j].IsSubscribed, true, new { @class = "pull-left " })<label class="pull-left">Yes&nbsp;&nbsp;</label>
                    @Html.RadioButtonFor(x => x.SitePackges[i].LstPackageDisplayItems[j].IsSubscribed, false, new { @class = "pull-left" })<label class="pull-left">No</label>
                </td>
                <td>
                    @Html.TextBoxFor(x => x.SitePackges[i].LstPackageDisplayItems[j].LastServiceDate, "{0:d MMM yyyy}", new { @class = "jquery_datepicker form-control", autocomplete = "off" })
                </td>
                <td>
                    @Html.TextBoxFor(x => x.SitePackges[i].LstPackageDisplayItems[j].ProposedDate, "{0:d MMM yyyy}", new { @class = "jquery_datepicker form-control", autocomplete = "off" })
                </td>
            </tr>
        }

    }
</table>

<div class="row">
  <div class="col-sm-3"><p>Parking Availability</p></div>
    <div class="col-sm-5">
        <select id="ParkingAvailability" class="form-control" name="ParkingAvailability">
            <option value="1">Free Carpark</option>
            <option value="2">Paid Carpark</option>
        </select>
    </div>
</div>
<div class="row">
    <div class="col-sm-3"><p>Access Time</p></div><div class="col-sm-5"> <input class="form-control" name="SiteContactEmail" value="0900-1500 MonSat">
</div
 </div>
<div class="row">
    <div class="col-sm-3">
        <input class="btn btn-primary" @*type="submit"*@ onclick="SubmitForm(); return false;" value="Calculate Cost" />
    </div>
    <div class="col-sm-5">
        <span id="totalCost" class="hide form-control"></span>
    </div>
</div>

<div class="row">
    <div class="col-sm-5 col-sm-offset-3">
        <input class="btn btn-success" type="submit" value="Submit For Approval" />
        <input class="btn btn-danger" type="submit" value="Cancel Signup" />
    </div>
</div>

}

我的主视图有以下标记

<div id="tabs">
        <ul>
            <li><a href="#tabs-1">Member Sites </a></li>
            <li><a href="#tabs-2">Services and Packages</a></li>

        </ul>
        <div id="tabs-1">
            @Html.Partial("_MemberSites")
        </div>
        <div id="tabs-2">
            @Html.Action("GetAllPpmTypePackages", new { @id = @Model.MemberNumber })
        </div>

</div>

我的行动方法看起来像这样

    [HttpGet]
    public ActionResult GetAllPpmTypePackages(int id)
    {
      // Processing to create the viewmodel and pass to view
    }
    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult CalculateCost(PpmTypePackageSubscriptionModel ppmTypePackageSubscriptionModel)
    {
    // Processing
    }

3 个答案:

答案 0 :(得分:0)

如果我理解正确,表单不会更新,因为您没有对从ajax响应中收到的数据做任何事情。

您应该在ajax成功函数中绑定结果。 Ajax是异步的,因此数据被发布,但响应不一定立即。当成功接收到响应(没有超时或连接丢失等)时,ajax调用将转到success函数,并且在您的情况下,响应数据将存储在变量“data”中。

尝试执行以下操作:

function SubmitForm() {
console.log($("#PackageSubscription").serialize());
$.ajax({
    url: '/HelpDesk/CalculateCost',
    cache: false,
    processData: false,
    data: $("#PackageSubscription").serialize(),
    type: 'POST',
    success: function (data) {
        alert(data); // This will only show the response for you, use for debugging only
        $("#MemberId").value(data.MemberId);
    }
});

答案 1 :(得分:0)

从ajax中删除processData:false。然后它肯定会与你的模型绑定。请阅读以下内容:

processData(默认值:true) 类型:布尔值 默认情况下,作为对象传入数据选项的数据(技术上,不是字符串)将被处理并转换为查询字符串,适合默认的内容类型&#34; application / x-www-form -urlencoded&#34 ;.如果要发送DOMDocument或其他未处理的数据,请将此选项设置为false。

答案 2 :(得分:0)

这可能是serialize()函数的问题。

尝试使用JSON.stringify。

<script type="text/javascript">
function OnBtnSubmitClick(s, e) {
    var item1 = SecurityCode.GetText();
    var item2 = SecurityCoderMnem.GetText();
    var item3 = SecurityRegNum.GetText();
    var item4 = SecurityIsin.GetText();
    var item5 = document.getElementById("DocOrderSecurityOut_Id").value;
    var item6 = document.getElementById("IsEdit").value;

    var jsmodel = {
        DocOrderSecurityOut: {
            SecurityCode: item1,
            SecurityCoderMnem: item2,
            SecurityRegNum: item3,
            SecurityIsin: item4,
            Id: item5
        },
        IsEdit: item6
    };

    $.ajax({
        url: '@Url.Action("AjaxForm", "DocOrderSecurityOut")',
        data: JSON.stringify(jsmodel),
        dataType: 'html',
        contentType: "application/json; charset=utf-8",
        type: "POST",
        beforeSend: function () { loadingPanel.Show(); },
        complete: function () { loadingPanel.Hide(); },
        error: function (x, status, error) {
            alert("Error code: " + x.status + '\n' +
                "State: " + status + ". More info: " + error);
        },
        success: function (response) {
            $("#container").html(response);
        }
    });
}

控制器:

[HttpPost]
    public ActionResult AjaxForm(DocOrderSecurityOutViewModel model)
    {
        // magic
    }

在Global.asax中:

        ValueProviderFactories.Factories.Add(
            new JsonValueProviderFactory());