使用目标 AJAX 和 ASP 将复杂模型传递给控制器

Posted

技术标签:

【中文标题】使用目标 AJAX 和 ASP 将复杂模型传递给控制器【英文标题】:Passing complex model to controller using targeted AJAX and ASP 【发布时间】:2019-01-18 06:37:03 【问题描述】:

我正在尝试将模型传递给 ASP.NET 中的控制器。有两种方法可以做到这一点:使用 Ajax.BeginForm 和使用 JQuery。我已经尝试过这两种技术。我更愿意让 Ajax.BeginForm 工作,但我对 JQuery 的运气更好。

我的页面提供了一个存储在 KnowledgeTransfer 模型中的职责列表,这些职责将由 KnowledgeTransfer 控制器编辑和保存。用户编辑并单击“AddKnowledgeTransfer”按钮以将模型发送到控制器(未显示),该控制器返回部分视图。部分视图是要完成和提交的较大调查表中的一个问题。

一些要求:我的表单是较大表单中的部分视图,嵌套,所以我必须针对正确的 Ajax 和控制器方法,而不是提交整个页面。 (我读到这可能是不可能的?我已经能够接近 jQuery。如果不可能,我可以提交只有一个层次结构的表单吗?)我的另一个要求是我必须自动拉取整个 KnowledgeTransfer 模型。模型中有数百个属性,所以我需要将它们全部提取出来,而不是像某些示例所示的那样列出它们。

这里是 Ajax.BeginForm 技术:

    @model KnowledgeTransfer

    <partial name="_MainResponsibilities" />


    @using (Ajax.BeginForm("UpdateMainResponsibilities2",
            "KnowledgeTransfer",
            null,
        new AjaxOptions()
        
            HttpMethod = "POST",
            InsertionMode = InsertionMode.Replace,
            UpdateTargetId = "mainResponsibilitiesList"
        ,
        new  id = "MainResponsibilitiesForm" ))
        

    <div class="form-group" id="mainResponsibilitiesList">
        <table id="ResponsibilitiesTable">
            <thead>
                <tr>
                    <th class="col-sm-5">
                        @html.LabelFor(m => m.MainResponsibilities[0].Responsibility)
                    </th>
               </tr>
            </thead>
            <tbody>
                @for (int i = 0; i < Model.MainResponsibilities.Count; i++)
                
                    <tr style="border-bottom:thin">
                        <td>
                            @Html.TextAreaFor(m => m.MainResponsibilities[i].Responsibility, new  id="responsibility_" + i, @style = "width:90%; margin:auto; border-style:none;" )
                        </td>      
                    </tr>
                
            </tbody>
        </table>
    </div>

    <button class="btn col-sm-2" value="Create" type="button" name="MainReponsibilities" onclick="document.getElementById('MainResponsibilitiesForm').submit();" id="AddResponsibility" title="Add Responsibility"><i class="fa fa-plus"></i>Add Responsibility</button>

    

此代码的问题是按钮找不到 MainResponsibilitiesForm ID,因此无法提交。

现在介绍第二种 jQuery 技术:

@model KnowledgeTransfer

<partial name="_MainResponsibilities" />

<div class="form-group" id="mainResponsibilitiesList">
    <table id="ResponsibilitiesTable">
        <thead>
            <tr>
                <th class="col-sm-5">
                    @Html.LabelFor(m => m.MainResponsibilities[0].Responsibility)
                </th>
        </thead>
        <tbody>
            @for (int i = 0; i < Model.MainResponsibilities.Count; i++)
            
                <tr >
                    <td>
                        @Html.TextAreaFor(m => m.MainResponsibilities[i].Responsibility)
                    </td>                    
                </tr>
            
        </tbody>
    </table>
</div>

<button class="btn col-sm-2" value="Create" type="button" id="AddResponsibility2" title="Add Responsibility">Add Responsibility</button>

<script>
    $("#AddResponsibility2").click(function () 
            var model = @Html.Raw(Json.Encode(Model));
            var url = "@Url.Action("UpdateMainResponsibilities2", "KnowledgeTransfer")";

            $.ajax(
                type: "POST",
                url: url,
                data: JSON.stringify(model),
                contentType: "application/json",
                success: function () 
                    location.reload();
                
            );
        )
</script>

使用 JQuery,我可以使用 var model = @Html.Raw(Json.Encode(Model)); 拉取模型,但这会调用服务器并从数据库更新模型,而不是从客户端更改的模型。所以也许我可以使用 Json.Encode() 来拉模型,然后编辑 JSON 对象来更新值?这似乎没有必要。使用 JSON 也可能很困难,因为我必须遍历结构以识别每个元素。我可能还需要动态标记 HTML 中的元素以选择它们。

我应该使用 Angular,哈哈。但是这个应用程序在其他任何地方都没有使用它,所以我在这里。

如果您对如何改进这篇文章有任何建议,请告诉我。感谢您的帮助。

【问题讨论】:

您为什么更喜欢Ajax.BeginFor()? - 它实际上已过时,已从 asp-net-core mvc 中删除,并且 mvc 团队不再推荐。并且嵌套表单是无效的 html 并且不受支持。 很难理解您的问题是什么,因为您没有显示任何与嵌套表单相关的代码。但是为什么你在成功回调中有location.reload(); - ajax 的全部意义在于保持在同一页面上,所以使用它根本没有意义(而且只会降低性能) 我正在学习 MVC。我不知道 Ajax.BeginFor 已经过时了。 jQuery 提交算不算?从技术上讲,它没有包装在表单中,所以它是有效的? MS 已过时,不再推荐。 jQuery submit count 是什么意思(你指的是什么'count'?为什么要发回原始的未编辑模式?完全不清楚你想在这里做什么。 【参考方案1】:

将模型传递给控制器​​的方式使用ID参数。

<tbody>
            @for (int i = 0; i < Model.MainResponsibilities.Count; i++)
            
                <tr >
                    <td>
                        @Html.TextAreaFor(m => m.MainResponsibilities[i].Responsibility, newid="responsibility-" + 1)
                    </td>                    
                </tr>
            
        </tbody>

我从数据库中拉取模型,在客户端重写模型值...

<script>
var model = @Html.Raw(Json.Encode(Model));

function MainResponsibilitiesLoop(callback) 
    for (i = 0; i < model.MainResponsibilities.length; i++) 
        var thisResponsibility = document.getElementById("responsibility_" + i);
        thisResponsibility = thisResponsibility.value;


model.MainResponsibilities[i].Responsibility = thisResponsibility;
</script>

然后我使用 AJAX 调用将更新的模型保存到服务器。

<script>
function SaveOverview(callback) 
    var url = "@Url.Action("UpdateMainResponsibilities", "ResponsibilitiesController")";
    $.ajax(
        type: "POST",
        url: url,
        data: JSON.stringify(model),
        contentType: "application/json",
        success: function () 
            callback();
            
        
    )

</script>

【讨论】:

以上是关于使用目标 AJAX 和 ASP 将复杂模型传递给控制器的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 AJAX JQuery ASP .NET MVC 4 将 FormCollection 和文件传递给控制器

使用 Jquery/Ajax 将模型传递给控制器

如何使用 json 将复杂类型传递给 ASP.NET MVC 控制器

将多个参数从 ajax post 传递到 asp.net mvc 控制器

ASP.NET MVC 3 - 通过ajax无法正常传递额外参数以及模型到操作

如何从 jQuery ajax 调用将复杂对象传递给 ASP.NET WebApi GET?