如何将复杂模型中的输入值从视图传递到控制器?

How can I pass input value in a complex Model from View to Controller?

我的场景是,在我的 View 上,我有多个字段用于输入数字,还有一个字段用于通过公式自动生成结果。我希望能够将这些值传递回我的 Controller,我将从那里计算并将结果 return 返回到 View,同时要计算的输入值仍然存在。我不在我的 Javascript 上执行此操作的原因是因为某些情况要求我与 database 中其他数据中的许多其他字段的值进行交互。我打算通过将一整套 ModelView 传递到 Controller 来做到这一点,并且我不想在输入输入字段时重新加载页面。到目前为止,这是我的两种方法:

使用Javascript Ajax:

var modelObject = @Html.Raw(Json.Serialize(Model));

这允许我仅在开头存储和传递 Base Model。我无法传递新的输入值。输入是否可以自动将它们的值存储在 Model 中,以便在类似于上述的代码中使用?

使用 Unobtrusive AJAXJavascript 激活提交操作:

function submit(){
    $('#formSubmit').submit();
    --OR--
    $('#btnSubmit').click();
}

<form id="formSubmit" data-ajax="true" asp-action="Action" method="POST">
    <input asp-for="Item.inputValue" onchange="submit()"/>
    <button id="btnSubmit" type="submit"></button>
</form>

单击时的按钮与 Unobtrusive AJAX 配合正常。但是 Javascript 激活提交事件不能。我的页面仍在重新加载。

我该走哪条路才正确?在哪一个中,我需要如何修复我的代码才能使它 运行 像我想要的那样?

Using Javascript Ajax:

var modelObject = @Html.Raw(Json.Serialize(Model));

This allow me to store and passing Base Model at the beginning only. I can't pass new input value. Is there away for the input to automatically store their value in Model to be used in the code similar to the above?

使用JQuery Ajax传递数据时,应使用serialize()方法序列化表单,然后将表单数据传递给控制器​​action方法。代码如下:

        $("#btnAjax").click(function () {
            // var data = $("#mainform").serialize(); //you could set a break point to check the value.
            $.ajax({
                url:"/Test/CreateProduct", // change the url to yours.
                method: "Post",
                data: $("#mainform").serialize(),
                success: function (response) {
                    //after getting the response, update the content.
                    $("#div_partial").html("");
                    $("#div_partial").html(response);  //
                },
                error: function (error) {
                    alert("error");
                }
            });
        });

Using Unobtrusive AJAX and Javascript to activate submit action:

function submit(){
    $('#formSubmit').submit();
    --OR--
    $('#btnSubmit').click();
}

<form id="formSubmit" data-ajax="true" asp-action="Action" method="POST">
    <input asp-for="Item.inputValue" onchange="submit()"/>
    <button id="btnSubmit" type="submit"></button>
</form>

The button when click works fine with Unobtrusive AJAX. But the javascript to activate the submit event can't. My page still reload.

使用jQuery Unobtrusive AJAX时,首先,请确保您在当前页面中添加了jQuery Unobtrusive AJAX引用,然后,确保您已在目标元素上激活不显眼 Ajax。

例如,使用下面的代码,点击提交按钮后,它会将mainform提交给ProductIndex action方法,然后更新div_partial内容:

    <form asp-action="ProductIndex" id="mainform" 
          data-ajax="true" 
          data-ajax-method="Post"
          data-ajax-update="#div_partial">
        <div asp-validation-summary="ModelOnly" class="text-danger"></div>
        <div id="div_partial"> 
            <partial name="_PVProduct.cshtml" data="@Model" />
        </div> 
        <div class="form-group">
            <input type="submit" value="Submit" class="btn btn-primary" /> 
        </div>
    </form>

有关使用 jQuery Unobtrusive AJAX 的更多详细信息,请参阅 this link

详细示例代码如下:

型号:

public class Item
{
    public int ItemId { get; set; }
    public string ItemDescription { get; set; } 
    public decimal ItemUnitPrice { get; set; }
    public decimal Quantity { get; set; }
}

public class ProductViewModel
{
    public string UserName { get; set; }
    public List<Item> Items { get; set; }
}

控制器:

    public IActionResult ProductIndex()
    {
        ProductViewModel newitem = new ProductViewModel()
        {
            Items = _repository.GetItemViewModels().Select(c => new Item() { ItemId = c.ItemId, ItemDescription = c.ItemDescription, Quantity = c.Quantity, ItemUnitPrice = c.ItemUnitPrice }).ToList()
        };


        return View(newitem);
    }
    // Unobtrusive AJAX Post method
    [HttpPost]
    public IActionResult ProductIndex(ProductViewModel product)
    {
        return PartialView("_PVProduct", product);
    }
    //JQuery Ajax Post method.
    [HttpPost]
    public IActionResult CreateProduct(ProductViewModel product)
    { 
        return PartialView("_PVProduct", product);
    }

PartialView(_PVProduct.cshtml):这里我使用局部视图来显示Model内容,用Ajax.

更容易更新内容
    @model WebApplication6.Models.ProductViewModel

        <div class="form-group">
            <label asp-for="UserName" class="control-label"></label>
            <input asp-for="UserName" class="form-control" />
            <span asp-validation-for="UserName" class="text-danger"></span>
        </div>
        <div class="form-group">
            <table class="table">
                <thead>
                    <tr>
                        <th>
                            ItemId
                        </th>
                        <th>
                            ItemDescription
                        </th>
                        <th>
                            ItemUnitPrice
                        </th>
                        <th>
                            Quantity
                        </th>
                        <th></th>
                    </tr>
                </thead>
                <tbody>
                    @for (var i = 0; i < Model.Items.Count(); i++)
                    {
                        <tr>
                            <td>
                                @Model.Items[i].ItemId
                                <input asp-for="Items[i].ItemId" type="hidden" />
                            </td>
                            <td>
                                @Model.Items[i].ItemDescription
                                <input asp-for="Items[i].ItemDescription" type="hidden" />
                            </td>
                            <td class="text-right">
                                <input asp-for="Items[i].ItemUnitPrice" type="text" />
                            </td>
                            <td class="text-right">
                                <input asp-for="Items[i].Quantity" type="text" />
                            </td>
                            <td class="text-right">
                                @(Model.Items[i].Quantity * Model.Items[i].ItemUnitPrice)
                            </td>
                            <td></td>
                        </tr>
                    }
                </tbody>
            </table>
        </div>

查看页面 ():

@model WebApplication6.Models.ProductViewModel
 
<div class="row">
    <div class="col-md-4">
        <form asp-action="ProductIndex" id="mainform" 
              data-ajax="true" 
              data-ajax-method="Post"
              data-ajax-update="#div_partial">
            <div asp-validation-summary="ModelOnly" class="text-danger"></div>
            <div id="div_partial"> 
                <partial name="_PVProduct.cshtml" data="@Model" />
            </div> 
            <div class="form-group">
                <input type="submit" value="Submit" class="btn btn-primary" />
                <input type="button" value="Ajax Submit" class="btn btn-primary" id="btnAjax" />
            </div>
        </form>
    </div>
</div>

在上面的查看页面最后,添加如下脚本: 这里我使用jQuery Unobtrusive AJAX CDN参考:

@section Scripts {
    @{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-ajax-unobtrusive/3.2.6/jquery.unobtrusive-ajax.min.js"></script>
    <script>
        $(function () {
            $("#btnAjax").click(function () {
                //var data = $("#mainform").serialize();
                $.ajax({
                    url:"/Test/CreateProduct", // change the url to yours.
                    method: "Post",
                    data: $("#mainform").serialize(),
                    success: function (response) {
                        //after getting the response, update the content.
                        $("#div_partial").html("");
                        $("#div_partial").html(response); 

                        //attach change event and then trigger the submit form action..
                        $(".table> tbody >tr").each(function (index, tr) {
                            $(tr).find("input[name$='Quantity']").change(function () {
                                //console.log($(this).val());
                                $("#btnAjax").click();
                            });
                        });
                    },
                    error: function (error) {
                        alert("error");
                    }
                });
            });
            //attach change event and then trigger the submit form action.
            $(".table> tbody >tr").each(function (index, tr) {
                $(tr).find("input[name$='Quantity']").change(function () {
                    //console.log($(this).val());
                    $("#btnAjax").click();
                });
            });
        })
    </script>
}

输出如下:

  • 提交按钮:使用 Unobtrusive AJAX 方法提交表单。
  • Ajax提交按钮:使用JQueryAjax提交表单。
  • 数量输入变化事件:触发Ajax按钮,然后提交表单。