Ajax 请求作为 GET 请求而不是 PUT 请求传递
Ajax request being passed as a GET request instead of a PUT request
我创建了一个表单,用户通过该表单输入数据,按下提交按钮后,数据作为 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 版本是 < 1.9。如果是这种情况,您需要使用 type
而不是 method
、see here:
type (default: 'GET') Type: String An alias for method. You should use
type if you're using versions of jQuery prior to 1.9.0.
$.ajax({
url: "/api/Customers/UpdateCustomer",
type: "PUT",
data: { vm },
success: function () {
Location("customers/Index");
//button.parents("tr").remove();
}
});
您大多喜欢以错误的格式发送数据,这会意外地被解释为具有不同参数(从不存在)的另一种方法——或者导致无法将参数绑定到正确的数据类型。例如,您要发送以下数据:
var vm = {
id: 123
};
预期API端点
GET /account/update-customer/123 // OK 200
实际URL发送
// 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, remove the curly braces from the vm
object (since it already is an object anyway) for HTTP to correctly bake them into the URL, or simply let jQuery serialize
数据适合您并且无忧无虑 (您可能应该这样做)。
下面是完整的代码片段,加上我的小重构建议:
您可能已经这样做了,但是使用 Html.BeginForm
可以让您在后期以更易于维护的方式获得 API url(例如在 AJAX 电话)。
切换自
<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) {
// ...
}
});
});
希望对您有所帮助。
使用button类型的button代替submit,Form submit默认采用GET方法
我创建了一个表单,用户通过该表单输入数据,按下提交按钮后,数据作为 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 版本是 < 1.9。如果是这种情况,您需要使用 type
而不是 method
、see here:
type (default: 'GET') Type: String An alias for method. You should use type if you're using versions of jQuery prior to 1.9.0.
$.ajax({
url: "/api/Customers/UpdateCustomer",
type: "PUT",
data: { vm },
success: function () {
Location("customers/Index");
//button.parents("tr").remove();
}
});
您大多喜欢以错误的格式发送数据,这会意外地被解释为具有不同参数(从不存在)的另一种方法——或者导致无法将参数绑定到正确的数据类型。例如,您要发送以下数据:
var vm = {
id: 123
};
预期API端点
GET /account/update-customer/123 // OK 200
实际URL发送
// 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, remove the curly braces from the vm
object (since it already is an object anyway) for HTTP to correctly bake them into the URL, or simply let jQuery serialize
数据适合您并且无忧无虑 (您可能应该这样做)。
下面是完整的代码片段,加上我的小重构建议:
您可能已经这样做了,但是使用 Html.BeginForm
可以让您在后期以更易于维护的方式获得 API url(例如在 AJAX 电话)。
切换自
<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) {
// ...
}
});
});
使用button类型的button代替submit,Form submit默认采用GET方法