【问题标题】:Ajax request being passed as a GET request instead of a PUT requestAjax 请求作为 GET 请求而不是 PUT 请求传递
【发布时间】:2019-01-11 23:14:50
【问题描述】:

我创建了一个表单,用户通过该表单输入数据,按下提交按钮后,数据作为 PUT Ajax 请求传递。问题是它实际上并没有作为 PUT 请求传递,而是在调查后发现它实际上是作为 GET 请求传递的,数据是查询字符串,而不是在 PUT 请求的主体参数中发送.

我尝试通过 firefox 调试 jquery 代码,但在提交调试器时不会暂停以跳过页面,而是发送一个 GET 请求,其中查询字符串作为 ajax 请求中 vm 变量中提供的数据传递.这是我的 HTML.cs 表单:

@model Auth.ViewModels.NewCustomerViewModel
@{
    ViewBag.Title = "New";
    Layout = "~/Views/Shared/_Layout.cshtml";
}

<h2>New Customer</h2>


<form id="idk">
    @Html.ValidationSummary(true, "Please fix the following errors: ")
    <div class="form-group">
        @Html.LabelFor(m => m.Customer.Name)
        @Html.TextBoxFor(m => m.Customer.Name, new { @class = "form-control", @id = "customername" })
        @Html.ValidationMessageFor(m => m.Customer.Name)
    </div>

    <div class="form-group">
        @Html.LabelFor(m => m.Customer.MembershipTypeId)
        @Html.DropDownListFor(m => m.Customer.MembershipTypeId, new SelectList(Model.MembershipTypes, "Id", "MembershipName"), "Select Membership Type", new { @class = "form-control", @id = "membershipname" })
        @Html.ValidationMessageFor(m => m.Customer.MembershipTypeId)
    </div>

    <div class="form-group">
        @Html.LabelFor(m => m.Customer.BirthDate)
        @Html.TextBoxFor(m => m.Customer.BirthDate, "{0:d MMM yyyy}", new { @class = "form-control", @id = "birthdate" })
        @Html.ValidationMessageFor(m => m.Customer.BirthDate)
    </div>

    <div class="checkbox">
        <label>
            @Html.CheckBoxFor(m => m.Customer.IsSubscribedToNewsletter, new { @id = "subscribename" }) Subscribe to Newsletter?
        </label>
    </div>

    <div class="checkbox">
        <label>
            @Html.CheckBoxFor(m => m.Customer.Irresponsible, new { @id = "irresponsiblename" }) Delinquent Person
        </label>
    </div>
    @Html.HiddenFor(m => m.Customer.Id, new { @id = "id" })
    @Html.AntiForgeryToken()
    <button type="submit" id="submit" class="btn btn-primary">Save</button>

</form>


@section scripts {
    @Scripts.Render("~/bundles/jqueryval")
    <script>
        $(document).ready(function () {
            $("#submit").on("click",function (event) {
                var vm = { id: $("#id").val(), Name: $("#customername").val(), IsSubscribedToNewsLetter: $("#subscribename").val(), MembershipTypeId: $("#membershipname").val(), BirthDate: $("#birthdate").val(), Irresponsible: $("#irresponsiblename").val(), Id: $("#id").val()  };


   $.ajax({
                url: "/api/Customers/UpdateCustomer",
                method: "PUT",
                data: {vm },
            success: function () {
                Location("customers/Index");
                //button.parents("tr").remove();
            }
        });
        });

        });



    </script>

}

这里是处理这个 PUT 请求的后端:

 [HttpPut]
        public IHttpActionResult UpdateCustomer(int id, CustomerDto customerDto)
        {
            if (!ModelState.IsValid)
                return BadRequest();
            var customerInDb = _context.Customer.SingleOrDefault(c => c.Id == id);
            if (customerInDb == null)
                return NotFound();
            Mapper.Map<CustomerDto, Customer>(customerDto, customerInDb);
            _context.SaveChanges();
            return Ok();

        }

我只是不知道为什么它没有作为 PUT 请求传递给后端,以及为什么数据作为查询字符串参数传递。我的期望是它将通过 PUT 请求传递数据并更新数据库中的各个字段

【问题讨论】:

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


    【解决方案1】:

    您通常喜欢以错误的格式发送数据,这会被意外地解释为具有不同参数的另一种方法(从不存在) - 或者导致数据无法将参数绑定到正确的数据类型。例如,您要发送以下数据:

    var vm = {
        id: 123
    };
    

    预期的 API 端点

    GET /account/update-customer/123 // OK 200
    

    发送的实际网址

    // Url encoded. This method expects an integer as parameter but string was passed.
    GET /account/update-customer/vm%5Bid%5D=123 // Internal Server Error 500
    

    因此,如果您是 sending them as form data,请从 vm 对象中删除花括号(因为它已经一个对象),以便 HTTP 正确地将它们烘焙到 URL 中,或者干脆让 jQuery serialize 为您处理数据,轻松无忧(您可能应该这样做)

    这里是完整的 sn-ps 操作,以及我的一些重构建议:

    您可能已经这样做了,但请使用Html.BeginForm,它允许您在稍后阶段(例如在 AJAX 调用中)以更易于维护的方式获取 API url。

    切换自

    <form id="idk">
      <div class="form-group">
        @Html.LabelFor(m => m.Customer.Name)
        @Html.TextBoxFor(m => m.Customer.Name, new { @class = "form-control", @id = "customername" })
        @Html.ValidationMessageFor(m => m.Customer.Name)
      </div>
    
      [...]
    

    收件人

    @using (Html.BeginForm("UpdateCustomer", "Account"))
    {
      <div class="form-group">
        @Html.LabelFor(m => m.Customer.Name)
        @Html.TextBoxFor(m => m.Customer.Name, new { @class = "form-control" })
        @Html.ValidationMessageFor(m => m.Customer.Name)
      </div>
    
      [...]
    
      <!-- No need for manually specifing the id here since it will be taken care of by the framework -->
      @Html.HiddenFor(m => m.Customer.Id)
    }
    

    Javascript 文件

    $("form#idk").submit(function (e) {
       e.preventDefault();
    
       //var vm = {
       //   id: $("#id").val(),
       //   Name: $("#customername").val(),
       //   IsSubscribedToNewsLetter: $("#subscribename").val(),
       //   MembershipTypeId: $("#membershipname").val(),
       //   BirthDate: $("#birthdate").val(),
       //   Irresponsible: $("#irresponsiblename").val(),
       //   Id: $("#id").val()
       //};
    
       // This one-liner should do the magic for you
       var vm = $(this).serialize();
    
      $.ajax({
        // Made available by the above Html.BeginForm().
        // This way, when you decide to change the URL later, you won't have to deal
        // with having to possibly update this in multiple places
        url: this.action,
    
        method: "PUT",
        data: vm,
        success: function (data) {
          // ...
        }
      });
    });
    

    希望对您有所帮助。

    【讨论】:

    • 你是一个救生员,非常感谢。还有 this.serialize 实际上是做什么的?为什么ajax请求中有this.action?
    • 其中的关键字this 实际上指的是表单元素本身,而action 指的是表单原生属性之一,它在后台保存了Html.BeginForm 指定的URL。 .serialize() 只是一个用于序列化表单输入的 jQuery 方法。无论如何,如果您发现此答案有帮助,您能否将其标记为已接受?
    【解决方案2】:

    我猜你的 jQuery 版本是 type 而不是methodsee here

    type (default: 'GET') Type: String 方法的别名。你应该使用 如果您使用的是 1.9.0 之前的 jQuery 版本,请键入。


     $.ajax({
         url: "/api/Customers/UpdateCustomer",
         type: "PUT",
         data: { vm },
         success: function () {
                Location("customers/Index");
                //button.parents("tr").remove();
            }
        });
    

    【讨论】:

    • 我不这么认为,因为我在同一个应用程序的其他 ajax 请求中尝试过方法,它们似乎工作正常。
    • 这只是一个猜测,如果是我,我会仔细检查我的 jQuery 版本……你可能已经尝试过方法:get(无论如何都是默认的)
    【解决方案3】:

    使用按钮类型按钮代替提交,表单提交默认采用GET方式

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-07
      • 2019-12-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多