如何通过包含表单数据但不单击提交按钮的 ajax 将视图模型发送到控制器

Posted

技术标签:

【中文标题】如何通过包含表单数据但不单击提交按钮的 ajax 将视图模型发送到控制器【英文标题】:How do I send a view model to the controller via ajax which includes form data but not by clicking the submit button 【发布时间】:2021-03-11 13:55:28 【问题描述】:

我正在开发一个为产品报价的 ASP.NET Core 2.1 Web 应用程序。我正在尝试通过 ajax 将视图模型发送到控制器,这将返回一个带有计算出的总报价的视图模型并将其显示在部分视图中。

我可以将模型发送到控制器,但模型只包含加载到视图中的默认值,并且没有任何表单输入值。我觉得我在这里错过了一些非常简单的东西。我尝试了很多选项,包括序列化表单,它将值输入控制器但错过了模型的其余部分。

下面的代码在调用函数时将模型发送到控制器(这是我想要的),但不包括输入到表单中的值。有没有办法实现这一点,还是整个事情都需要返工?

帮助我 Stack Overflow,你是我唯一的希望。

控制器

   [HttpPost]
    public ActionResult CalculateItemQuote(string jsonString)
    

        BifoldItemViewModel bifoldItemViewModel = JsonConvert.DeserializeObject<BifoldItemViewModel>(jsonString);

        // Do calculations and return view model to partial view.

        return PartialView("~/Views/Shared/_BifoldItemHeader.cshtml", bifoldItemViewModel);
    

脚本

函数 RefreshHeaderValue()

    var serModel =  '@Html.Raw(Json.Serialize(@Model))';
          console.log(serModel);
      $.ajax(
            url: '@Url.Action("CalculateItemQuote", "Quote")',
            type: 'POST',
            data:  jsonString: serModel ,
          dataType: 'json',
          traditional: true,
            contentType: 'application/x-www-form-urlencoded; charset=UTF-8',
            success: function (data) 
                $("#bifoldHeaderPartial").html(data);
                $('#bifoldHeaderPartial').show();
            
        );
    ;

查看

                <div class="form-group col-md-6">
                    <label asp-for="thisBifoldItem.Width"></label>
                    <input asp-for="thisBifoldItem.Width" class="form-control" autocomplete="nay" />
                    <span asp-validation-for="thisBifoldItem.Width" class="text-danger"></span>
                </div>

                <div class="form-group col-md-6">
                    <label asp-for="thisBifoldItem.Height"></label>
                    <input asp-for="thisBifoldItem.Height" class="form-control" autocomplete="nay" />
                    <span asp-validation-for="thisBifoldItem.Height" class="text-danger"></span>
                </div>


                <div class="form-group col-md-4">
                    <label asp-for="DoorQuantityOptions" class="control-label">How Many Doors?</label>
                    <select asp-for="SelectedDoorQuantity" id="DoorQuantityOptions" class="form-control" asp-items="@Model.DoorQuantityOptions">
                        <option value="" selected disabled>-- Select --</option>
                    </select>
                </div>

=========== 更新解决方案==========

感谢 kbaccouche 将我推向正确的方向。以下现在有效

控制器


[HttpPost] public ActionResult CalculateItemQuote(BifoldItemViewModel bifoldItemViewModel)

        //Do stuff here

        return PartialView("~/Views/Shared/_BifoldItemHeader.cshtml", bifoldItemViewModel);
    

脚本


函数 RefreshHeaderValue()

      $.ajax(
            url: '@Url.Action("CalculateItemQuote", "Quote")',
            type: 'POST',
          data: $("#myForm").serialize(),
          dataType: 'json',
          traditional: true,
            contentType: 'application/x-www-form-urlencoded; charset=UTF-8',
            success: function (data) 
                $("#bifoldHeaderPartial").html(data);
                $('#bifoldHeaderPartial').show();
            
        );
    ;

【问题讨论】:

ASP.NET MVC 有 ModelBinders 可以为你做 JSON 转换。所以你可以有一个BifoldItemViewModel 类型参数到CalculateItemQuote。您需要根据页面上的输入创建自己的(或更新现有的)serModel 感谢您的回复。我目前正在阅读 ModelBinding 文档以寻求解决方案。我已经用视图中的一些数据更新了我的问题。我不确定从页面上的输入更新 serModel 是什么意思,你的意思是像@kbaccouche 中的示例一样单独分配它们 【参考方案1】:

我尝试使用您的代码创建一个示例应用程序,并使用标准 MVC 模型绑定让它工作。这是代码

控制器

public class QuoteController : Controller

    // POST: Quote/Create
    [HttpPost]
    public ActionResult CalculateItemQuote(ProductForm model)
    
        var bifoldItemViewModel = new BifoldItemViewModel();
        return PartialView("~/Views/Shared/_BifoldItemHeader.cshtml", bifoldItemViewModel);
    


public class ProductForm

    public string ProductId  get; set; 
    public string Quantity  get; set; 


public class BifoldItemViewModel



HTML + javascript

@
   ViewData["Title"] = "Home Page";
 

<form>
  <input id="ProductId" name="ProductId" type="text" />
  <input id="Quantity" name="Quantity" type="text" />
  <a id="submitForm" class="btn">Submit</a>
</form>

<div class="text-center">
  <h1 class="display-4">Welcome</h1>
  <p>Learn about <a href="https://docs.microsoft.com/aspnet/core">building Web apps with ASP.NET Core</a>.</p>
</div>

<div id="bifoldHeaderPartial">

</div>

@section Scripts
  <script type="text/javascript">
    $('a#submitForm').click(function () 
    $.ajax(
        url: '@Url.Action("CalculateItemQuote", "Quote")',
        type: 'POST',
        data: 
            'ProductId': $('#ProductId').val(),
            'Quantity': $('#Quantity').val()
        ,
      dataType: 'json',
      traditional: true,
        contentType: 'application/x-www-form-urlencoded; charset=UTF-8',
        success: function (data) 
            $("#bifoldHeaderPartial").html(data);
            $('#bifoldHeaderPartial').show();
        
    );
  );
 </script>

【讨论】:

感谢您的回复,我可以看到这是如何工作的,但看不到如何使我的模型与 ajax 请求相协调。我用一些视图编辑了我的问题,它显示了输入值如何绑定到表单中的模型。根据您的示例,我应该以相同的方式分配这些值吗? 澄清一下,在提交表单时,它正确绑定了所有模型值,只是在我使用 ajax 请求发布时不绑定值。 var serModel = '@Html.Raw(Json.Serialize(@Model))'; 这一行中,您将服务器端代码与客户端代码混合在一起。我不认为这是一个好的做法,或者它甚至行不通。您可以手动创建要发送到服务器的对象(就像我一样),也可以将所有输入放在
中,然后在data 中像这样序列化它: data: $(" form").serialize()
我一直在绕过解决方案一段时间,而您却给了我缺失的部分。我以前使用过 data: $("form").serialize() 但控制器参数作为 json 的字符串。我现在已将参数更改为 viewmodel 并传入序列化表单正在工作。非常感谢你。我的头痛现在可能会消失! 乐于助人:)

以上是关于如何通过包含表单数据但不单击提交按钮的 ajax 将视图模型发送到控制器的主要内容,如果未能解决你的问题,请参考以下文章

单击提交按钮后的 AJAX 定期轮询数据

Rails 5 ajax 表单:单击 Ajax 中的 2 个单选按钮之一提交表单

来自ckeditor textarea的ajax表单提交值之后没有通过邮件发送

如何使用 ajax 提交带有 3 个提交按钮的表单而不重定向到 Laravel 中的表单操作 url?

如何在功能测试期间单击不是表单提交按钮的按钮

如何在 ASP.NET MVC 中通过 Ajax 提交表单?