将Ajax请求作为GET请求而不是PUT请求传递

时间:2019-01-11 23:14:50

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

我创建了一个表单,用户可以通过该表单输入数据,并在按下“提交”按钮之后,将数据作为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请求传递数据并更新数据库中的各个字段

3 个答案:

答案 0 :(得分: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为您提供数据,并且轻松(您可能应该这样做)

以下是完整的摘要,以及我的一些重构建议:

您可能已经在执行此操作,但是使用Html.BeginForm可以让您在以后的阶段(例如在AJAX调用中)以更易于维护的方式获取API网址。

切换

<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) {
      // ...
    }
  });
});

enter image description here 希望有帮助。

答案 1 :(得分:0)

我的猜测是您的jQuery版本<1.9。在这种情况下,您需要使用/** * Uncle Bobs builder example for constructors with many required & optional parameters, * realized by lombok. * */ @AllArgsConstructor(access=AccessLevel.PRIVATE) // Let lombok generate private c-tor with all parameters, as needed by @Builder. @Builder( builderClassName="Builder", // Cosmetic. Without this option, the builder class would have the name NutritionFactsBuilder. toBuilder=true // Enabling creation of a builder instance based on a main class instance: NutritionFacts. ) public class NutritionFacts { // Required parameters private int servingSize; private int servings; // Optional parameters private int calories; private int fat; private int sodium; private int carbohydrate; /** * A builder method demanding required parameters. */ public static Builder builder(int servingSize, int servings) { return new NutritionFacts(servingSize, servings).toBuilder(); } /** * eclipse-created C-tor with required parameters. * Can be public for instantiating, but doesn't have to. */ public NutritionFacts(int servingSize, int servings) { super(); this.servingSize = servingSize; this.servings = servings; } public static void main(String[] args) { NutritionFacts cocaCola = NutritionFacts.builder(240, 8) .calories(100) .sodium(35) .carbohydrate(27) .build(); } } 而不是typesee here

  

type(默认:'GET')类型:String方法的别名。你应该用   如果您使用的是1.9.9.0之前的jQuery版本,则键入。


method

答案 2 :(得分:0)

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